From 8401e2edf77097bb6ac6ddac4aa7fb1aecd8e01a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 16 Jul 2020 10:11:13 +0200 Subject: [PATCH 0001/1494] drm/radeon: stop using TTM_MEMTYPE_FLAG_MAPPABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver doesn't expose any not-mapable memory resources. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/378239/ --- drivers/gpu/drm/radeon/radeon_ttm.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 54af06df865ba..b474781a0920d 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -76,7 +76,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: /* System memory */ - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = 0; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; break; @@ -84,7 +84,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = 0; #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { if (!rdev->ddev->agp) { @@ -92,8 +92,6 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, (unsigned)type); return -EINVAL; } - if (!rdev->ddev->agp->cant_use_aperture) - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -103,8 +101,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_VRAM: /* "On-card" video ram */ man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; @@ -394,7 +391,6 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; struct radeon_device *rdev = radeon_get_rdev(bdev); mem->bus.addr = NULL; @@ -402,8 +398,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_ mem->bus.size = mem->num_pages << PAGE_SHIFT; mem->bus.base = 0; mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; + switch (mem->mem_type) { case TTM_PL_SYSTEM: /* system memory */ -- GitLab From 902d77f3568a9f35493e1ebcfe25ba32cd3489e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 16 Jul 2020 10:28:04 +0200 Subject: [PATCH 0002/1494] drm/amdgpu: stop using TTM_MEMTYPE_FLAG_MAPPABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver does support some not-mapable resources, but those are already handled correctly in the switch/case statement in the code. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/378243/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 44fa8bc49d18f..0dd5e802091d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -84,7 +84,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: /* System memory */ - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = 0; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; break; @@ -93,13 +93,12 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->func = &amdgpu_gtt_mgr_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = 0; break; case TTM_PL_VRAM: /* "On-card" video ram */ man->func = &amdgpu_vram_mgr_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED | - TTM_MEMTYPE_FLAG_MAPPABLE; + man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; @@ -796,7 +795,6 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, */ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct drm_mm_node *mm_node = mem->mm_node; @@ -805,8 +803,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_ mem->bus.size = mem->num_pages << PAGE_SHIFT; mem->bus.base = 0; mem->bus.is_iomem = false; - if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) - return -EINVAL; + switch (mem->mem_type) { case TTM_PL_SYSTEM: /* system memory */ -- GitLab From 9fadd6d1e2977bbd449d4fb99cde41ed6f71f668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 16 Jul 2020 14:02:08 +0200 Subject: [PATCH 0003/1494] drm/ttm: remove TTM_MEMTYPE_FLAG_MAPPABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used any more. And it is bad design to use a TTM flag to do a check inside a driver. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/378245/ --- include/drm/ttm/ttm_bo_driver.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 71b195e78c7cf..9b251853afe25 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -46,7 +46,6 @@ #define TTM_MAX_BO_PRIORITY 4U #define TTM_MEMTYPE_FLAG_FIXED (1 << 0) /* Fixed (on-card) PCI memory */ -#define TTM_MEMTYPE_FLAG_MAPPABLE (1 << 1) /* Memory mappable */ struct ttm_mem_type_manager; -- GitLab From 4922f1bcad1a001dc6379cfe5196f3862c6107c6 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Wed, 22 Jul 2020 09:40:11 +0800 Subject: [PATCH 0004/1494] drm/amdgpu: expand sienna chichlid reg access support Added dedicated 64bit reg read/write support Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index ea69ae76773e8..74d02d270d342 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -97,6 +97,49 @@ static void nv_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); } +static u64 nv_pcie_rreg64(struct amdgpu_device *adev, u32 reg) +{ + unsigned long flags, address, data; + u64 r; + address = adev->nbio.funcs->get_pcie_index_offset(adev); + data = adev->nbio.funcs->get_pcie_data_offset(adev); + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + /* read low 32 bit */ + WREG32(address, reg); + (void)RREG32(address); + r = RREG32(data); + + /* read high 32 bit*/ + WREG32(address, reg + 4); + (void)RREG32(address); + r |= ((u64)RREG32(data) << 32); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +static void nv_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) +{ + unsigned long flags, address, data; + + address = adev->nbio.funcs->get_pcie_index_offset(adev); + data = adev->nbio.funcs->get_pcie_data_offset(adev); + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + /* write low 32 bit */ + WREG32(address, reg); + (void)RREG32(address); + WREG32(data, (u32)(v & 0xffffffffULL)); + (void)RREG32(data); + + /* write high 32 bit */ + WREG32(address, reg + 4); + (void)RREG32(address); + WREG32(data, (u32)(v >> 32)); + (void)RREG32(data); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; @@ -673,6 +716,8 @@ static int nv_common_early_init(void *handle) adev->smc_wreg = NULL; adev->pcie_rreg = &nv_pcie_rreg; adev->pcie_wreg = &nv_pcie_wreg; + adev->pcie_rreg64 = &nv_pcie_rreg64; + adev->pcie_wreg64 = &nv_pcie_wreg64; /* TODO: will add them during VCN v2 implementation */ adev->uvd_ctx_rreg = NULL; -- GitLab From b16284259f2dd11e331be73829cdc9877b5f7280 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Mon, 20 Jul 2020 11:11:13 +0800 Subject: [PATCH 0005/1494] drm/amdgpu: add printing after executing page reservation to eeprom This will tell users if the faulty page has been written to external eeprom device in dmesg log. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e10f02ed3f65e..bcce4c0be4623 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1618,7 +1618,7 @@ static int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev) data = con->eh_data; save_count = data->count - control->num_recs; /* only new entries are saved */ - if (save_count > 0) + if (save_count > 0) { if (amdgpu_ras_eeprom_process_recods(control, &data->bps[control->num_recs], true, @@ -1627,6 +1627,9 @@ static int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev) return -EIO; } + dev_info(adev->dev, "Saved %d pages to EEPROM table.\n", save_count); + } + return 0; } -- GitLab From 799a2fbbbfc1caa6832c4b74294e6e86fb1ebb4e Mon Sep 17 00:00:00 2001 From: Changfeng <Changfeng.Zhu@amd.com> Date: Tue, 21 Jul 2020 10:38:19 +0800 Subject: [PATCH 0006/1494] Revert "drm/amd/powerplay: drop unnecessary message support check" The below 3 messages are not supported on Renoir SMU_MSG_PrepareMp1ForShutdown SMU_MSG_PrepareMp1ForUnload SMU_MSG_PrepareMp1ForReset It needs to revert patch: drm/amd/powerplay: drop unnecessary message support check to avoid set mp1 state fail during gpu reset on renoir. Signed-off-by: changfeng <Changfeng.Zhu@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 9 +++++++++ drivers/gpu/drm/amd/powerplay/smu_cmn.h | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 838a369c9ec3c..f778b00e49eb8 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -34,6 +34,7 @@ #include "sienna_cichlid_ppt.h" #include "renoir_ppt.h" #include "amd_pcie.h" +#include "smu_cmn.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -1589,6 +1590,14 @@ int smu_set_mp1_state(struct smu_context *smu, return 0; } + /* some asics may not support those messages */ + if (smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_MSG, + msg) < 0) { + mutex_unlock(&smu->mutex); + return 0; + } + ret = smu_send_smc_msg(smu, msg, NULL); if (ret) dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/powerplay/smu_cmn.h index 98face8c5fd61..f9e63f18b1570 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.h +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.h @@ -25,7 +25,7 @@ #include "amdgpu_smu.h" -#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4) +#if defined(SWSMU_CODE_LAYER_L1) || defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4) int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, enum smu_message_type msg, uint32_t param, -- GitLab From 5befb6fc3b77b7c689c22ceb190e9d9087b3a961 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 21 Jul 2020 14:24:43 +0800 Subject: [PATCH 0007/1494] drm/amdgpu: add member to store vm fault interrupt masks This patch adds a member in vmhub structure to store the vm fault interrupt masks for different version gfxhubs/mmhubs. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 ++ drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 8 ++++++++ 4 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index acdb61cfa24cd..e11c21a639fdb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -92,6 +92,8 @@ struct amdgpu_vmhub { uint32_t ctx_addr_distance; /* include LO32/HI32 */ uint32_t eng_distance; uint32_t eng_addr_distance; /* include LO32/HI32 */ + + uint32_t vm_cntx_cntl_vm_fault; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 394e6f56948a5..993185fb71357 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -390,4 +390,12 @@ void gfxhub_v2_0_init(struct amdgpu_device *adev) mmGCVM_INVALIDATE_ENG0_REQ; hub->eng_addr_distance = mmGCVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 - mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32; + + hub->vm_cntx_cntl_vm_fault = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index fa0bca3e1f730..07cae64d55f15 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -389,6 +389,14 @@ void gfxhub_v2_1_init(struct amdgpu_device *adev) mmGCVM_INVALIDATE_ENG0_REQ; hub->eng_addr_distance = mmGCVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 - mmGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32; + + hub->vm_cntx_cntl_vm_fault = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; } int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 757fa8e83f5b3..48134b9673f0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -381,6 +381,14 @@ void mmhub_v2_0_init(struct amdgpu_device *adev) mmMMVM_INVALIDATE_ENG0_REQ; hub->eng_addr_distance = mmMMVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 - mmMMVM_INVALIDATE_ENG0_ADDR_RANGE_LO32; + + hub->vm_cntx_cntl_vm_fault = MMVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | + MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; } static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, -- GitLab From f2c1b5c145c8ffe71b314d94f35383ac0d94edd0 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 21 Jul 2020 14:57:02 +0800 Subject: [PATCH 0008/1494] drm/amdgpu: abstract set_vm_fault_masks function to refine the programming This patch is to add set_vm_fault_masks helper to amdgpu_gmc to refine the original programming. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 20 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 4 ++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 53 ++----------------------- 3 files changed, 28 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 34cbd6f6a56b7..21d2c8543f852 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -411,3 +411,23 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) break; } } + +void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, + bool enable) +{ + struct amdgpu_vmhub *hub; + u32 tmp, reg, i; + + hub = &adev->vmhub[hub_type]; + for (i = 0; i < 16; i++) { + reg = hub->vm_context0_cntl + hub->ctx_distance * i; + + tmp = RREG32(reg); + if (enable) + tmp |= hub->vm_cntx_cntl_vm_fault; + else + tmp &= ~hub->vm_cntx_cntl_vm_fault; + + WREG32(reg, tmp); + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index e11c21a639fdb..1785a0e378df1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -291,4 +291,8 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev); extern void amdgpu_gmc_tmz_set(struct amdgpu_device *adev); +extern void +amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, + bool enable); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index ec90c62078d96..e6c8526f0093b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -62,63 +62,18 @@ gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, enum amdgpu_interrupt_state state) { - struct amdgpu_vmhub *hub; - u32 tmp, reg, bits[AMDGPU_MAX_VMHUBS], i; - - bits[AMDGPU_GFXHUB_0] = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; - - bits[AMDGPU_MMHUB_0] = MMVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | - MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; - switch (state) { case AMDGPU_IRQ_STATE_DISABLE: /* MM HUB */ - hub = &adev->vmhub[AMDGPU_MMHUB_0]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + hub->ctx_distance * i; - tmp = RREG32(reg); - tmp &= ~bits[AMDGPU_MMHUB_0]; - WREG32(reg, tmp); - } - + amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, false); /* GFX HUB */ - hub = &adev->vmhub[AMDGPU_GFXHUB_0]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + hub->ctx_distance * i; - tmp = RREG32(reg); - tmp &= ~bits[AMDGPU_GFXHUB_0]; - WREG32(reg, tmp); - } + amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, false); break; case AMDGPU_IRQ_STATE_ENABLE: /* MM HUB */ - hub = &adev->vmhub[AMDGPU_MMHUB_0]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + hub->ctx_distance * i; - tmp = RREG32(reg); - tmp |= bits[AMDGPU_MMHUB_0]; - WREG32(reg, tmp); - } - + amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_MMHUB_0, true); /* GFX HUB */ - hub = &adev->vmhub[AMDGPU_GFXHUB_0]; - for (i = 0; i < 16; i++) { - reg = hub->vm_context0_cntl + hub->ctx_distance * i; - tmp = RREG32(reg); - tmp |= bits[AMDGPU_GFXHUB_0]; - WREG32(reg, tmp); - } + amdgpu_gmc_set_vm_fault_masks(adev, AMDGPU_GFXHUB_0, true); break; default: break; -- GitLab From 2577db91e82e9b2e68acb9f467ae29ce3aa89d52 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 21 Jul 2020 17:39:26 +0800 Subject: [PATCH 0009/1494] drm/amdgpu: add vmhub funcs helper (v2) This patch is to introduce vmhub funcs helper to add following callback (print_l2_protection_fault_status). Each GC/MMHUB register specific programming should be in gfxhub/mmhub level. v2: remove the condition of funcs assignment. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 7 +++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 33 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 33 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 25 ++---------------- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 33 ++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 1785a0e378df1..bbecd879744a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -74,6 +74,11 @@ struct amdgpu_gmc_fault { /* * VMHUB structures, functions & helpers */ +struct amdgpu_vmhub_funcs { + void (*print_l2_protection_fault_status)(struct amdgpu_device *adev, + uint32_t status); +}; + struct amdgpu_vmhub { uint32_t ctx0_ptb_addr_lo32; uint32_t ctx0_ptb_addr_hi32; @@ -94,6 +99,8 @@ struct amdgpu_vmhub { uint32_t eng_addr_distance; /* include LO32/HI32 */ uint32_t vm_cntx_cntl_vm_fault; + + const struct amdgpu_vmhub_funcs *vmhub_funcs; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 993185fb71357..607a76a1ebb7a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -31,6 +31,33 @@ #include "soc15_common.h" +static void +gfxhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, + uint32_t status) +{ + dev_err(adev->dev, + "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", + status); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); + dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR)); + dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS)); + dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); + dev_err(adev->dev, "\t RW: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, RW)); +} + u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE); @@ -360,6 +387,10 @@ void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } +static const struct amdgpu_vmhub_funcs gfxhub_v2_0_vmhub_funcs = { + .print_l2_protection_fault_status = gfxhub_v2_0_print_l2_protection_fault_status, +}; + void gfxhub_v2_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -398,4 +429,6 @@ void gfxhub_v2_0_init(struct amdgpu_device *adev) GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; + + hub->vmhub_funcs = &gfxhub_v2_0_vmhub_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 07cae64d55f15..777384e6fa10a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -31,6 +31,33 @@ #include "soc15_common.h" +static void +gfxhub_v2_1_print_l2_protection_fault_status(struct amdgpu_device *adev, + uint32_t status) +{ + dev_err(adev->dev, + "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", + status); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); + dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR)); + dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS)); + dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); + dev_err(adev->dev, "\t RW: 0x%lx\n", + REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, RW)); +} + u64 gfxhub_v2_1_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE); @@ -359,6 +386,10 @@ void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp); } +static const struct amdgpu_vmhub_funcs gfxhub_v2_1_vmhub_funcs = { + .print_l2_protection_fault_status = gfxhub_v2_1_print_l2_protection_fault_status, +}; + void gfxhub_v2_1_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -397,6 +428,8 @@ void gfxhub_v2_1_init(struct amdgpu_device *adev) GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; + + hub->vmhub_funcs = &gfxhub_v2_1_vmhub_funcs; } int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index e6c8526f0093b..8f35e1315177d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -121,29 +121,8 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, task_info.task_name, task_info.pid); dev_err(adev->dev, " in page starting at address 0x%016llx from client %d\n", addr, entry->client_id); - if (!amdgpu_sriov_vf(adev)) { - dev_err(adev->dev, - "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", - status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, CID)); - dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); - dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR)); - dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS)); - dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); - dev_err(adev->dev, "\t RW: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, RW)); - } + if (!amdgpu_sriov_vf(adev)) + hub->vmhub_funcs->print_l2_protection_fault_status(adev, status); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 48134b9673f0d..8f911efec607a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -36,6 +36,33 @@ #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 +static void +mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, + uint32_t status) +{ + dev_err(adev->dev, + "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", + status); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); + dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR)); + dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS)); + dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); + dev_err(adev->dev, "\t RW: 0x%lx\n", + REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, RW)); +} + void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { @@ -351,6 +378,10 @@ void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) WREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL, tmp); } +static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = { + .print_l2_protection_fault_status = mmhub_v2_0_print_l2_protection_fault_status, +}; + void mmhub_v2_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -389,6 +420,8 @@ void mmhub_v2_0_init(struct amdgpu_device *adev) MMVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | MMVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK | MMVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK; + + hub->vmhub_funcs = &mmhub_v2_0_vmhub_funcs; } static void mmhub_v2_0_update_medium_grain_clock_gating(struct amdgpu_device *adev, -- GitLab From caa9f483ca76693159499bd45e2e635c7e47bf46 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 21 Jul 2020 18:04:46 +0800 Subject: [PATCH 0010/1494] drm/amdgpu: move get_invalidate_req function into gfxhub/mmhub level This patch is to move get_invalidate_req into gfxhub/mmhub level. It will avoid mismatch of the different gfxhub/mmhub register offsets and fields in the same gmc block. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 21 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 21 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 26 +++--------------------- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 21 +++++++++++++++++++ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index bbecd879744a4..9d58c56f6cfc4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -77,6 +77,7 @@ struct amdgpu_gmc_fault { struct amdgpu_vmhub_funcs { void (*print_l2_protection_fault_status)(struct amdgpu_device *adev, uint32_t status); + uint32_t (*get_invalidate_req)(unsigned int vmid, uint32_t flush_type); }; struct amdgpu_vmhub { diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 607a76a1ebb7a..76acd7f7723e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -31,6 +31,26 @@ #include "soc15_common.h" +static uint32_t gfxhub_v2_0_get_invalidate_req(unsigned int vmid, + uint32_t flush_type) +{ + u32 req = 0; + + /* invalidate using legacy mode on vmid*/ + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, + PER_VMID_INVALIDATE_REQ, 1 << vmid); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, + CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0); + + return req; +} + static void gfxhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) @@ -389,6 +409,7 @@ void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, static const struct amdgpu_vmhub_funcs gfxhub_v2_0_vmhub_funcs = { .print_l2_protection_fault_status = gfxhub_v2_0_print_l2_protection_fault_status, + .get_invalidate_req = gfxhub_v2_0_get_invalidate_req, }; void gfxhub_v2_0_init(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 777384e6fa10a..1f6112b7fa49a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -31,6 +31,26 @@ #include "soc15_common.h" +static uint32_t gfxhub_v2_1_get_invalidate_req(unsigned int vmid, + uint32_t flush_type) +{ + u32 req = 0; + + /* invalidate using legacy mode on vmid*/ + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, + PER_VMID_INVALIDATE_REQ, 1 << vmid); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1); + req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, + CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0); + + return req; +} + static void gfxhub_v2_1_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) @@ -388,6 +408,7 @@ void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, static const struct amdgpu_vmhub_funcs gfxhub_v2_1_vmhub_funcs = { .print_l2_protection_fault_status = gfxhub_v2_1_print_l2_protection_fault_status, + .get_invalidate_req = gfxhub_v2_1_get_invalidate_req, }; void gfxhub_v2_1_init(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 8f35e1315177d..a1798ec25d2b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -139,26 +139,6 @@ static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev) adev->gmc.vm_fault.funcs = &gmc_v10_0_irq_funcs; } -static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid, - uint32_t flush_type) -{ - u32 req = 0; - - /* invalidate using legacy mode on vmid*/ - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, - PER_VMID_INVALIDATE_REQ, 1 << vmid); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1); - req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, - CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0); - - return req; -} - /** * gmc_v10_0_use_invalidate_semaphore - judge whether to use semaphore * @@ -199,7 +179,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid, { bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub); struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; - u32 inv_req = gmc_v10_0_get_invalidate_req(vmid, flush_type); + u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type); u32 tmp; /* Use register 17 for GART */ const unsigned eng = 17; @@ -294,7 +274,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; - u32 inv_req = gmc_v10_0_get_invalidate_req(vmid, flush_type); + u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type); u32 req = hub->vm_inv_eng0_req + hub->eng_distance * eng; u32 ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -425,7 +405,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, { bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub); struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; - uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0); + uint32_t req = hub->vmhub_funcs->get_invalidate_req(vmid, 0); unsigned eng = ring->vm_inv_eng; /* diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 8f911efec607a..d83912901f730 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -36,6 +36,26 @@ #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 +static uint32_t mmhub_v2_0_get_invalidate_req(unsigned int vmid, + uint32_t flush_type) +{ + u32 req = 0; + + /* invalidate using legacy mode on vmid*/ + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, + PER_VMID_INVALIDATE_REQ, 1 << vmid); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1); + req = REG_SET_FIELD(req, MMVM_INVALIDATE_ENG0_REQ, + CLEAR_PROTECTION_FAULT_STATUS_ADDR, 0); + + return req; +} + static void mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) @@ -380,6 +400,7 @@ void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = { .print_l2_protection_fault_status = mmhub_v2_0_print_l2_protection_fault_status, + .get_invalidate_req = mmhub_v2_0_get_invalidate_req, }; void mmhub_v2_0_init(struct amdgpu_device *adev) -- GitLab From db92fbc3d7f0128a2fab8a34f80c388509721eb1 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 21 Jul 2020 18:08:24 +0800 Subject: [PATCH 0011/1494] drm/amdgpu: won't include gc and mmhub register headers in GMC block All gc/mmhub register access and operation should be in gfxhub/mmhub level. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index a1798ec25d2b0..19051ce122b1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -28,8 +28,6 @@ #include "hdp/hdp_5_0_0_offset.h" #include "hdp/hdp_5_0_0_sh_mask.h" -#include "gc/gc_10_1_0_sh_mask.h" -#include "mmhub/mmhub_2_0_0_sh_mask.h" #include "athub/athub_2_0_0_sh_mask.h" #include "athub/athub_2_0_0_offset.h" #include "dcn/dcn_2_0_0_offset.h" -- GitLab From 06b668c1dc1f5ef02e3065ef9201b4710cc03d0e Mon Sep 17 00:00:00 2001 From: Tom St Denis <tom.stdenis@amd.com> Date: Wed, 22 Jul 2020 07:36:36 -0400 Subject: [PATCH 0012/1494] drm/amd/amdgpu: Fix compiler warning in df driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this warning: CC [M] drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.o In file included from drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h:29, from drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h:26, from drivers/gpu/drm/amd/amdgpu/amdgpu.h:43, from drivers/gpu/drm/amd/amdgpu/df_v3_6.c:23: drivers/gpu/drm/amd/amdgpu/df_v3_6.c: In function ‘df_v3_6_pmc_get_count’: ./include/drm/drm_print.h:487:2: warning: ‘hi_base_addr’ may be used uninitialized in this function [-Wmaybe-uninitialized] 487 | __drm_dbg(DRM_UT_DRIVER, fmt, ##__VA_ARGS__) | ^~~~~~~~~ drivers/gpu/drm/amd/amdgpu/df_v3_6.c:649:25: note: ‘hi_base_addr’ was declared here 649 | uint32_t lo_base_addr, hi_base_addr, lo_val = 0, hi_val = 0; | ^~~~~~~~~~~~ In file included from drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h:29, from drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h:26, from drivers/gpu/drm/amd/amdgpu/amdgpu.h:43, from drivers/gpu/drm/amd/amdgpu/df_v3_6.c:23: ./include/drm/drm_print.h:487:2: warning: ‘lo_base_addr’ may be used uninitialized in this function [-Wmaybe-uninitialized] 487 | __drm_dbg(DRM_UT_DRIVER, fmt, ##__VA_ARGS__) | ^~~~~~~~~ drivers/gpu/drm/amd/amdgpu/df_v3_6.c:649:11: note: ‘lo_base_addr’ was declared here 649 | uint32_t lo_base_addr, hi_base_addr, lo_val = 0, hi_val = 0; Signed-off-by: Tom St Denis <tom.stdenis@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 1ab2618369834..0aa1ac1accd6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -646,7 +646,7 @@ static void df_v3_6_pmc_get_count(struct amdgpu_device *adev, uint64_t config, uint64_t *count) { - uint32_t lo_base_addr, hi_base_addr, lo_val = 0, hi_val = 0; + uint32_t lo_base_addr = 0, hi_base_addr = 0, lo_val = 0, hi_val = 0; *count = 0; switch (adev->asic_type) { -- GitLab From 8fe384ff2d9610f4bf4aa2a9cecb5a209a1e85a2 Mon Sep 17 00:00:00 2001 From: Kenneth Feng <kenneth.feng@amd.com> Date: Wed, 22 Jul 2020 21:27:35 +0800 Subject: [PATCH 0013/1494] drm/amd/powerplay: remove the dpm checking in the boot sequence It's not necessary to retrieve the power features status when the asic is booted up the first time. This patch can have the features enablement status still checked in suspend/resume case and removed from the first boot up sequence. Signed-off-by: Kenneth Feng <kenneth.feng@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f778b00e49eb8..6b03f750e63bc 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -735,7 +735,7 @@ static int smu_smc_hw_setup(struct smu_context *smu) uint32_t pcie_gen = 0, pcie_width = 0; int ret; - if (smu_is_dpm_running(smu) && adev->in_suspend) { + if (adev->in_suspend && smu_is_dpm_running(smu)) { dev_info(adev->dev, "dpm has been enabled\n"); return 0; } -- GitLab From 2afda735c5504e1258a0ec259aceec2078d3da67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com> Date: Wed, 22 Jul 2020 14:38:13 +0200 Subject: [PATCH 0014/1494] drm/amdgpu/dc: Simplify drm_crtc_state::active checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_atomic_crtc_check enforces that ::active can only be true if ::enable is as well. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Michel Dänzer <mdaenzer@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 45886649cc53e..03a60c7498344 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3430,21 +3430,12 @@ static bool modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream) { - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - if (!crtc_state->enable) - return false; - - return crtc_state->active; + return crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state); } static bool modereset_required(struct drm_crtc_state *crtc_state) { - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return false; - - return !crtc_state->enable || !crtc_state->active; + return !crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state); } static void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder) @@ -8034,8 +8025,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, * We want to do dc stream updates that do not require a * full modeset below. */ - if (!(enable && aconnector && new_crtc_state->enable && - new_crtc_state->active)) + if (!(enable && aconnector && new_crtc_state->active)) return 0; /* * Given above conditions, the dc state cannot be NULL because: -- GitLab From 4031ead37239ec397fb9441555ae2d60e46dc333 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Mon, 20 Jul 2020 15:03:27 +0200 Subject: [PATCH 0015/1494] drm: pl111: Update documentation Remove notes about migrating from the old driver which is retired as all users are now migrated. Update the text to reflect that we support PL110 and PL111 alike. Drop the bullet on memory bandwidth scaling: this has been implemented. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Russell King <linux@armlinux.org.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200720130327.92364-1-linus.walleij@linaro.org --- Documentation/gpu/pl111.rst | 8 ++++---- drivers/gpu/drm/pl111/pl111_drv.c | 20 +++++--------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Documentation/gpu/pl111.rst b/Documentation/gpu/pl111.rst index 9b03736d33dd7..6d9a1b59a5459 100644 --- a/Documentation/gpu/pl111.rst +++ b/Documentation/gpu/pl111.rst @@ -1,6 +1,6 @@ -========================================== - drm/pl111 ARM PrimeCell PL111 CLCD Driver -========================================== +==================================================== + drm/pl111 ARM PrimeCell PL110 and PL111 CLCD Driver +==================================================== .. kernel-doc:: drivers/gpu/drm/pl111/pl111_drv.c - :doc: ARM PrimeCell PL111 CLCD Driver + :doc: ARM PrimeCell PL110 and PL111 CLCD Driver diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 96e58fda75d82..46b0d1c4a16c6 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -10,18 +10,11 @@ */ /** - * DOC: ARM PrimeCell PL111 CLCD Driver + * DOC: ARM PrimeCell PL110 and PL111 CLCD Driver * - * The PL111 is a simple LCD controller that can support TFT and STN - * displays. This driver exposes a standard KMS interface for them. - * - * This driver uses the same Device Tree binding as the fbdev CLCD - * driver. While the fbdev driver supports panels that may be - * connected to the CLCD internally to the CLCD driver, in DRM the - * panels get split out to drivers/gpu/drm/panels/. This means that, - * in converting from using fbdev to using DRM, you also need to write - * a panel driver (which may be as simple as an entry in - * panel-simple.c). + * The PL110/PL111 is a simple LCD controller that can support TFT + * and STN displays. This driver exposes a standard KMS interface + * for them. * * The driver currently doesn't expose the cursor. The DRM API for * cursors requires support for 64x64 ARGB8888 cursor images, while @@ -29,16 +22,13 @@ * cursors. While one could imagine trying to hack something together * to look at the ARGB8888 and program reasonable in monochrome, we * just don't expose the cursor at all instead, and leave cursor - * support to the X11 software cursor layer. + * support to the application software cursor layer. * * TODO: * * - Fix race between setting plane base address and getting IRQ for * vsync firing the pageflip completion. * - * - Use the "max-memory-bandwidth" DT property to filter the - * supported formats. - * * - Read back hardware state at boot to skip reprogramming the * hardware when doing a no-op modeset. * -- GitLab From ebee9621bbc1e9f07e105121bf2d4d5debd435fd Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Tue, 21 Jul 2020 14:01:53 +0800 Subject: [PATCH 0016/1494] drm/amd/powerplay: skip invalid msg when smu set mp1 state Some asic may not support for some message of set mp1 state. If the return value of smu_send_smc_msg is -EINVAL, that means it failed to send msg to smc as it can not map an valid message for the ASIC. And with that case, smu_set_mp1_state should be skipped as those ASIC was in fact do not support for that. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 6b03f750e63bc..727cb9fd4aee1 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -1599,6 +1599,9 @@ int smu_set_mp1_state(struct smu_context *smu, } ret = smu_send_smc_msg(smu, msg, NULL); + /* some asics may not support those messages */ + if (ret == -EINVAL) + ret = 0; if (ret) dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); -- GitLab From 7a3ecc82f1b9e14e8e864772f03ce040835735ba Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Tue, 21 Jul 2020 13:13:39 +0800 Subject: [PATCH 0017/1494] drm/amd/powerplay: add msg map for mode1 reset Mapping Mode1Reset message for sienna_cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 59da3ca2a4cae..f44fd33aeb93e 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -121,6 +121,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 1), MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 1), + MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 1), }; static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { -- GitLab From 91190db1a72dada38f1ae375c63a6b02c8d3d465 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Tue, 21 Jul 2020 16:39:45 +0800 Subject: [PATCH 0018/1494] drm/amd/powerplay: correct smu message for vf mode Set valid_in_vf to false for the message not support in vf mode on sienna cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f44fd33aeb93e..dcc5d25a78940 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -74,10 +74,10 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), - MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 1), - MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 1), - MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 1), - MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 1), + MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0), + MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0), + MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), + MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1), MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1), MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1), @@ -85,43 +85,43 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1), MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1), MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), - MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 1), - MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), - MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), - MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 1), - MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 1), - MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), - MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1), - MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 1), - MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 1), - MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1), - MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), - MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 1), + MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), - MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 1), - MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 1), - MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 1), - MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 1), - MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 1), - MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 1), - MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 1), - MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 1), + MSG_MAP(SetGeminiMode, PPSMC_MSG_SetGeminiMode, 0), + MSG_MAP(SetGeminiApertureHigh, PPSMC_MSG_SetGeminiApertureHigh, 0), + MSG_MAP(SetGeminiApertureLow, PPSMC_MSG_SetGeminiApertureLow, 0), + MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0), + MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0), + MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), + MSG_MAP(SetUclkFastSwitch, PPSMC_MSG_SetUclkFastSwitch, 0), + MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 0), MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), - MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1), - MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1), - MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), + MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), + MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), - MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 1), - MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), - MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), - MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), - MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), - MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 1), - MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 1), - MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 1), + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), + MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), + MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), + MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0), + MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), + MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), }; static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { -- GitLab From 8f3b800a31f8ac6fe243649c41bcfa15c987ce20 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Thu, 23 Jul 2020 15:26:27 +0800 Subject: [PATCH 0019/1494] drm/amdgpu: update golden setting for sienna_cichlid Update golden setting for sienna_cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 61e89247faf3b..8344c3b0b9b5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3082,7 +3082,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA0_CLK_CTRL, 0xff7f0fff, 0x30000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA1_CLK_CTRL, 0xff7f0fff, 0x7e000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCPF_GCR_CNTL, 0x0007ffff, 0x0000c000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500), -- GitLab From c5a4ef3e20da16829bf417fb2093824c1bc0f82f Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Thu, 23 Jul 2020 17:38:20 +0800 Subject: [PATCH 0020/1494] drm/amdgpu: move umc specific macros to header certain umc macros are common across umc versions Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 14 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/umc_v6_1.c | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index a615a1eb750be..1838144936580 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -21,6 +21,20 @@ #ifndef __AMDGPU_UMC_H__ #define __AMDGPU_UMC_H__ +/* + * (addr / 256) * 8192, the higher 26 bits in ErrorAddr + * is the index of 8KB block + */ +#define ADDR_OF_8KB_BLOCK(addr) (((addr) & ~0xffULL) << 5) +/* channel index is the index of 256B block */ +#define ADDR_OF_256B_BLOCK(channel_index) ((channel_index) << 8) +/* offset in 256B block */ +#define OFFSET_IN_256B_BLOCK(addr) ((addr) & 0xffULL) + +#define LOOP_UMC_INST(umc_inst) for ((umc_inst) = 0; (umc_inst) < adev->umc.umc_inst_num; (umc_inst)++) +#define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++) +#define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst)) + struct amdgpu_umc_funcs { void (*err_cnt_init)(struct amdgpu_device *adev); int (*ras_late_init)(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c index 418cf097c918a..5288617ca5523 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c @@ -32,20 +32,6 @@ #define UMC_6_INST_DIST 0x40000 -/* - * (addr / 256) * 8192, the higher 26 bits in ErrorAddr - * is the index of 8KB block - */ -#define ADDR_OF_8KB_BLOCK(addr) (((addr) & ~0xffULL) << 5) -/* channel index is the index of 256B block */ -#define ADDR_OF_256B_BLOCK(channel_index) ((channel_index) << 8) -/* offset in 256B block */ -#define OFFSET_IN_256B_BLOCK(addr) ((addr) & 0xffULL) - -#define LOOP_UMC_INST(umc_inst) for ((umc_inst) = 0; (umc_inst) < adev->umc.umc_inst_num; (umc_inst)++) -#define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++) -#define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst)) - const uint32_t umc_v6_1_channel_idx_tbl[UMC_V6_1_UMC_INSTANCE_NUM][UMC_V6_1_CHANNEL_INSTANCE_NUM] = { {2, 18, 11, 27}, {4, 20, 13, 29}, -- GitLab From cc0e7ff8ffe01653a078824594e32be114414035 Mon Sep 17 00:00:00 2001 From: Li Heng <liheng40@huawei.com> Date: Thu, 23 Jul 2020 11:27:43 +0800 Subject: [PATCH 0021/1494] drm/amdgpu: Remove redundant NULL check Fix below warnings reported by coccicheck: ./drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c:557:2-7: WARNING: NULL check before some freeing functions is not needed. Fixes: 4d55b0dd1cdd ("drm/amd/display: Add DCN3 CLK_MGR") Signed-off-by: Li Heng <liheng40@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index d94fdc52be374..d8af56a58196a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -553,8 +553,7 @@ void dcn3_clk_mgr_construct( void dcn3_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr) { - if (clk_mgr->base.bw_params) - kfree(clk_mgr->base.bw_params); + kfree(clk_mgr->base.bw_params); if (clk_mgr->wm_range_table) dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART, -- GitLab From ccda42a4629aa6ea48b5343a131ba420d0fa5c8f Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 16 Jul 2020 22:20:04 -0400 Subject: [PATCH 0022/1494] drm/amdgpu/powerplay: add some documentation about memory clock We expose the actual memory controller clock rate in Linux, not the effective memory clock of the DRAMs. To translate it, it follows the following formula: Clock conversion (Mhz): HBM: effective_memory_clock = memory_controller_clock * 1 G5: effective_memory_clock = memory_controller_clock * 1 G6: effective_memory_clock = memory_controller_clock * 2 DRAM data rate (MT/s): HBM: effective_memory_clock * 2 = data_rate G5: effective_memory_clock * 4 = data_rate G6: effective_memory_clock * 8 = data_rate Bandwidth (MB/s): data_rate * vram_bit_width / 8 = memory_bandwidth Some examples: G5 on RX460: memory_controller_clock = 1750 Mhz effective_memory_clock = 1750 Mhz * 1 = 1750 Mhz data rate = 1750 * 4 = 7000 MT/s memory_bandwidth = 7000 * 128 bits / 8 = 112000 MB/s G6 on RX5600: memory_controller_clock = 900 Mhz effective_memory_clock = 900 Mhz * 2 = 1800 Mhz data rate = 1800 * 8 = 14400 MT/s memory_bandwidth = 14400 * 192 bits / 8 = 345600 MB/s Acked-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 5f20cadee3438..0a05db9b71320 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -694,6 +694,52 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, * in each power level within a power state. The pp_od_clk_voltage is used for * this. * + * Note that the actual memory controller clock rate are exposed, not + * the effective memory clock of the DRAMs. To translate it, use the + * following formula: + * + * Clock conversion (Mhz): + * + * HBM: effective_memory_clock = memory_controller_clock * 1 + * + * G5: effective_memory_clock = memory_controller_clock * 1 + * + * G6: effective_memory_clock = memory_controller_clock * 2 + * + * DRAM data rate (MT/s): + * + * HBM: effective_memory_clock * 2 = data_rate + * + * G5: effective_memory_clock * 4 = data_rate + * + * G6: effective_memory_clock * 8 = data_rate + * + * Bandwidth (MB/s): + * + * data_rate * vram_bit_width / 8 = memory_bandwidth + * + * Some examples: + * + * G5 on RX460: + * + * memory_controller_clock = 1750 Mhz + * + * effective_memory_clock = 1750 Mhz * 1 = 1750 Mhz + * + * data rate = 1750 * 4 = 7000 MT/s + * + * memory_bandwidth = 7000 * 128 bits / 8 = 112000 MB/s + * + * G6 on RX5700: + * + * memory_controller_clock = 875 Mhz + * + * effective_memory_clock = 875 Mhz * 2 = 1750 Mhz + * + * data rate = 1750 * 8 = 14000 MT/s + * + * memory_bandwidth = 14000 * 256 bits / 8 = 448000 MB/s + * * < For Vega10 and previous ASICs > * * Reading the file will display: -- GitLab From 6142b1b82ce43e6f7663f2e148ca48808f9d698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 17 Jul 2020 16:54:39 +0300 Subject: [PATCH 0023/1494] drm/todo: Plumb drm_atomic_state all over MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a TODO for plumbing drm_atomic_state all over to ease the hurdles of accessing additional object states. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> #irc Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200717135439.5996-1-ville.syrjala@linux.intel.com --- Documentation/gpu/todo.rst | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 7969f106877de..b0ea17da8ff63 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -403,6 +403,52 @@ Contact: Emil Velikov, respective driver maintainers Level: Intermediate +Plumb drm_atomic_state all over +------------------------------- + +Currently various atomic functions take just a single or a handful of +object states (eg. plane state). While that single object state can +suffice for some simple cases, we often have to dig out additional +object states for dealing with various dependencies between the individual +objects or the hardware they represent. The process of digging out the +additional states is rather non-intuitive and error prone. + +To fix that most functions should rather take the overall +drm_atomic_state as one of their parameters. The other parameters +would generally be the object(s) we mainly want to interact with. + +For example, instead of + +.. code-block:: c + + int (*atomic_check)(struct drm_plane *plane, struct drm_plane_state *state); + +we would have something like + +.. code-block:: c + + int (*atomic_check)(struct drm_plane *plane, struct drm_atomic_state *state); + +The implementation can then trivially gain access to any required object +state(s) via drm_atomic_get_plane_state(), drm_atomic_get_new_plane_state(), +drm_atomic_get_old_plane_state(), and their equivalents for +other object types. + +Additionally many drivers currently access the object->state pointer +directly in their commit functions. That is not going to work if we +eg. want to allow deeper commit pipelines as those pointers could +then point to the states corresponding to a future commit instead of +the current commit we're trying to process. Also non-blocking commits +execute locklessly so there are serious concerns with dereferencing +the object->state pointers without holding the locks that protect them. +Use of drm_atomic_get_new_plane_state(), drm_atomic_get_old_plane_state(), +etc. avoids these problems as well since they relate to a specific +commit via the passed in drm_atomic_state. + +Contact: Ville Syrjälä, Daniel Vetter + +Level: Intermediate + Core refactorings ================= -- GitLab From 0d3df1c603de993163c6c9906373e8dde352c56a Mon Sep 17 00:00:00 2001 From: Vinod Koul <vkoul@kernel.org> Date: Thu, 23 Jul 2020 22:04:40 +0530 Subject: [PATCH 0024/1494] dt-bindings: vendor-prefixes: Add Lontium vendor prefix Add prefix for Lontium Semiconductor Corporation Acked-by: Rob Herring <robh@kernel.org> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200723163442.1280414-2-vkoul@kernel.org --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 740b116b179f4..caf7dbed564ca 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -595,6 +595,8 @@ patternProperties: description: Logic Technologies Limited "^longcheer,.*": description: Longcheer Technology (Shanghai) Co., Ltd. + "^lontium,.*": + description: Lontium Semiconductor Corporation "^loongson,.*": description: Loongson Technology Corporation Limited "^lsi,.*": -- GitLab From 8a72a2de0a4fc727970a06c565f1112ae82ed132 Mon Sep 17 00:00:00 2001 From: Vinod Koul <vkoul@kernel.org> Date: Thu, 23 Jul 2020 22:04:41 +0530 Subject: [PATCH 0025/1494] dt-bindings: display: bridge: Add documentation for LT9611 Lontium LT9611 is a DSI to HDMI bridge which supports 2 DSI ports and I2S port as input and one HDMI port as output Reviewed-by: Rob Herring <robh@kernel.org> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200723163442.1280414-3-vkoul@kernel.org --- .../display/bridge/lontium,lt9611.yaml | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml new file mode 100644 index 0000000000000..d60208359234b --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml @@ -0,0 +1,176 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/lontium,lt9611.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lontium LT9611 2 Port MIPI to HDMI Bridge + +maintainers: + - Vinod Koul <vkoul@kernel.org> + +description: | + The LT9611 is a bridge device which converts DSI to HDMI + +properties: + compatible: + enum: + - lontium,lt9611 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + maxItems: 1 + description: GPIO connected to active high RESET pin. + + vdd-supply: + description: Regulator for 1.8V MIPI phy power. + + vcc-supply: + description: Regulator for 3.3V IO power. + + ports: + type: object + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + port@0: + type: object + description: | + Primary MIPI port-1 for MIPI input + + properties: + reg: + const: 0 + + patternProperties: + "^endpoint(@[0-9])$": + type: object + additionalProperties: false + + properties: + remote-endpoint: + $ref: /schemas/types.yaml#/definitions/phandle + + required: + - reg + + port@1: + type: object + description: | + Additional MIPI port-2 for MIPI input, used in combination + with primary MIPI port-1 to drive higher resolution displays + + properties: + reg: + const: 1 + + patternProperties: + "^endpoint(@[0-9])$": + type: object + additionalProperties: false + + properties: + remote-endpoint: + $ref: /schemas/types.yaml#/definitions/phandle + + required: + - reg + + port@2: + type: object + description: | + HDMI port for HDMI output + + properties: + reg: + const: 2 + + patternProperties: + "^endpoint(@[0-9])$": + type: object + additionalProperties: false + + properties: + remote-endpoint: + $ref: /schemas/types.yaml#/definitions/phandle + + required: + - reg + + required: + - "#address-cells" + - "#size-cells" + - port@0 + - port@2 + +required: + - compatible + - reg + - interrupts + - vdd-supply + - vcc-supply + - ports + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c10 { + #address-cells = <1>; + #size-cells = <0>; + + hdmi-bridge@3b { + compatible = "lontium,lt9611"; + reg = <0x3b>; + + reset-gpios = <&tlmm 128 GPIO_ACTIVE_HIGH>; + interrupts-extended = <&tlmm 84 IRQ_TYPE_EDGE_FALLING>; + + vdd-supply = <<9611_1v8>; + vcc-supply = <<9611_3v3>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + lt9611_a: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + lt9611_b: endpoint { + remote-endpoint = <&dsi1_out>; + }; + }; + + port@2 { + reg = <2>; + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; + }; + }; + +... -- GitLab From 23278bf54afe180967069bdc8c0f1c7a365fc63e Mon Sep 17 00:00:00 2001 From: Vinod Koul <vkoul@kernel.org> Date: Thu, 23 Jul 2020 22:04:42 +0530 Subject: [PATCH 0026/1494] drm/bridge: Introduce LT9611 DSI to HDMI bridge Lontium Lt9611 is a DSI to HDMI bridge which supports two DSI ports and I2S port as an input and HDMI port as output Co-developed-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Co-developed-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> # fix lt9611_bridge_mode_valid Link: https://patchwork.freedesktop.org/patch/msgid/20200723163442.1280414-4-vkoul@kernel.org --- drivers/gpu/drm/bridge/Kconfig | 13 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/lontium-lt9611.c | 1230 +++++++++++++++++++++++ 3 files changed, 1244 insertions(+) create mode 100644 drivers/gpu/drm/bridge/lontium-lt9611.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 43271c21d3fce..c7f0dacfb57aa 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -48,6 +48,19 @@ config DRM_DISPLAY_CONNECTOR on ARM-based platforms. Saying Y here when this driver is not needed will not cause any issue. +config DRM_LONTIUM_LT9611 + tristate "Lontium LT9611 DSI/HDMI bridge" + select SND_SOC_HDMI_CODEC if SND_SOC + depends on OF + select DRM_PANEL_BRIDGE + select DRM_KMS_HELPER + select REGMAP_I2C + help + Driver for Lontium LT9611 DSI to HDMI bridge + chip driver that converts dual DSI and I2S to + HDMI signals + Please say Y if you have such hardware. + config DRM_LVDS_CODEC tristate "Transparent LVDS encoders and decoders support" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index d63d4b7e43473..7d7c123a95e43 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o +obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c new file mode 100644 index 0000000000000..1009fc4ed4edc --- /dev/null +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -0,0 +1,1230 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2020. Linaro Limited. + */ + +#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> + +#include <sound/hdmi-codec.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +#define EDID_SEG_SIZE 256 +#define EDID_LEN 32 +#define EDID_LOOP 8 +#define KEY_DDC_ACCS_DONE 0x02 +#define DDC_NO_ACK 0x50 + +#define LT9611_4LANES 0 + +struct lt9611 { + struct device *dev; + struct drm_bridge bridge; + struct drm_connector connector; + + struct regmap *regmap; + + struct device_node *dsi0_node; + struct device_node *dsi1_node; + struct mipi_dsi_device *dsi0; + struct mipi_dsi_device *dsi1; + struct platform_device *audio_pdev; + + bool ac_mode; + + struct gpio_desc *reset_gpio; + struct gpio_desc *enable_gpio; + + bool power_on; + bool sleep; + + struct regulator_bulk_data supplies[2]; + + struct i2c_client *client; + + enum drm_connector_status status; + + u8 edid_buf[EDID_SEG_SIZE]; + u32 vic; +}; + +#define LT9611_PAGE_CONTROL 0xff + +static const struct regmap_range_cfg lt9611_ranges[] = { + { + .name = "register_range", + .range_min = 0, + .range_max = 0x85ff, + .selector_reg = LT9611_PAGE_CONTROL, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config lt9611_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xffff, + .ranges = lt9611_ranges, + .num_ranges = ARRAY_SIZE(lt9611_ranges), +}; + +struct lt9611_mode { + u16 hdisplay; + u16 vdisplay; + u8 vrefresh; + u8 lanes; + u8 intfs; +}; + +static struct lt9611_mode lt9611_modes[] = { + { 3840, 2160, 30, 4, 2 }, /* 3840x2160 24bit 30Hz 4Lane 2ports */ + { 1920, 1080, 60, 4, 1 }, /* 1080P 24bit 60Hz 4lane 1port */ + { 1920, 1080, 30, 3, 1 }, /* 1080P 24bit 30Hz 3lane 1port */ + { 1920, 1080, 24, 3, 1 }, + { 720, 480, 60, 4, 1 }, + { 720, 576, 50, 2, 1 }, + { 640, 480, 60, 2, 1 }, +}; + +static struct lt9611 *bridge_to_lt9611(struct drm_bridge *bridge) +{ + return container_of(bridge, struct lt9611, bridge); +} + +static struct lt9611 *connector_to_lt9611(struct drm_connector *connector) +{ + return container_of(connector, struct lt9611, connector); +} + +static int lt9611_mipi_input_analog(struct lt9611 *lt9611) +{ + const struct reg_sequence reg_cfg[] = { + { 0x8106, 0x40 }, /* port A rx current */ + { 0x810a, 0xfe }, /* port A ldo voltage set */ + { 0x810b, 0xbf }, /* enable port A lprx */ + { 0x8111, 0x40 }, /* port B rx current */ + { 0x8115, 0xfe }, /* port B ldo voltage set */ + { 0x8116, 0xbf }, /* enable port B lprx */ + + { 0x811c, 0x03 }, /* PortA clk lane no-LP mode */ + { 0x8120, 0x03 }, /* PortB clk lane with-LP mode */ + }; + + return regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); +} + +static int lt9611_mipi_input_digital(struct lt9611 *lt9611, + const struct drm_display_mode *mode) +{ + struct reg_sequence reg_cfg[] = { + { 0x8300, LT9611_4LANES }, + { 0x830a, 0x00 }, + { 0x824f, 0x80 }, + { 0x8250, 0x10 }, + { 0x8302, 0x0a }, + { 0x8306, 0x0a }, + }; + + if (mode->hdisplay == 3840) + reg_cfg[1].def = 0x03; + + return regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); +} + +static void lt9611_mipi_video_setup(struct lt9611 *lt9611, + const struct drm_display_mode *mode) +{ + u32 h_total, hactive, hsync_len, hfront_porch, hsync_porch; + u32 v_total, vactive, vsync_len, vfront_porch, vsync_porch; + + h_total = mode->htotal; + v_total = mode->vtotal; + + hactive = mode->hdisplay; + hsync_len = mode->hsync_end - mode->hsync_start; + hfront_porch = mode->hsync_start - mode->hdisplay; + hsync_porch = hsync_len + mode->htotal - mode->hsync_end; + + vactive = mode->vdisplay; + vsync_len = mode->vsync_end - mode->vsync_start; + vfront_porch = mode->vsync_start - mode->vdisplay; + vsync_porch = vsync_len + mode->vtotal - mode->vsync_end; + + regmap_write(lt9611->regmap, 0x830d, (u8)(v_total / 256)); + regmap_write(lt9611->regmap, 0x830e, (u8)(v_total % 256)); + + regmap_write(lt9611->regmap, 0x830f, (u8)(vactive / 256)); + regmap_write(lt9611->regmap, 0x8310, (u8)(vactive % 256)); + + regmap_write(lt9611->regmap, 0x8311, (u8)(h_total / 256)); + regmap_write(lt9611->regmap, 0x8312, (u8)(h_total % 256)); + + regmap_write(lt9611->regmap, 0x8313, (u8)(hactive / 256)); + regmap_write(lt9611->regmap, 0x8314, (u8)(hactive % 256)); + + regmap_write(lt9611->regmap, 0x8315, (u8)(vsync_len % 256)); + regmap_write(lt9611->regmap, 0x8316, (u8)(hsync_len % 256)); + + regmap_write(lt9611->regmap, 0x8317, (u8)(vfront_porch % 256)); + + regmap_write(lt9611->regmap, 0x8318, (u8)(vsync_porch % 256)); + + regmap_write(lt9611->regmap, 0x8319, (u8)(hfront_porch % 256)); + + regmap_write(lt9611->regmap, 0x831a, (u8)(hsync_porch / 256)); + regmap_write(lt9611->regmap, 0x831b, (u8)(hsync_porch % 256)); +} + +static void lt9611_pcr_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode) +{ + const struct reg_sequence reg_cfg[] = { + { 0x830b, 0x01 }, + { 0x830c, 0x10 }, + { 0x8348, 0x00 }, + { 0x8349, 0x81 }, + + /* stage 1 */ + { 0x8321, 0x4a }, + { 0x8324, 0x71 }, + { 0x8325, 0x30 }, + { 0x832a, 0x01 }, + + /* stage 2 */ + { 0x834a, 0x40 }, + { 0x831d, 0x10 }, + + /* MK limit */ + { 0x832d, 0x38 }, + { 0x8331, 0x08 }, + }; + const struct reg_sequence reg_cfg2[] = { + { 0x830b, 0x03 }, + { 0x830c, 0xd0 }, + { 0x8348, 0x03 }, + { 0x8349, 0xe0 }, + { 0x8324, 0x72 }, + { 0x8325, 0x00 }, + { 0x832a, 0x01 }, + { 0x834a, 0x10 }, + { 0x831d, 0x10 }, + { 0x8326, 0x37 }, + }; + + regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); + + switch (mode->hdisplay) { + case 640: + regmap_write(lt9611->regmap, 0x8326, 0x14); + break; + case 1920: + regmap_write(lt9611->regmap, 0x8326, 0x37); + break; + case 3840: + regmap_multi_reg_write(lt9611->regmap, reg_cfg2, ARRAY_SIZE(reg_cfg2)); + break; + } + + /* pcr rst */ + regmap_write(lt9611->regmap, 0x8011, 0x5a); + regmap_write(lt9611->regmap, 0x8011, 0xfa); +} + +static int lt9611_pll_setup(struct lt9611 *lt9611, const struct drm_display_mode *mode) +{ + unsigned int pclk = mode->clock; + const struct reg_sequence reg_cfg[] = { + /* txpll init */ + { 0x8123, 0x40 }, + { 0x8124, 0x64 }, + { 0x8125, 0x80 }, + { 0x8126, 0x55 }, + { 0x812c, 0x37 }, + { 0x812f, 0x01 }, + { 0x8126, 0x55 }, + { 0x8127, 0x66 }, + { 0x8128, 0x88 }, + }; + + regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); + + if (pclk > 150000) + regmap_write(lt9611->regmap, 0x812d, 0x88); + else if (pclk > 70000) + regmap_write(lt9611->regmap, 0x812d, 0x99); + else + regmap_write(lt9611->regmap, 0x812d, 0xaa); + + /* + * first divide pclk by 2 first + * - write divide by 64k to 19:16 bits which means shift by 17 + * - write divide by 256 to 15:8 bits which means shift by 9 + * - write remainder to 7:0 bits, which means shift by 1 + */ + regmap_write(lt9611->regmap, 0x82e3, pclk >> 17); /* pclk[19:16] */ + regmap_write(lt9611->regmap, 0x82e4, pclk >> 9); /* pclk[15:8] */ + regmap_write(lt9611->regmap, 0x82e5, pclk >> 1); /* pclk[7:0] */ + + regmap_write(lt9611->regmap, 0x82de, 0x20); + regmap_write(lt9611->regmap, 0x82de, 0xe0); + + regmap_write(lt9611->regmap, 0x8016, 0xf1); + regmap_write(lt9611->regmap, 0x8016, 0xf3); + + return 0; +} + +static int lt9611_read_video_check(struct lt9611 *lt9611, unsigned int reg) +{ + unsigned int temp, temp2; + int ret; + + ret = regmap_read(lt9611->regmap, reg, &temp); + if (ret) + return ret; + temp <<= 8; + ret = regmap_read(lt9611->regmap, reg + 1, &temp2); + if (ret) + return ret; + + return (temp + temp2); +} + +static int lt9611_video_check(struct lt9611 *lt9611) +{ + u32 v_total, vactive, hactive_a, hactive_b, h_total_sysclk; + int temp; + + /* top module video check */ + + /* vactive */ + temp = lt9611_read_video_check(lt9611, 0x8282); + if (temp < 0) + goto end; + vactive = temp; + + /* v_total */ + temp = lt9611_read_video_check(lt9611, 0x826c); + if (temp < 0) + goto end; + v_total = temp; + + /* h_total_sysclk */ + temp = lt9611_read_video_check(lt9611, 0x8286); + if (temp < 0) + goto end; + h_total_sysclk = temp; + + /* hactive_a */ + temp = lt9611_read_video_check(lt9611, 0x8382); + if (temp < 0) + goto end; + hactive_a = temp / 3; + + /* hactive_b */ + temp = lt9611_read_video_check(lt9611, 0x8386); + if (temp < 0) + goto end; + hactive_b = temp / 3; + + dev_info(lt9611->dev, + "video check: hactive_a=%d, hactive_b=%d, vactive=%d, v_total=%d, h_total_sysclk=%d\n", + hactive_a, hactive_b, vactive, v_total, h_total_sysclk); + + return 0; + +end: + dev_err(lt9611->dev, "read video check error\n"); + return temp; +} + +static void lt9611_hdmi_tx_digital(struct lt9611 *lt9611) +{ + regmap_write(lt9611->regmap, 0x8443, 0x46 - lt9611->vic); + regmap_write(lt9611->regmap, 0x8447, lt9611->vic); + regmap_write(lt9611->regmap, 0x843d, 0x0a); /* UD1 infoframe */ + + regmap_write(lt9611->regmap, 0x82d6, 0x8c); + regmap_write(lt9611->regmap, 0x82d7, 0x04); +} + +static void lt9611_hdmi_tx_phy(struct lt9611 *lt9611) +{ + struct reg_sequence reg_cfg[] = { + { 0x8130, 0x6a }, + { 0x8131, 0x44 }, /* HDMI DC mode */ + { 0x8132, 0x4a }, + { 0x8133, 0x0b }, + { 0x8134, 0x00 }, + { 0x8135, 0x00 }, + { 0x8136, 0x00 }, + { 0x8137, 0x44 }, + { 0x813f, 0x0f }, + { 0x8140, 0xa0 }, + { 0x8141, 0xa0 }, + { 0x8142, 0xa0 }, + { 0x8143, 0xa0 }, + { 0x8144, 0x0a }, + }; + + /* HDMI AC mode */ + if (lt9611->ac_mode) + reg_cfg[2].def = 0x73; + + regmap_multi_reg_write(lt9611->regmap, reg_cfg, ARRAY_SIZE(reg_cfg)); +} + +static irqreturn_t lt9611_irq_thread_handler(int irq, void *dev_id) +{ + struct lt9611 *lt9611 = dev_id; + unsigned int irq_flag0 = 0; + unsigned int irq_flag3 = 0; + + regmap_read(lt9611->regmap, 0x820f, &irq_flag3); + regmap_read(lt9611->regmap, 0x820c, &irq_flag0); + + /* hpd changed low */ + if (irq_flag3 & 0x80) { + dev_info(lt9611->dev, "hdmi cable disconnected\n"); + + regmap_write(lt9611->regmap, 0x8207, 0xbf); + regmap_write(lt9611->regmap, 0x8207, 0x3f); + } + + /* hpd changed high */ + if (irq_flag3 & 0x40) { + dev_info(lt9611->dev, "hdmi cable connected\n"); + + regmap_write(lt9611->regmap, 0x8207, 0x7f); + regmap_write(lt9611->regmap, 0x8207, 0x3f); + } + + if (irq_flag3 & 0xc0 && lt9611->bridge.dev) + drm_kms_helper_hotplug_event(lt9611->bridge.dev); + + /* video input changed */ + if (irq_flag0 & 0x01) { + dev_info(lt9611->dev, "video input changed\n"); + regmap_write(lt9611->regmap, 0x829e, 0xff); + regmap_write(lt9611->regmap, 0x829e, 0xf7); + regmap_write(lt9611->regmap, 0x8204, 0xff); + regmap_write(lt9611->regmap, 0x8204, 0xfe); + } + + return IRQ_HANDLED; +} + +static void lt9611_enable_hpd_interrupts(struct lt9611 *lt9611) +{ + unsigned int val; + + regmap_read(lt9611->regmap, 0x8203, &val); + + val &= ~0xc0; + regmap_write(lt9611->regmap, 0x8203, val); + regmap_write(lt9611->regmap, 0x8207, 0xff); /* clear */ + regmap_write(lt9611->regmap, 0x8207, 0x3f); +} + +static void lt9611_sleep_setup(struct lt9611 *lt9611) +{ + const struct reg_sequence sleep_setup[] = { + { 0x8024, 0x76 }, + { 0x8023, 0x01 }, + { 0x8157, 0x03 }, /* set addr pin as output */ + { 0x8149, 0x0b }, + { 0x8151, 0x30 }, /* disable IRQ */ + { 0x8102, 0x48 }, /* MIPI Rx power down */ + { 0x8123, 0x80 }, + { 0x8130, 0x00 }, + { 0x8100, 0x01 }, /* bandgap power down */ + { 0x8101, 0x00 }, /* system clk power down */ + }; + + regmap_multi_reg_write(lt9611->regmap, + sleep_setup, ARRAY_SIZE(sleep_setup)); + lt9611->sleep = true; +} + +static int lt9611_power_on(struct lt9611 *lt9611) +{ + int ret; + const struct reg_sequence seq[] = { + /* LT9611_System_Init */ + { 0x8101, 0x18 }, /* sel xtal clock */ + + /* timer for frequency meter */ + { 0x821b, 0x69 }, /* timer 2 */ + { 0x821c, 0x78 }, + { 0x82cb, 0x69 }, /* timer 1 */ + { 0x82cc, 0x78 }, + + /* irq init */ + { 0x8251, 0x01 }, + { 0x8258, 0x0a }, /* hpd irq */ + { 0x8259, 0x80 }, /* hpd debounce width */ + { 0x829e, 0xf7 }, /* video check irq */ + + /* power consumption for work */ + { 0x8004, 0xf0 }, + { 0x8006, 0xf0 }, + { 0x800a, 0x80 }, + { 0x800b, 0x40 }, + { 0x800d, 0xef }, + { 0x8011, 0xfa }, + }; + + if (lt9611->power_on) + return 0; + + ret = regmap_multi_reg_write(lt9611->regmap, seq, ARRAY_SIZE(seq)); + if (!ret) + lt9611->power_on = true; + + return ret; +} + +static int lt9611_power_off(struct lt9611 *lt9611) +{ + int ret; + + ret = regmap_write(lt9611->regmap, 0x8130, 0x6a); + if (!ret) + lt9611->power_on = false; + + return ret; +} + +static void lt9611_reset(struct lt9611 *lt9611) +{ + gpiod_set_value_cansleep(lt9611->reset_gpio, 1); + msleep(20); + + gpiod_set_value_cansleep(lt9611->reset_gpio, 0); + msleep(20); + + gpiod_set_value_cansleep(lt9611->reset_gpio, 1); + msleep(100); +} + +static void lt9611_assert_5v(struct lt9611 *lt9611) +{ + if (!lt9611->enable_gpio) + return; + + gpiod_set_value_cansleep(lt9611->enable_gpio, 1); + msleep(20); +} + +static int lt9611_regulator_init(struct lt9611 *lt9611) +{ + int ret; + + lt9611->supplies[0].supply = "vdd"; + lt9611->supplies[1].supply = "vcc"; + + ret = devm_regulator_bulk_get(lt9611->dev, 2, lt9611->supplies); + if (ret < 0) + return ret; + + return regulator_set_load(lt9611->supplies[0].consumer, 300000); +} + +static int lt9611_regulator_enable(struct lt9611 *lt9611) +{ + int ret; + + ret = regulator_enable(lt9611->supplies[0].consumer); + if (ret < 0) + return ret; + + usleep_range(1000, 10000); + + ret = regulator_enable(lt9611->supplies[1].consumer); + if (ret < 0) { + regulator_disable(lt9611->supplies[0].consumer); + return ret; + } + + return 0; +} + +static struct lt9611_mode *lt9611_find_mode(const struct drm_display_mode *mode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lt9611_modes); i++) { + if (lt9611_modes[i].hdisplay == mode->hdisplay && + lt9611_modes[i].vdisplay == mode->vdisplay && + lt9611_modes[i].vrefresh == drm_mode_vrefresh(mode)) { + return <9611_modes[i]; + } + } + + return NULL; +} + +/* connector funcs */ +static enum drm_connector_status +lt9611_connector_detect(struct drm_connector *connector, bool force) +{ + struct lt9611 *lt9611 = connector_to_lt9611(connector); + unsigned int reg_val = 0; + int connected = 0; + + regmap_read(lt9611->regmap, 0x825e, ®_val); + connected = (reg_val & BIT(2)); + + lt9611->status = connected ? connector_status_connected : + connector_status_disconnected; + + return lt9611->status; +} + +static int lt9611_read_edid(struct lt9611 *lt9611) +{ + unsigned int temp; + int ret = 0; + int i, j; + + /* memset to clear old buffer, if any */ + memset(lt9611->edid_buf, 0, sizeof(lt9611->edid_buf)); + + regmap_write(lt9611->regmap, 0x8503, 0xc9); + + /* 0xA0 is EDID device address */ + regmap_write(lt9611->regmap, 0x8504, 0xa0); + /* 0x00 is EDID offset address */ + regmap_write(lt9611->regmap, 0x8505, 0x00); + + /* length for read */ + regmap_write(lt9611->regmap, 0x8506, EDID_LEN); + regmap_write(lt9611->regmap, 0x8514, 0x7f); + + for (i = 0; i < EDID_LOOP; i++) { + /* offset address */ + regmap_write(lt9611->regmap, 0x8505, i * EDID_LEN); + regmap_write(lt9611->regmap, 0x8507, 0x36); + regmap_write(lt9611->regmap, 0x8507, 0x31); + regmap_write(lt9611->regmap, 0x8507, 0x37); + usleep_range(5000, 10000); + + regmap_read(lt9611->regmap, 0x8540, &temp); + + if (temp & KEY_DDC_ACCS_DONE) { + for (j = 0; j < EDID_LEN; j++) { + regmap_read(lt9611->regmap, 0x8583, &temp); + lt9611->edid_buf[i * EDID_LEN + j] = temp; + } + + } else if (temp & DDC_NO_ACK) { /* DDC No Ack or Abitration lost */ + dev_err(lt9611->dev, "read edid failed: no ack\n"); + ret = -EIO; + goto end; + + } else { + dev_err(lt9611->dev, "read edid failed: access not done\n"); + ret = -EIO; + goto end; + } + } + +end: + regmap_write(lt9611->regmap, 0x8507, 0x1f); + return ret; +} + +static int +lt9611_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len) +{ + struct lt9611 *lt9611 = data; + int ret; + + if (len > 128) + return -EINVAL; + + /* supports up to 1 extension block */ + /* TODO: add support for more extension blocks */ + if (block > 1) + return -EINVAL; + + if (block == 0) { + ret = lt9611_read_edid(lt9611); + if (ret) { + dev_err(lt9611->dev, "edid read failed\n"); + return ret; + } + } + + block %= 2; + memcpy(buf, lt9611->edid_buf + (block * 128), len); + + return 0; +} + +static int lt9611_connector_get_modes(struct drm_connector *connector) +{ + struct lt9611 *lt9611 = connector_to_lt9611(connector); + unsigned int count; + struct edid *edid; + + lt9611_power_on(lt9611); + edid = drm_do_get_edid(connector, lt9611_get_edid_block, lt9611); + drm_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + kfree(edid); + + return count; +} + +static enum drm_mode_status +lt9611_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode); + + return lt9611_mode ? MODE_OK : MODE_BAD; +} + +/* bridge funcs */ +static void lt9611_bridge_enable(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + if (lt9611_power_on(lt9611)) { + dev_err(lt9611->dev, "power on failed\n"); + return; + } + + lt9611_mipi_input_analog(lt9611); + lt9611_hdmi_tx_digital(lt9611); + lt9611_hdmi_tx_phy(lt9611); + + msleep(500); + + lt9611_video_check(lt9611); + + /* Enable HDMI output */ + regmap_write(lt9611->regmap, 0x8130, 0xea); +} + +static void lt9611_bridge_disable(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + int ret; + + /* Disable HDMI output */ + ret = regmap_write(lt9611->regmap, 0x8130, 0x6a); + if (ret) { + dev_err(lt9611->dev, "video on failed\n"); + return; + } + + if (lt9611_power_off(lt9611)) { + dev_err(lt9611->dev, "power on failed\n"); + return; + } +} + +static struct +drm_connector_helper_funcs lt9611_bridge_connector_helper_funcs = { + .get_modes = lt9611_connector_get_modes, + .mode_valid = lt9611_connector_mode_valid, +}; + +static const struct drm_connector_funcs lt9611_bridge_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = lt9611_connector_detect, + .destroy = drm_connector_cleanup, + .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 struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, + struct device_node *dsi_node) +{ + const struct mipi_dsi_device_info info = { "lt9611", 0, NULL }; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + int ret; + + host = of_find_mipi_dsi_host_by_node(dsi_node); + if (!host) { + dev_err(lt9611->dev, "failed to find dsi host\n"); + return ERR_PTR(-EPROBE_DEFER); + } + + dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dsi)) { + dev_err(lt9611->dev, "failed to create dsi device\n"); + return dsi; + } + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_VIDEO_HSE; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(lt9611->dev, "failed to attach dsi to host\n"); + mipi_dsi_device_unregister(dsi); + return ERR_PTR(ret); + } + + return dsi; +} + +static void lt9611_bridge_detach(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + if (lt9611->dsi1) { + mipi_dsi_detach(lt9611->dsi1); + mipi_dsi_device_unregister(lt9611->dsi1); + } + + mipi_dsi_detach(lt9611->dsi0); + mipi_dsi_device_unregister(lt9611->dsi0); +} + +static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt9611) +{ + int ret; + + ret = drm_connector_init(bridge->dev, <9611->connector, + <9611_bridge_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(<9611->connector, + <9611_bridge_connector_helper_funcs); + drm_connector_attach_encoder(<9611->connector, bridge->encoder); + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + return 0; +} + +static int lt9611_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + int ret; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + ret = lt9611_connector_init(bridge, lt9611); + if (ret < 0) + return ret; + } + + /* Attach primary DSI */ + lt9611->dsi0 = lt9611_attach_dsi(lt9611, lt9611->dsi0_node); + if (IS_ERR(lt9611->dsi0)) + return PTR_ERR(lt9611->dsi0); + + /* Attach secondary DSI, if specified */ + if (lt9611->dsi1_node) { + lt9611->dsi1 = lt9611_attach_dsi(lt9611, lt9611->dsi1_node); + if (IS_ERR(lt9611->dsi1)) { + ret = PTR_ERR(lt9611->dsi1); + goto err_unregister_dsi0; + } + } + + return 0; + +err_unregister_dsi0: + lt9611_bridge_detach(bridge); + drm_connector_cleanup(<9611->connector); + mipi_dsi_device_unregister(lt9611->dsi0); + + return ret; +} + +static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct lt9611_mode *lt9611_mode = lt9611_find_mode(mode); + + return lt9611_mode ? MODE_OK : MODE_BAD; +} + +static void lt9611_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + if (!lt9611->sleep) + return; + + lt9611_reset(lt9611); + regmap_write(lt9611->regmap, 0x80ee, 0x01); + + lt9611->sleep = false; +} + +static void lt9611_bridge_post_disable(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + lt9611_sleep_setup(lt9611); +} + +static void lt9611_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adj_mode) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + struct hdmi_avi_infoframe avi_frame; + int ret; + + lt9611_bridge_pre_enable(bridge); + + lt9611_mipi_input_digital(lt9611, mode); + lt9611_pll_setup(lt9611, mode); + lt9611_mipi_video_setup(lt9611, mode); + lt9611_pcr_setup(lt9611, mode); + + ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame, + <9611->connector, + mode); + if (!ret) + lt9611->vic = avi_frame.video_code; +} + +static enum drm_connector_status lt9611_bridge_detect(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + unsigned int reg_val = 0; + int connected; + + regmap_read(lt9611->regmap, 0x825e, ®_val); + connected = reg_val & BIT(2); + + lt9611->status = connected ? connector_status_connected : + connector_status_disconnected; + + return lt9611->status; +} + +static struct edid *lt9611_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + lt9611_power_on(lt9611); + return drm_do_get_edid(connector, lt9611_get_edid_block, lt9611); +} + +static void lt9611_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct lt9611 *lt9611 = bridge_to_lt9611(bridge); + + lt9611_enable_hpd_interrupts(lt9611); +} + +static const struct drm_bridge_funcs lt9611_bridge_funcs = { + .attach = lt9611_bridge_attach, + .detach = lt9611_bridge_detach, + .mode_valid = lt9611_bridge_mode_valid, + .enable = lt9611_bridge_enable, + .disable = lt9611_bridge_disable, + .post_disable = lt9611_bridge_post_disable, + .mode_set = lt9611_bridge_mode_set, + .detect = lt9611_bridge_detect, + .get_edid = lt9611_bridge_get_edid, + .hpd_enable = lt9611_bridge_hpd_enable, +}; + +static int lt9611_parse_dt(struct device *dev, + struct lt9611 *lt9611) +{ + lt9611->dsi0_node = of_graph_get_remote_node(dev->of_node, 1, -1); + if (!lt9611->dsi0_node) { + dev_err(lt9611->dev, "failed to get remote node for primary dsi\n"); + return -ENODEV; + } + + lt9611->dsi1_node = of_graph_get_remote_node(dev->of_node, 2, -1); + + lt9611->ac_mode = of_property_read_bool(dev->of_node, "lt,ac-mode"); + + return 0; +} + +static int lt9611_gpio_init(struct lt9611 *lt9611) +{ + struct device *dev = lt9611->dev; + + lt9611->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(lt9611->reset_gpio)) { + dev_err(dev, "failed to acquire reset gpio\n"); + return PTR_ERR(lt9611->reset_gpio); + } + + lt9611->enable_gpio = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(lt9611->enable_gpio)) { + dev_err(dev, "failed to acquire enable gpio\n"); + return PTR_ERR(lt9611->enable_gpio); + } + + return 0; +} + +static int lt9611_read_device_rev(struct lt9611 *lt9611) +{ + unsigned int rev; + int ret; + + regmap_write(lt9611->regmap, 0x80ee, 0x01); + ret = regmap_read(lt9611->regmap, 0x8002, &rev); + if (ret) + dev_err(lt9611->dev, "failed to read revision: %d\n", ret); + else + dev_info(lt9611->dev, "LT9611 revision: 0x%x\n", rev); + + return ret; +} + +static int lt9611_hdmi_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) +{ + struct lt9611 *lt9611 = data; + + if (hparms->sample_rate == 48000) + regmap_write(lt9611->regmap, 0x840f, 0x2b); + else if (hparms->sample_rate == 96000) + regmap_write(lt9611->regmap, 0x840f, 0xab); + else + return -EINVAL; + + regmap_write(lt9611->regmap, 0x8435, 0x00); + regmap_write(lt9611->regmap, 0x8436, 0x18); + regmap_write(lt9611->regmap, 0x8437, 0x00); + + return 0; +} + +static int lt9611_audio_startup(struct device *dev, void *data) +{ + struct lt9611 *lt9611 = data; + + regmap_write(lt9611->regmap, 0x82d6, 0x8c); + regmap_write(lt9611->regmap, 0x82d7, 0x04); + + regmap_write(lt9611->regmap, 0x8406, 0x08); + regmap_write(lt9611->regmap, 0x8407, 0x10); + + regmap_write(lt9611->regmap, 0x8434, 0xd5); + + return 0; +} + +static void lt9611_audio_shutdown(struct device *dev, void *data) +{ + struct lt9611 *lt9611 = data; + + regmap_write(lt9611->regmap, 0x8406, 0x00); + regmap_write(lt9611->regmap, 0x8407, 0x00); +} + +static int lt9611_hdmi_i2s_get_dai_id(struct snd_soc_component *component, + struct device_node *endpoint) +{ + struct of_endpoint of_ep; + int ret; + + ret = of_graph_parse_endpoint(endpoint, &of_ep); + if (ret < 0) + return ret; + + /* + * HDMI sound should be located as reg = <2> + * Then, it is sound port 0 + */ + if (of_ep.port == 2) + return 0; + + return -EINVAL; +} + +static const struct hdmi_codec_ops lt9611_codec_ops = { + .hw_params = lt9611_hdmi_hw_params, + .audio_shutdown = lt9611_audio_shutdown, + .audio_startup = lt9611_audio_startup, + .get_dai_id = lt9611_hdmi_i2s_get_dai_id, +}; + +static struct hdmi_codec_pdata codec_data = { + .ops = <9611_codec_ops, + .max_i2s_channels = 8, + .i2s = 1, +}; + +static int lt9611_audio_init(struct device *dev, struct lt9611 *lt9611) +{ + codec_data.data = lt9611; + lt9611->audio_pdev = + platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, + PLATFORM_DEVID_AUTO, + &codec_data, sizeof(codec_data)); + + return PTR_ERR_OR_ZERO(lt9611->audio_pdev); +} + +static void lt9611_audio_exit(struct lt9611 *lt9611) +{ + if (lt9611->audio_pdev) { + platform_device_unregister(lt9611->audio_pdev); + lt9611->audio_pdev = NULL; + } +} + +static int lt9611_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lt9611 *lt9611; + struct device *dev = &client->dev; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(dev, "device doesn't support I2C\n"); + return -ENODEV; + } + + lt9611 = devm_kzalloc(dev, sizeof(*lt9611), GFP_KERNEL); + if (!lt9611) + return -ENOMEM; + + lt9611->dev = &client->dev; + lt9611->client = client; + lt9611->sleep = false; + + lt9611->regmap = devm_regmap_init_i2c(client, <9611_regmap_config); + if (IS_ERR(lt9611->regmap)) { + dev_err(lt9611->dev, "regmap i2c init failed\n"); + return PTR_ERR(lt9611->regmap); + } + + ret = lt9611_parse_dt(&client->dev, lt9611); + if (ret) { + dev_err(dev, "failed to parse device tree\n"); + return ret; + } + + ret = lt9611_gpio_init(lt9611); + if (ret < 0) + goto err_of_put; + + ret = lt9611_regulator_init(lt9611); + if (ret < 0) + goto err_of_put; + + lt9611_assert_5v(lt9611); + + ret = lt9611_regulator_enable(lt9611); + if (ret) + goto err_of_put; + + lt9611_reset(lt9611); + + ret = lt9611_read_device_rev(lt9611); + if (ret) { + dev_err(dev, "failed to read chip rev\n"); + goto err_disable_regulators; + } + + ret = devm_request_threaded_irq(dev, client->irq, NULL, + lt9611_irq_thread_handler, + IRQF_ONESHOT, "lt9611", lt9611); + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto err_disable_regulators; + } + + i2c_set_clientdata(client, lt9611); + + lt9611->bridge.funcs = <9611_bridge_funcs; + lt9611->bridge.of_node = client->dev.of_node; + lt9611->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_MODES; + lt9611->bridge.type = DRM_MODE_CONNECTOR_HDMIA; + + drm_bridge_add(<9611->bridge); + + lt9611_enable_hpd_interrupts(lt9611); + + return lt9611_audio_init(dev, lt9611); + +err_disable_regulators: + regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies); + +err_of_put: + of_node_put(lt9611->dsi1_node); + of_node_put(lt9611->dsi0_node); + + return ret; +} + +static int lt9611_remove(struct i2c_client *client) +{ + struct lt9611 *lt9611 = i2c_get_clientdata(client); + + disable_irq(client->irq); + lt9611_audio_exit(lt9611); + drm_bridge_remove(<9611->bridge); + + regulator_bulk_disable(ARRAY_SIZE(lt9611->supplies), lt9611->supplies); + + of_node_put(lt9611->dsi1_node); + of_node_put(lt9611->dsi0_node); + + return 0; +} + +static struct i2c_device_id lt9611_id[] = { + { "lontium,lt9611", 0 }, + {} +}; + +static const struct of_device_id lt9611_match_table[] = { + { .compatible = "lontium,lt9611" }, + { } +}; +MODULE_DEVICE_TABLE(of, lt9611_match_table); + +static struct i2c_driver lt9611_driver = { + .driver = { + .name = "lt9611", + .of_match_table = lt9611_match_table, + }, + .probe = lt9611_probe, + .remove = lt9611_remove, + .id_table = lt9611_id, +}; +module_i2c_driver(lt9611_driver); + +MODULE_LICENSE("GPL v2"); -- GitLab From 2a5c2ff5848efc77a115c53d59655aa6016237e8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 13 Apr 2020 20:30:05 +0200 Subject: [PATCH 0027/1494] drm/panel: add connector type to boe,hv070wsa-100 panel The boe,hv070wsa-100 panel is a LVDS panel. Fix connector type to reflect this. With this change users of this panel do not have to specify the connector type. v4: - Add .bpc = 4 (Laurent) v3: - Drop PIXDATA bus_flag, not relevant v2: - Add .bus_format (Laurent) - Add .bus_flags Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200703192417.372164-2-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-simple.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 88493538a147b..54323515ca2c5 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1191,10 +1191,14 @@ static const struct drm_display_mode boe_hv070wsa_mode = { static const struct panel_desc boe_hv070wsa = { .modes = &boe_hv070wsa_mode, .num_modes = 1, + .bpc = 8, .size = { .width = 154, .height = 90, }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .connector_type = DRM_MODE_CONNECTOR_LVDS, }; static const struct drm_display_mode boe_nv101wxmn51_modes[] = { -- GitLab From ddb8e853dc8507ecf9c7b4630857771da1f89752 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:10 +0200 Subject: [PATCH 0028/1494] drm/panel: panel-simple: validate panel description Warn if we detect a panel with incomplete/wrong description. This is inspired by a similar patch by Laurent that introduced checks for LVDS panels - this extends the checks to the remaining type of connectors. This is known to warn for some of the existing panels but added despite this as we need help from people using the panels to add the missing info. The checks are not complete but will catch the most common mistakes. The checks at the same time serve as documentation for the minimum required description for a panel. The checks uses dev_warn() as we know this will hit. WARN() was too noisy at the moment for anything else than LVDS. v3: - %d => %u for bpc (Laurent) v2: - Use dev_warn (Laurent) - Check for empty bus_flags Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-2-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-simple.c | 41 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 54323515ca2c5..2c972cc8d1970 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -500,6 +500,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) struct panel_simple *panel; struct display_timing dt; struct device_node *ddc; + u32 bus_flags; int err; panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); @@ -549,8 +550,12 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) panel_simple_parse_panel_timing_node(dev, panel, &dt); } - if (desc->connector_type == DRM_MODE_CONNECTOR_LVDS) { - /* Catch common mistakes for LVDS panels. */ + /* Catch common mistakes for panels. */ + switch (desc->connector_type) { + case 0: + dev_warn(dev, "Specify missing connector_type\n"); + break; + case DRM_MODE_CONNECTOR_LVDS: WARN_ON(desc->bus_flags & ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH | @@ -564,6 +569,38 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) WARN_ON((desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_SPWG || desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA) && desc->bpc != 8); + break; + case DRM_MODE_CONNECTOR_eDP: + if (desc->bus_format == 0) + dev_warn(dev, "Specify missing bus_format\n"); + if (desc->bpc != 6 && desc->bpc != 8) + dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc); + break; + case DRM_MODE_CONNECTOR_DSI: + if (desc->bpc != 6 && desc->bpc != 8) + dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc); + break; + case DRM_MODE_CONNECTOR_DPI: + bus_flags = DRM_BUS_FLAG_DE_LOW | + DRM_BUS_FLAG_DE_HIGH | + DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE | + DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_DATA_MSB_TO_LSB | + DRM_BUS_FLAG_DATA_LSB_TO_MSB | + DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE | + DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE; + if (desc->bus_flags & ~bus_flags) + dev_warn(dev, "Unexpected bus_flags(%d)\n", desc->bus_flags & ~bus_flags); + if (!(desc->bus_flags & bus_flags)) + dev_warn(dev, "Specify missing bus_flags\n"); + if (desc->bus_format == 0) + dev_warn(dev, "Specify missing bus_format\n"); + if (desc->bpc != 6 && desc->bpc != 8) + dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc); + break; + default: + dev_warn(dev, "Specify a valid connector_type: %d\n", desc->connector_type); + break; } drm_panel_init(&panel->base, dev, &panel_simple_funcs, -- GitLab From 9f069c6fbc72669311723262766047f577dba496 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:11 +0200 Subject: [PATCH 0029/1494] drm/panel: panel-simple: add default connector_type All panels shall report a connector type. panel-simple has a lot of panels with no connector_type, and for these fall back to DPI as the default. v2: - Rebased on top of validation of panel description Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-3-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-simple.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 2c972cc8d1970..5cba33394083a 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -500,6 +500,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) struct panel_simple *panel; struct display_timing dt; struct device_node *ddc; + int connector_type; u32 bus_flags; int err; @@ -550,10 +551,12 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) panel_simple_parse_panel_timing_node(dev, panel, &dt); } + connector_type = desc->connector_type; /* Catch common mistakes for panels. */ - switch (desc->connector_type) { + switch (connector_type) { case 0: dev_warn(dev, "Specify missing connector_type\n"); + connector_type = DRM_MODE_CONNECTOR_DPI; break; case DRM_MODE_CONNECTOR_LVDS: WARN_ON(desc->bus_flags & @@ -600,11 +603,11 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) break; default: dev_warn(dev, "Specify a valid connector_type: %d\n", desc->connector_type); + connector_type = DRM_MODE_CONNECTOR_DPI; break; } - drm_panel_init(&panel->base, dev, &panel_simple_funcs, - desc->connector_type); + drm_panel_init(&panel->base, dev, &panel_simple_funcs, connector_type); err = drm_panel_of_backlight(&panel->base); if (err) -- GitLab From 385ca38da29c214e03f526d28346176e1b500db8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:12 +0200 Subject: [PATCH 0030/1494] drm/bridge: tc358764: drop drm_connector_(un)register Drop drm_connector handling that is not needed: - drm_dev_register() in the display controller driver takes care of registering connectors. So the call to drm_connector_register() call is not needed in the bridge driver. - Use of drm_connector_unregister() is only required for drivers that explicit have called drm_dev_register. - The reference counting using drm_connector_put() is likewise not needed. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-4-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358764.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index 5ac1430fab049..a277739fab581 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -375,7 +375,6 @@ static int tc358764_attach(struct drm_bridge *bridge, drm_connector_attach_encoder(&ctx->connector, bridge->encoder); drm_panel_attach(ctx->panel, &ctx->connector); ctx->connector.funcs->reset(&ctx->connector); - drm_connector_register(&ctx->connector); return 0; } @@ -384,10 +383,8 @@ static void tc358764_detach(struct drm_bridge *bridge) { struct tc358764 *ctx = bridge_to_tc358764(bridge); - drm_connector_unregister(&ctx->connector); drm_panel_detach(ctx->panel); ctx->panel = NULL; - drm_connector_put(&ctx->connector); } static const struct drm_bridge_funcs tc358764_bridge_funcs = { -- GitLab From 1644127f83bc72fcf2564dfbcab5802b587d964e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:13 +0200 Subject: [PATCH 0031/1494] drm/bridge: tc358764: add drm_panel_bridge support Prepare the tc358764 bridge driver for use in a chained setup by replacing direct use of drm_panel with drm_panel_bridge support. The bridge panel will use the connector type reported by the panel, where the connector for this driver hardcodes DRM_MODE_CONNECTOR_LVDS. The tc358764 did not add any additional info the the connector so the connector creation is passed to the bridge panel driver. v3: - Merge with patch to make connector creation optional to avoid creating two connectors (Laurent) - Pass connector creation to bridge panel, as this bridge driver did not add any extra info to the connector. - Set bridge.type to DRM_MODE_CONNECTOR_LVDS. v2: - Use PTR_ERR_OR_ZERO() (kbuild test robot) Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: kbuild test robot <lkp@intel.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-5-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358764.c | 106 +++++------------------------- 1 file changed, 15 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index a277739fab581..d89394bc5aa4d 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -153,10 +153,9 @@ static const char * const tc358764_supplies[] = { struct tc358764 { struct device *dev; struct drm_bridge bridge; - struct drm_connector connector; struct regulator_bulk_data supplies[ARRAY_SIZE(tc358764_supplies)]; struct gpio_desc *gpio_reset; - struct drm_panel *panel; + struct drm_bridge *panel_bridge; int error; }; @@ -210,12 +209,6 @@ static inline struct tc358764 *bridge_to_tc358764(struct drm_bridge *bridge) return container_of(bridge, struct tc358764, bridge); } -static inline -struct tc358764 *connector_to_tc358764(struct drm_connector *connector) -{ - return container_of(connector, struct tc358764, connector); -} - static int tc358764_init(struct tc358764 *ctx) { u32 v = 0; @@ -278,43 +271,11 @@ static void tc358764_reset(struct tc358764 *ctx) usleep_range(1000, 2000); } -static int tc358764_get_modes(struct drm_connector *connector) -{ - struct tc358764 *ctx = connector_to_tc358764(connector); - - return drm_panel_get_modes(ctx->panel, connector); -} - -static const -struct drm_connector_helper_funcs tc358764_connector_helper_funcs = { - .get_modes = tc358764_get_modes, -}; - -static const struct drm_connector_funcs tc358764_connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .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 void tc358764_disable(struct drm_bridge *bridge) -{ - struct tc358764 *ctx = bridge_to_tc358764(bridge); - int ret = drm_panel_disable(bridge_to_tc358764(bridge)->panel); - - if (ret < 0) - dev_err(ctx->dev, "error disabling panel (%d)\n", ret); -} - static void tc358764_post_disable(struct drm_bridge *bridge) { struct tc358764 *ctx = bridge_to_tc358764(bridge); int ret; - ret = drm_panel_unprepare(ctx->panel); - if (ret < 0) - dev_err(ctx->dev, "error unpreparing panel (%d)\n", ret); tc358764_reset(ctx); usleep_range(10000, 15000); ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); @@ -335,70 +296,28 @@ static void tc358764_pre_enable(struct drm_bridge *bridge) ret = tc358764_init(ctx); if (ret < 0) dev_err(ctx->dev, "error initializing bridge (%d)\n", ret); - ret = drm_panel_prepare(ctx->panel); - if (ret < 0) - dev_err(ctx->dev, "error preparing panel (%d)\n", ret); -} - -static void tc358764_enable(struct drm_bridge *bridge) -{ - struct tc358764 *ctx = bridge_to_tc358764(bridge); - int ret = drm_panel_enable(ctx->panel); - - if (ret < 0) - dev_err(ctx->dev, "error enabling panel (%d)\n", ret); } static int tc358764_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) -{ - struct tc358764 *ctx = bridge_to_tc358764(bridge); - struct drm_device *drm = bridge->dev; - int ret; - - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - - ctx->connector.polled = DRM_CONNECTOR_POLL_HPD; - ret = drm_connector_init(drm, &ctx->connector, - &tc358764_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - if (ret) { - DRM_ERROR("Failed to initialize connector\n"); - return ret; - } - - drm_connector_helper_add(&ctx->connector, - &tc358764_connector_helper_funcs); - drm_connector_attach_encoder(&ctx->connector, bridge->encoder); - drm_panel_attach(ctx->panel, &ctx->connector); - ctx->connector.funcs->reset(&ctx->connector); - - return 0; -} - -static void tc358764_detach(struct drm_bridge *bridge) { struct tc358764 *ctx = bridge_to_tc358764(bridge); - drm_panel_detach(ctx->panel); - ctx->panel = NULL; + return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, + bridge, flags); } static const struct drm_bridge_funcs tc358764_bridge_funcs = { - .disable = tc358764_disable, .post_disable = tc358764_post_disable, - .enable = tc358764_enable, .pre_enable = tc358764_pre_enable, .attach = tc358764_attach, - .detach = tc358764_detach, }; static int tc358764_parse_dt(struct tc358764 *ctx) { + struct drm_bridge *panel_bridge; struct device *dev = ctx->dev; + struct drm_panel *panel; int ret; ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); @@ -407,12 +326,16 @@ static int tc358764_parse_dt(struct tc358764 *ctx) return PTR_ERR(ctx->gpio_reset); } - ret = drm_of_find_panel_or_bridge(ctx->dev->of_node, 1, 0, &ctx->panel, - NULL); - if (ret && ret != -EPROBE_DEFER) - dev_err(dev, "cannot find panel (%d)\n", ret); + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); + if (ret) + return ret; - return ret; + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + ctx->panel_bridge = panel_bridge; + return 0; } static int tc358764_configure_regulators(struct tc358764 *ctx) @@ -458,6 +381,7 @@ static int tc358764_probe(struct mipi_dsi_device *dsi) return ret; ctx->bridge.funcs = &tc358764_bridge_funcs; + ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS; ctx->bridge.of_node = dev->of_node; drm_bridge_add(&ctx->bridge); -- GitLab From 5b851515eff335a3b09de46a0080a64d66085875 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:17 +0200 Subject: [PATCH 0032/1494] drm/bridge: parade-ps8622: add drm_panel_bridge support Prepare the bridge driver for use in a chained setup by replacing direct use of drm_panel with drm_panel_bridge support. The connecter is now either created by the panel bridge or the display driver. So all code for connector creation in this driver is no longer relevant and thus dropped. The connector code had some special polling handling: connector.polled = DRM_CONNECTOR_POLL_HPD; drm_helper_hpd_irq_event(ps8622->bridge.dev); This code was most likely added to speed up detection of the connector. If really needed then this functionality belongs somewhere else. Note: the bridge panel will use the connector type from the panel. v2: - Fix to avoid creating connector twice (Laurent) - Drop all connector code - defer to bridge panel - Use panel_bridge for local variable to align with other drivers - Set bridge.type to DRM_MODE_CONNECTOR_LVDS; Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-9-sam@ravnborg.org --- drivers/gpu/drm/bridge/parade-ps8622.c | 100 ++++--------------------- 1 file changed, 13 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index d789ea2a7fb9e..614b19f0f1b73 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -42,10 +42,9 @@ #endif struct ps8622_bridge { - struct drm_connector connector; struct i2c_client *client; struct drm_bridge bridge; - struct drm_panel *panel; + struct drm_bridge *panel_bridge; struct regulator *v12; struct backlight_device *bl; @@ -64,12 +63,6 @@ static inline struct ps8622_bridge * return container_of(bridge, struct ps8622_bridge, bridge); } -static inline struct ps8622_bridge * - connector_to_ps8622(struct drm_connector *connector) -{ - return container_of(connector, struct ps8622_bridge, connector); -} - static int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val) { int ret; @@ -365,11 +358,6 @@ static void ps8622_pre_enable(struct drm_bridge *bridge) DRM_ERROR("fails to enable ps8622->v12"); } - if (drm_panel_prepare(ps8622->panel)) { - DRM_ERROR("failed to prepare panel\n"); - return; - } - gpiod_set_value(ps8622->gpio_slp, 1); /* @@ -399,24 +387,9 @@ static void ps8622_pre_enable(struct drm_bridge *bridge) ps8622->enabled = true; } -static void ps8622_enable(struct drm_bridge *bridge) -{ - struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); - - if (drm_panel_enable(ps8622->panel)) { - DRM_ERROR("failed to enable panel\n"); - return; - } -} - static void ps8622_disable(struct drm_bridge *bridge) { - struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); - - if (drm_panel_disable(ps8622->panel)) { - DRM_ERROR("failed to disable panel\n"); - return; - } + /* Delay after panel is disabled */ msleep(PS8622_PWMO_END_T12_MS); } @@ -436,11 +409,6 @@ static void ps8622_post_disable(struct drm_bridge *bridge) */ gpiod_set_value(ps8622->gpio_slp, 0); - if (drm_panel_unprepare(ps8622->panel)) { - DRM_ERROR("failed to unprepare panel\n"); - return; - } - if (ps8622->v12) regulator_disable(ps8622->v12); @@ -455,67 +423,17 @@ static void ps8622_post_disable(struct drm_bridge *bridge) msleep(PS8622_POWER_OFF_T17_MS); } -static int ps8622_get_modes(struct drm_connector *connector) -{ - struct ps8622_bridge *ps8622; - - ps8622 = connector_to_ps8622(connector); - - return drm_panel_get_modes(ps8622->panel, connector); -} - -static const struct drm_connector_helper_funcs ps8622_connector_helper_funcs = { - .get_modes = ps8622_get_modes, -}; - -static const struct drm_connector_funcs ps8622_connector_funcs = { - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .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 int ps8622_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge); - int ret; - - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - - ps8622->connector.polled = DRM_CONNECTOR_POLL_HPD; - ret = drm_connector_init(bridge->dev, &ps8622->connector, - &ps8622_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - if (ret) { - DRM_ERROR("Failed to initialize connector with drm\n"); - return ret; - } - drm_connector_helper_add(&ps8622->connector, - &ps8622_connector_helper_funcs); - drm_connector_register(&ps8622->connector); - drm_connector_attach_encoder(&ps8622->connector, - bridge->encoder); - - if (ps8622->panel) - drm_panel_attach(ps8622->panel, &ps8622->connector); - - drm_helper_hpd_irq_event(ps8622->connector.dev); - - return ret; + return drm_bridge_attach(ps8622->bridge.encoder, ps8622->panel_bridge, + &ps8622->bridge, flags); } static const struct drm_bridge_funcs ps8622_bridge_funcs = { .pre_enable = ps8622_pre_enable, - .enable = ps8622_enable, .disable = ps8622_disable, .post_disable = ps8622_post_disable, .attach = ps8622_attach, @@ -533,16 +451,23 @@ static int ps8622_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct ps8622_bridge *ps8622; + struct drm_bridge *panel_bridge; + struct drm_panel *panel; int ret; ps8622 = devm_kzalloc(dev, sizeof(*ps8622), GFP_KERNEL); if (!ps8622) return -ENOMEM; - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL); + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, NULL); if (ret) return ret; + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + ps8622->panel_bridge = panel_bridge; ps8622->client = client; ps8622->v12 = devm_regulator_get(dev, "vdd12"); @@ -595,6 +520,7 @@ static int ps8622_probe(struct i2c_client *client, } ps8622->bridge.funcs = &ps8622_bridge_funcs; + ps8622->bridge.type = DRM_MODE_CONNECTOR_LVDS; ps8622->bridge.of_node = dev->of_node; drm_bridge_add(&ps8622->bridge); -- GitLab From 43c601a6e85e9a1c2a013006345ccf12af578c10 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:18 +0200 Subject: [PATCH 0033/1494] drm/bridge: megachips: add helper to create connector Factor out connector creation to a small helper function. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Peter Senna Tschudin <peter.senna@gmail.com> Cc: Martin Donnelly <martin.donnelly@ge.com> Cc: Martyn Welch <martyn.welch@collabora.co.uk> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-10-sam@ravnborg.org --- .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 6200f12a37e69..258e0525cdcce 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -191,6 +191,32 @@ static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; +static int ge_b850v3_lvds_create_connector(struct drm_bridge *bridge) +{ + struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector; + int ret; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + connector->polled = DRM_CONNECTOR_POLL_HPD; + + drm_connector_helper_add(connector, + &ge_b850v3_lvds_connector_helper_funcs); + + ret = drm_connector_init(bridge->dev, connector, + &ge_b850v3_lvds_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + return drm_connector_attach_encoder(connector, bridge->encoder); +} + static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id) { struct i2c_client *stdp4028_i2c @@ -209,7 +235,6 @@ static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id) static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { - struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector; struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c; int ret; @@ -219,25 +244,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, return -EINVAL; } - if (!bridge->encoder) { - DRM_ERROR("Parent encoder object not found"); - return -ENODEV; - } - - connector->polled = DRM_CONNECTOR_POLL_HPD; - - drm_connector_helper_add(connector, - &ge_b850v3_lvds_connector_helper_funcs); - - ret = drm_connector_init(bridge->dev, connector, - &ge_b850v3_lvds_connector_funcs, - DRM_MODE_CONNECTOR_DisplayPort); - if (ret) { - DRM_ERROR("Failed to initialize connector with drm\n"); - return ret; - } - - ret = drm_connector_attach_encoder(connector, bridge->encoder); + ret = ge_b850v3_lvds_create_connector(bridge); if (ret) return ret; -- GitLab From 77860a7c892eca5a3a4b0d5e0e7065f1cd45c655 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:19 +0200 Subject: [PATCH 0034/1494] drm/bridge: megachips: get drm_device from bridge Fix so drm_device is read from the bridge. This is a preparation for the connector being optional. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Peter Senna Tschudin <peter.senna@gmail.com> Cc: Martin Donnelly <martin.donnelly@ge.com> Cc: Martyn Welch <martyn.welch@collabora.co.uk> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-11-sam@ravnborg.org --- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 258e0525cdcce..cf1dfbc88acf0 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -226,8 +226,8 @@ static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id) STDP4028_DPTX_IRQ_STS_REG, STDP4028_DPTX_IRQ_CLEAR); - if (ge_b850v3_lvds_ptr->connector.dev) - drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->connector.dev); + if (ge_b850v3_lvds_ptr->bridge.dev) + drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->bridge.dev); return IRQ_HANDLED; } -- GitLab From a3d495ce5c0b25739b6e450d0810567819a96735 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:20 +0200 Subject: [PATCH 0035/1494] drm/bridge: megachips: enable detect bridge operation To prepare for use in a chained bridge setup enable the detect operation. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Peter Senna Tschudin <peter.senna@gmail.com> Cc: Martin Donnelly <martin.donnelly@ge.com> Cc: Martyn Welch <martyn.welch@collabora.co.uk> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-12-sam@ravnborg.org --- .../gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index cf1dfbc88acf0..450dca33ea48f 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -163,8 +163,7 @@ drm_connector_helper_funcs ge_b850v3_lvds_connector_helper_funcs = { .mode_valid = ge_b850v3_lvds_mode_valid, }; -static enum drm_connector_status ge_b850v3_lvds_detect( - struct drm_connector *connector, bool force) +static enum drm_connector_status ge_b850v3_lvds_bridge_detect(struct drm_bridge *bridge) { struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c; @@ -182,6 +181,12 @@ static enum drm_connector_status ge_b850v3_lvds_detect( return connector_status_unknown; } +static enum drm_connector_status ge_b850v3_lvds_detect(struct drm_connector *connector, + bool force) +{ + return ge_b850v3_lvds_bridge_detect(&ge_b850v3_lvds_ptr->bridge); +} + static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .detect = ge_b850v3_lvds_detect, @@ -263,6 +268,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = { .attach = ge_b850v3_lvds_attach, + .detect = ge_b850v3_lvds_bridge_detect, }; static int ge_b850v3_lvds_init(struct device *dev) @@ -317,6 +323,7 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, /* drm bridge initialization */ ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; + ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT; ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); -- GitLab From 489ce80fa4942ba855b937eee7f621d52ccdff3f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:21 +0200 Subject: [PATCH 0036/1494] drm/bridge: megachips: add get_edid bridge operation To prepare for a chained bridge setup add support for the get_edid bridge operation. There is no need for a copy of the edid - so drop the pointer to the copy. v2: - Fix so we do not leak memory (Laurent) Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Peter Senna Tschudin <peter.senna@gmail.com> Cc: Martin Donnelly <martin.donnelly@ge.com> Cc: Martyn Welch <martyn.welch@collabora.co.uk> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-13-sam@ravnborg.org --- .../bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 450dca33ea48f..f7b55dc374ac3 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -61,7 +61,6 @@ struct ge_b850v3_lvds { struct drm_bridge bridge; struct i2c_client *stdp4028_i2c; struct i2c_client *stdp2690_i2c; - struct edid *edid; }; static struct ge_b850v3_lvds *ge_b850v3_lvds_ptr; @@ -131,22 +130,26 @@ static u8 *stdp2690_get_edid(struct i2c_client *client) return NULL; } -static int ge_b850v3_lvds_get_modes(struct drm_connector *connector) +static struct edid *ge_b850v3_lvds_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) { struct i2c_client *client; - int num_modes = 0; client = ge_b850v3_lvds_ptr->stdp2690_i2c; - kfree(ge_b850v3_lvds_ptr->edid); - ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client); + return (struct edid *)stdp2690_get_edid(client); +} - if (ge_b850v3_lvds_ptr->edid) { - drm_connector_update_edid_property(connector, - ge_b850v3_lvds_ptr->edid); - num_modes = drm_add_edid_modes(connector, - ge_b850v3_lvds_ptr->edid); - } +static int ge_b850v3_lvds_get_modes(struct drm_connector *connector) +{ + struct edid *edid; + int num_modes; + + edid = ge_b850v3_lvds_get_edid(&ge_b850v3_lvds_ptr->bridge, connector); + + drm_connector_update_edid_property(connector, edid); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); return num_modes; } @@ -269,6 +272,7 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = { .attach = ge_b850v3_lvds_attach, .detect = ge_b850v3_lvds_bridge_detect, + .get_edid = ge_b850v3_lvds_get_edid, }; static int ge_b850v3_lvds_init(struct device *dev) @@ -304,8 +308,6 @@ static void ge_b850v3_lvds_remove(void) drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge); - kfree(ge_b850v3_lvds_ptr->edid); - ge_b850v3_lvds_ptr = NULL; out: mutex_unlock(&ge_b850v3_lvds_dev_mutex); @@ -323,7 +325,8 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, /* drm bridge initialization */ ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; - ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT; + ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT | + DRM_BRIDGE_OP_EDID; ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); -- GitLab From a8ef18d7dd4817cc35ab03358b3fe2aafad22d9f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sun, 26 Jul 2020 22:33:22 +0200 Subject: [PATCH 0037/1494] drm/bridge: megachips: make connector creation optional Make the connector creation optional to enable usage of the megachips-stdpxxxx-ge-b850v3-fw bridge with the DRM bridge connector helper. v2: - Set bridge.type to DRM_MODE_CONNECTOR_DisplayPort Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Peter Senna Tschudin <peter.senna@gmail.com> Cc: Martin Donnelly <martin.donnelly@ge.com> Cc: Martyn Welch <martyn.welch@collabora.co.uk> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-14-sam@ravnborg.org --- .../drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index f7b55dc374ac3..61a24f265c7ac 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -245,16 +245,6 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, { struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c; - int ret; - - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } - - ret = ge_b850v3_lvds_create_connector(bridge); - if (ret) - return ret; /* Configures the bridge to re-enable interrupts after each ack. */ i2c_smbus_write_word_data(stdp4028_i2c, @@ -266,7 +256,10 @@ static int ge_b850v3_lvds_attach(struct drm_bridge *bridge, STDP4028_DPTX_IRQ_EN_REG, STDP4028_DPTX_IRQ_CONFIG); - return 0; + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; + + return ge_b850v3_lvds_create_connector(bridge); } static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = { @@ -327,6 +320,7 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs; ge_b850v3_lvds_ptr->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; + ge_b850v3_lvds_ptr->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node; drm_bridge_add(&ge_b850v3_lvds_ptr->bridge); -- GitLab From 136d73a8c88d113b46d29c51710fe9e689e1b93e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 27 Jul 2020 19:03:16 +0200 Subject: [PATCH 0038/1494] drm/bridge: tc358767: add detect bridge operation Prepare the bridge driver for chained operation by adding support for the detect operation. v3: - Fix code to make it readable (Laurent) v2: - Do not announce detect operation if there is no hpd pin (Laurent) Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200727170320.959777-2-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358767.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index c2777b226c750..bde89e213882b 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1369,21 +1369,13 @@ static const struct drm_connector_helper_funcs tc_connector_helper_funcs = { .get_modes = tc_connector_get_modes, }; -static enum drm_connector_status tc_connector_detect(struct drm_connector *connector, - bool force) +static enum drm_connector_status tc_bridge_detect(struct drm_bridge *bridge) { - struct tc_data *tc = connector_to_tc(connector); + struct tc_data *tc = bridge_to_tc(bridge); bool conn; u32 val; int ret; - if (tc->hpd_pin < 0) { - if (tc->panel) - return connector_status_connected; - else - return connector_status_unknown; - } - ret = regmap_read(tc->regmap, GPIOI, &val); if (ret) return connector_status_unknown; @@ -1396,6 +1388,20 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne return connector_status_disconnected; } +static enum drm_connector_status +tc_connector_detect(struct drm_connector *connector, bool force) +{ + struct tc_data *tc = connector_to_tc(connector); + + if (tc->hpd_pin >= 0) + return tc_bridge_detect(&tc->bridge); + + if (tc->panel) + return connector_status_connected; + else + return connector_status_unknown; +} + static const struct drm_connector_funcs tc_connector_funcs = { .detect = tc_connector_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -1458,6 +1464,7 @@ static const struct drm_bridge_funcs tc_bridge_funcs = { .disable = tc_bridge_disable, .post_disable = tc_bridge_post_disable, .mode_fixup = tc_bridge_mode_fixup, + .detect = tc_bridge_detect, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) @@ -1680,6 +1687,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) return ret; tc->bridge.funcs = &tc_bridge_funcs; + if (tc->hpd_pin >= 0) + tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; + tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); -- GitLab From 731f4badcb3b47e2b0a1f4971a047fcaa552b406 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 27 Jul 2020 19:03:17 +0200 Subject: [PATCH 0039/1494] drm/bridge: tc358767: add get_edid bridge operation Prepare for chained bridge with the addition of get_edid support. v2: - Fixed handling of edid storage (Laurent) Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200727170320.959777-3-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358767.c | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index bde89e213882b..b26c669f3e910 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -250,8 +250,6 @@ struct tc_data { /* link settings */ struct tc_edp_link link; - /* display edid */ - struct edid *edid; /* current mode */ struct drm_display_mode mode; @@ -1335,11 +1333,19 @@ static void tc_bridge_mode_set(struct drm_bridge *bridge, tc->mode = *mode; } +static struct edid *tc_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct tc_data *tc = bridge_to_tc(bridge); + + return drm_get_edid(connector, &tc->aux.ddc); +} + static int tc_connector_get_modes(struct drm_connector *connector) { struct tc_data *tc = connector_to_tc(connector); + int num_modes; struct edid *edid; - int count; int ret; ret = tc_get_display_props(tc); @@ -1348,21 +1354,15 @@ static int tc_connector_get_modes(struct drm_connector *connector) return 0; } - count = drm_panel_get_modes(tc->panel, connector); - if (count > 0) - return count; - - edid = drm_get_edid(connector, &tc->aux.ddc); - - kfree(tc->edid); - tc->edid = edid; - if (!edid) - return 0; + num_modes = drm_panel_get_modes(tc->panel, connector); + if (num_modes > 0) + return num_modes; - drm_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); + edid = tc_get_edid(&tc->bridge, connector); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); - return count; + return num_modes; } static const struct drm_connector_helper_funcs tc_connector_helper_funcs = { @@ -1465,6 +1465,7 @@ static const struct drm_bridge_funcs tc_bridge_funcs = { .post_disable = tc_bridge_post_disable, .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, + .get_edid = tc_get_edid, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) @@ -1689,6 +1690,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->bridge.funcs = &tc_bridge_funcs; if (tc->hpd_pin >= 0) tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; + tc->bridge.ops |= DRM_BRIDGE_OP_EDID; tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); -- GitLab From de5e6c027ae67dd1dfcd3022593651c24b3f794a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 27 Jul 2020 19:03:18 +0200 Subject: [PATCH 0040/1494] drm/bridge: tc358767: add drm_panel_bridge support With the bridge operations implemented the last step to prepare this driver for a chained setup is the use of the bridge panel driver. The bridge panel driver is only used when a port@2 is present in the DT. So when the display driver requests a connector support both situations: - connector created by bridge panel driver - connector created by this driver And on top, support that the display driver creates the connector, which is the preferred setup. Note: the bridge panel will use the connector type from the panel. v3: - Fix wrong logic in connector creation (Laurent) v2: - Merge connector and drm_panel_bridge patches and fix so we do not create two connectors (Laurent) Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200727170320.959777-4-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358767.c | 67 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index b26c669f3e910..34a3e4e9f7175 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -244,8 +244,8 @@ struct tc_data { struct drm_dp_aux aux; struct drm_bridge bridge; + struct drm_bridge *panel_bridge; struct drm_connector connector; - struct drm_panel *panel; /* link settings */ struct tc_edp_link link; @@ -1234,13 +1234,6 @@ static int tc_stream_disable(struct tc_data *tc) return 0; } -static void tc_bridge_pre_enable(struct drm_bridge *bridge) -{ - struct tc_data *tc = bridge_to_tc(bridge); - - drm_panel_prepare(tc->panel); -} - static void tc_bridge_enable(struct drm_bridge *bridge) { struct tc_data *tc = bridge_to_tc(bridge); @@ -1264,8 +1257,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) tc_main_link_disable(tc); return; } - - drm_panel_enable(tc->panel); } static void tc_bridge_disable(struct drm_bridge *bridge) @@ -1273,8 +1264,6 @@ static void tc_bridge_disable(struct drm_bridge *bridge) struct tc_data *tc = bridge_to_tc(bridge); int ret; - drm_panel_disable(tc->panel); - ret = tc_stream_disable(tc); if (ret < 0) dev_err(tc->dev, "main link stream stop error: %d\n", ret); @@ -1284,13 +1273,6 @@ static void tc_bridge_disable(struct drm_bridge *bridge) dev_err(tc->dev, "main link disable error: %d\n", ret); } -static void tc_bridge_post_disable(struct drm_bridge *bridge) -{ - struct tc_data *tc = bridge_to_tc(bridge); - - drm_panel_unprepare(tc->panel); -} - static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adj) @@ -1354,9 +1336,11 @@ static int tc_connector_get_modes(struct drm_connector *connector) return 0; } - num_modes = drm_panel_get_modes(tc->panel, connector); - if (num_modes > 0) - return num_modes; + if (tc->panel_bridge) { + num_modes = drm_bridge_get_modes(tc->panel_bridge, connector); + if (num_modes > 0) + return num_modes; + } edid = tc_get_edid(&tc->bridge, connector); num_modes = drm_add_edid_modes(connector, edid); @@ -1396,7 +1380,7 @@ tc_connector_detect(struct drm_connector *connector, bool force) if (tc->hpd_pin >= 0) return tc_bridge_detect(&tc->bridge); - if (tc->panel) + if (tc->panel_bridge) return connector_status_connected; else return connector_status_unknown; @@ -1419,16 +1403,20 @@ static int tc_bridge_attach(struct drm_bridge *bridge, struct drm_device *drm = bridge->dev; int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; + if (tc->panel_bridge) { + /* If a connector is required then this driver shall create it */ + ret = drm_bridge_attach(tc->bridge.encoder, tc->panel_bridge, + &tc->bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret) + return ret; } + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; + /* Create DP/eDP connector */ drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs); - ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, - tc->panel ? DRM_MODE_CONNECTOR_eDP : - DRM_MODE_CONNECTOR_DisplayPort); + ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, tc->bridge.type); if (ret) return ret; @@ -1441,9 +1429,6 @@ static int tc_bridge_attach(struct drm_bridge *bridge, DRM_CONNECTOR_POLL_DISCONNECT; } - if (tc->panel) - drm_panel_attach(tc->panel, &tc->connector); - drm_display_info_set_bus_formats(&tc->connector.display_info, &bus_format, 1); tc->connector.display_info.bus_flags = @@ -1459,10 +1444,8 @@ static const struct drm_bridge_funcs tc_bridge_funcs = { .attach = tc_bridge_attach, .mode_valid = tc_mode_valid, .mode_set = tc_bridge_mode_set, - .pre_enable = tc_bridge_pre_enable, .enable = tc_bridge_enable, .disable = tc_bridge_disable, - .post_disable = tc_bridge_post_disable, .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, .get_edid = tc_get_edid, @@ -1555,6 +1538,7 @@ static irqreturn_t tc_irq_handler(int irq, void *arg) static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; + struct drm_panel *panel; struct tc_data *tc; int ret; @@ -1565,10 +1549,23 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->dev = dev; /* port@2 is the output port */ - ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL); + ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, NULL); if (ret && ret != -ENODEV) return ret; + if (panel) { + struct drm_bridge *panel_bridge; + + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + tc->panel_bridge = panel_bridge; + tc->bridge.type = DRM_MODE_CONNECTOR_eDP; + } else { + tc->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; + } + /* Shut down GPIO is optional */ tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); if (IS_ERR(tc->sd_gpio)) -- GitLab From 4151c14cdda689fd64299736f2779668a9fb3a7d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 27 Jul 2020 19:03:19 +0200 Subject: [PATCH 0041/1494] drm/bridge: nxp-ptn3460: add get_edid bridge operation Add the get_edid() bridge operation to prepare for use as a chained bridge. Add helper function that is also used by the connector. v2: - Fix memory leak (Laurent) - Do not save a copy of edid, read it when needed Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200727170320.959777-5-sam@ravnborg.org --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 43 ++++++++++++++++------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 438e566ce0a4a..2805c8938f985 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -29,7 +29,6 @@ struct ptn3460_bridge { struct drm_connector connector; struct i2c_client *client; struct drm_bridge bridge; - struct edid *edid; struct drm_panel *panel; struct gpio_desc *gpio_pd_n; struct gpio_desc *gpio_rst_n; @@ -184,17 +183,13 @@ static void ptn3460_post_disable(struct drm_bridge *bridge) } } -static int ptn3460_get_modes(struct drm_connector *connector) +static struct edid *ptn3460_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) { - struct ptn3460_bridge *ptn_bridge; - u8 *edid; - int ret, num_modes = 0; + struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); bool power_off; - - ptn_bridge = connector_to_ptn3460(connector); - - if (ptn_bridge->edid) - return drm_add_edid_modes(connector, ptn_bridge->edid); + u8 *edid; + int ret; power_off = !ptn_bridge->enabled; ptn3460_pre_enable(&ptn_bridge->bridge); @@ -202,30 +197,40 @@ static int ptn3460_get_modes(struct drm_connector *connector) edid = kmalloc(EDID_LENGTH, GFP_KERNEL); if (!edid) { DRM_ERROR("Failed to allocate EDID\n"); - return 0; + goto out; } ret = ptn3460_read_bytes(ptn_bridge, PTN3460_EDID_ADDR, edid, - EDID_LENGTH); + EDID_LENGTH); if (ret) { kfree(edid); + edid = NULL; goto out; } - ptn_bridge->edid = (struct edid *)edid; - drm_connector_update_edid_property(connector, ptn_bridge->edid); - - num_modes = drm_add_edid_modes(connector, ptn_bridge->edid); - out: if (power_off) ptn3460_disable(&ptn_bridge->bridge); + return (struct edid *)edid; +} + +static int ptn3460_connector_get_modes(struct drm_connector *connector) +{ + struct ptn3460_bridge *ptn_bridge = connector_to_ptn3460(connector); + struct edid *edid; + int num_modes; + + edid = ptn3460_get_edid(&ptn_bridge->bridge, connector); + drm_connector_update_edid_property(connector, edid); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); + return num_modes; } static const struct drm_connector_helper_funcs ptn3460_connector_helper_funcs = { - .get_modes = ptn3460_get_modes, + .get_modes = ptn3460_connector_get_modes, }; static const struct drm_connector_funcs ptn3460_connector_funcs = { @@ -279,6 +284,7 @@ static const struct drm_bridge_funcs ptn3460_bridge_funcs = { .disable = ptn3460_disable, .post_disable = ptn3460_post_disable, .attach = ptn3460_bridge_attach, + .get_edid = ptn3460_get_edid, }; static int ptn3460_probe(struct i2c_client *client, @@ -327,6 +333,7 @@ static int ptn3460_probe(struct i2c_client *client, } ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; + ptn_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; ptn_bridge->bridge.of_node = dev->of_node; drm_bridge_add(&ptn_bridge->bridge); -- GitLab From 8f22c21dce5b6a8a50049275f77c771c598e5598 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Mon, 27 Jul 2020 19:03:20 +0200 Subject: [PATCH 0042/1494] drm/bridge: nxp-ptn3460: add drm_panel_bridge support Prepare the bridge driver for use in a chained setup. - Replacing direct use of drm_panel with drm_panel_bridge support. - Make the connector creation optional Note: the bridge panel will use the connector type from the panel. v3: - Fix wrong logic in connector creation (Laurent) v2: - Use panel_bridge for local variable name to align with other drivers - Fix that connector was created twice (Laurent) - Set bridge.type to DRM_MODE_CONNECTOR_LVDS. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Andrzej Hajda <a.hajda@samsung.com> Cc: Neil Armstrong <narmstrong@baylibre.com> Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com> Cc: Jonas Karlman <jonas@kwiboo.se> Cc: Jernej Skrabec <jernej.skrabec@siol.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200727170320.959777-6-sam@ravnborg.org --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 58 +++++++++------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 2805c8938f985..e941c11325984 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -29,7 +29,7 @@ struct ptn3460_bridge { struct drm_connector connector; struct i2c_client *client; struct drm_bridge bridge; - struct drm_panel *panel; + struct drm_bridge *panel_bridge; struct gpio_desc *gpio_pd_n; struct gpio_desc *gpio_rst_n; u32 edid_emulation; @@ -126,11 +126,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) usleep_range(10, 20); gpiod_set_value(ptn_bridge->gpio_rst_n, 1); - if (drm_panel_prepare(ptn_bridge->panel)) { - DRM_ERROR("failed to prepare panel\n"); - return; - } - /* * There's a bug in the PTN chip where it falsely asserts hotplug before * it is fully functional. We're forced to wait for the maximum start up @@ -145,16 +140,6 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge) ptn_bridge->enabled = true; } -static void ptn3460_enable(struct drm_bridge *bridge) -{ - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); - - if (drm_panel_enable(ptn_bridge->panel)) { - DRM_ERROR("failed to enable panel\n"); - return; - } -} - static void ptn3460_disable(struct drm_bridge *bridge) { struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); @@ -164,24 +149,10 @@ static void ptn3460_disable(struct drm_bridge *bridge) ptn_bridge->enabled = false; - if (drm_panel_disable(ptn_bridge->panel)) { - DRM_ERROR("failed to disable panel\n"); - return; - } - gpiod_set_value(ptn_bridge->gpio_rst_n, 1); gpiod_set_value(ptn_bridge->gpio_pd_n, 0); } -static void ptn3460_post_disable(struct drm_bridge *bridge) -{ - struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); - - if (drm_panel_unprepare(ptn_bridge->panel)) { - DRM_ERROR("failed to unprepare panel\n"); - return; - } -} static struct edid *ptn3460_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) @@ -247,10 +218,14 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, struct ptn3460_bridge *ptn_bridge = bridge_to_ptn3460(bridge); int ret; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { - DRM_ERROR("Fix bridge driver to make connector optional!"); - return -EINVAL; - } + /* Let this driver create connector if requested */ + ret = drm_bridge_attach(bridge->encoder, ptn_bridge->panel_bridge, + bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret < 0) + return ret; + + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + return 0; if (!bridge->encoder) { DRM_ERROR("Parent encoder object not found"); @@ -270,9 +245,6 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, drm_connector_attach_encoder(&ptn_bridge->connector, bridge->encoder); - if (ptn_bridge->panel) - drm_panel_attach(ptn_bridge->panel, &ptn_bridge->connector); - drm_helper_hpd_irq_event(ptn_bridge->connector.dev); return ret; @@ -280,9 +252,7 @@ static int ptn3460_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs ptn3460_bridge_funcs = { .pre_enable = ptn3460_pre_enable, - .enable = ptn3460_enable, .disable = ptn3460_disable, - .post_disable = ptn3460_post_disable, .attach = ptn3460_bridge_attach, .get_edid = ptn3460_get_edid, }; @@ -292,6 +262,8 @@ static int ptn3460_probe(struct i2c_client *client, { struct device *dev = &client->dev; struct ptn3460_bridge *ptn_bridge; + struct drm_bridge *panel_bridge; + struct drm_panel *panel; int ret; ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL); @@ -299,10 +271,15 @@ static int ptn3460_probe(struct i2c_client *client, return -ENOMEM; } - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL); + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, NULL); if (ret) return ret; + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + ptn_bridge->panel_bridge = panel_bridge; ptn_bridge->client = client; ptn_bridge->gpio_pd_n = devm_gpiod_get(&client->dev, "powerdown", @@ -334,6 +311,7 @@ static int ptn3460_probe(struct i2c_client *client, ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs; ptn_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; + ptn_bridge->bridge.type = DRM_MODE_CONNECTOR_LVDS; ptn_bridge->bridge.of_node = dev->of_node; drm_bridge_add(&ptn_bridge->bridge); -- GitLab From de7fe7e87a926743b05b895575d58e853f3bb515 Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Thu, 4 Jun 2020 12:02:06 -0400 Subject: [PATCH 0043/1494] drm/amdgpu/jpeg: Remove extra asic type check jpeg ip block is already selected based on ASIC type during set_ip_blocks. Signed-off-by: James Zhu <James.Zhu@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index 7a51c615d22d6..845306f63cdb4 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c @@ -55,22 +55,18 @@ static int amdgpu_ih_clientid_jpeg[] = { static int jpeg_v2_5_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_ARCTURUS) { - u32 harvest; - int i; - - adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS; - for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) { - harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING); - if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) - adev->jpeg.harvest_config |= 1 << i; - } + u32 harvest; + int i; - if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 | - AMDGPU_JPEG_HARVEST_JPEG1)) - return -ENOENT; - } else - adev->jpeg.num_jpeg_inst = 1; + adev->jpeg.num_jpeg_inst = JPEG25_MAX_HW_INSTANCES_ARCTURUS; + for (i = 0; i < adev->jpeg.num_jpeg_inst; i++) { + harvest = RREG32_SOC15(JPEG, i, mmCC_UVD_HARVESTING); + if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) + adev->jpeg.harvest_config |= 1 << i; + } + if (adev->jpeg.harvest_config == (AMDGPU_JPEG_HARVEST_JPEG0 | + AMDGPU_JPEG_HARVEST_JPEG1)) + return -ENOENT; jpeg_v2_5_set_dec_ring_funcs(adev); jpeg_v2_5_set_irq_funcs(adev); -- GitLab From 8214617aafa31c7d30721e3f9128737a1259a52a Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Wed, 3 Jun 2020 09:29:27 -0400 Subject: [PATCH 0044/1494] drm/amdgpu: Remove extra asic type check vcn ip block is already selected based on ASIC type during set_ip_blocks Signed-off-by: James Zhu <James.Zhu@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 29 +++++++++++---------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index e99bef6e23542..2719ef9de3bd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -80,23 +80,18 @@ static int vcn_v2_5_early_init(void *handle) adev->vcn.harvest_config = 0; adev->vcn.num_enc_rings = 1; } else { - if (adev->asic_type == CHIP_ARCTURUS) { - u32 harvest; - int i; - - adev->vcn.num_vcn_inst = VCN25_MAX_HW_INSTANCES_ARCTURUS; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); - if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) - adev->vcn.harvest_config |= 1 << i; - } - - if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | - AMDGPU_VCN_HARVEST_VCN1)) - /* both instances are harvested, disable the block */ - return -ENOENT; - } else - adev->vcn.num_vcn_inst = 1; + u32 harvest; + int i; + adev->vcn.num_vcn_inst = VCN25_MAX_HW_INSTANCES_ARCTURUS; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); + if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) + adev->vcn.harvest_config |= 1 << i; + } + if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | + AMDGPU_VCN_HARVEST_VCN1)) + /* both instances are harvested, disable the block */ + return -ENOENT; adev->vcn.num_enc_rings = 2; } -- GitLab From 26cfd12b5e24993ac943ac37044128fe33b3ed94 Mon Sep 17 00:00:00 2001 From: Tom St Denis <tom.stdenis@amd.com> Date: Thu, 23 Jul 2020 08:51:55 -0400 Subject: [PATCH 0045/1494] drm/amd/amdgpu: Add RLC_CGTT_MGCG_OVERRIDE to gfx 10.3 headers Signed-off-by: Tom St Denis <tom.stdenis@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../include/asic_reg/gc/gc_10_3_0_offset.h | 2 ++ .../include/asic_reg/gc/gc_10_3_0_sh_mask.h | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h index 05d1b0a5f6d25..cbaad7d831943 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h @@ -9180,6 +9180,8 @@ #define mmRLC_GPM_THREAD_ENABLE_BASE_IDX 1 #define mmRLC_RLCG_DOORBELL_RANGE 0x4c47 #define mmRLC_RLCG_DOORBELL_RANGE_BASE_IDX 1 +#define mmRLC_CGTT_MGCG_OVERRIDE 0x4c48 +#define mmRLC_CGTT_MGCG_OVERRIDE_BASE_IDX 1 #define mmRLC_CGCG_CGLS_CTRL 0x4c49 #define mmRLC_CGCG_CGLS_CTRL_BASE_IDX 1 #define mmRLC_CGCG_RAMP_CTRL 0x4c4a diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h index aac57f714cf16..c2d035ef3e94e 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h @@ -32315,6 +32315,31 @@ #define RLC_RLCG_DOORBELL_CNTL__DOORBELL_3_MODE_MASK 0x000000C0L #define RLC_RLCG_DOORBELL_CNTL__DOORBELL_ID_MASK 0x001F0000L #define RLC_RLCG_DOORBELL_CNTL__DOORBELL_ID_EN_MASK 0x00200000L +//RLC_CGTT_MGCG_OVERRIDE +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_0__SHIFT 0x0 +#define RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE__SHIFT 0x1 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE__SHIFT 0x2 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE__SHIFT 0x3 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE__SHIFT 0x4 +#define RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE__SHIFT 0x5 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE__SHIFT 0x6 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE__SHIFT 0x7 +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE__SHIFT 0x8 +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_15_9__SHIFT 0x9 +#define RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY__SHIFT 0x10 +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_31_17__SHIFT 0x11 +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_0_MASK 0x00000001L +#define RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK 0x00000002L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK 0x00000004L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK 0x00000008L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK 0x00000010L +#define RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK 0x00000020L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK 0x00000040L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK 0x00000080L +#define RLC_CGTT_MGCG_OVERRIDE__GFXIP_FGCG_OVERRIDE_MASK 0x00000100L +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_15_9_MASK 0x0000FE00L +#define RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK 0x00010000L +#define RLC_CGTT_MGCG_OVERRIDE__RESERVED_31_17_MASK 0xFFFE0000L //RLC_RLCG_DOORBELL_STAT #define RLC_RLCG_DOORBELL_STAT__DOORBELL_0_VALID__SHIFT 0x0 #define RLC_RLCG_DOORBELL_STAT__DOORBELL_1_VALID__SHIFT 0x1 -- GitLab From 0a5baee415000a3e18730ac98e19d046c3cebbe6 Mon Sep 17 00:00:00 2001 From: Laurent Morichetti <laurent.morichetti@amd.com> Date: Mon, 6 Jul 2020 16:13:40 -0700 Subject: [PATCH 0046/1494] drm/amdkfd: Unify gfx9/gfx10 context save area layouts Add some padding before the MODE register in the HWREGs block to preserve the same layout as gfx9. This simplifies implementation of a user-mode debugger. Signed-off-by: Laurent Morichetti <laurent.morichetti@amd.com> Reviewed-by: Jay Cornwall <jay.cornwall@amd.com> Acked-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 930 +++++++++--------- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 2 + 2 files changed, 468 insertions(+), 464 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 577d901fdb636..7290a30f26caa 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -680,7 +680,7 @@ static const uint32_t cwsr_trap_gfx9_hex[] = { }; static const uint32_t cwsr_trap_nv1x_hex[] = { - 0xbf820001, 0xbf8201cd, + 0xbf820001, 0xbf8201ce, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -794,255 +794,256 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbefc037e, 0xbefe037c, 0xbefc0370, 0xf4611efa, 0xf8000000, 0x80708470, - 0xbefc037e, 0xb971f801, - 0xbefe037c, 0xbefc0370, - 0xf4611c7a, 0xf8000000, - 0x80708470, 0xbefc037e, - 0xb971f814, 0xbefe037c, + 0xbefc037e, 0x80708470, + 0xb971f801, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, - 0xbefc037e, 0xb971f815, + 0xbefc037e, 0xb971f814, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, 0xbefc037e, - 0xb9702a05, 0x80708170, - 0xbf0d9973, 0xbf850002, - 0x8f708970, 0xbf820001, - 0x8f708a70, 0xb97a1e06, - 0x8f7a8a7a, 0x80707a70, - 0xbef603ff, 0x01000000, - 0xbefb0374, 0x80747074, - 0x82758075, 0xbefc0380, - 0xbf800000, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xbe8c2f0c, - 0xbe8e2f0e, 0xf469003a, - 0xfa000000, 0xf469013a, - 0xfa000010, 0xf469023a, - 0xfa000020, 0xf469033a, - 0xfa000030, 0x8074c074, - 0x82758075, 0x807c907c, - 0xbf0aff7c, 0x00000060, - 0xbf85ffea, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xf469003a, - 0xfa000000, 0xf469013a, - 0xfa000010, 0xf469023a, - 0xfa000020, 0x8074b074, - 0x82758075, 0xbef4037b, + 0xb971f815, 0xbefe037c, + 0xbefc0370, 0xf4611c7a, + 0xf8000000, 0x80708470, + 0xbefc037e, 0xb9702a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0xbef603ff, + 0x01000000, 0xbefb0374, + 0x80747074, 0x82758075, + 0xbefc0380, 0xbf800000, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xbe8c2f0c, 0xbe8e2f0e, + 0xf469003a, 0xfa000000, + 0xf469013a, 0xfa000010, + 0xf469023a, 0xfa000020, + 0xf469033a, 0xfa000030, + 0x8074c074, 0x82758075, + 0x807c907c, 0xbf0aff7c, + 0x00000060, 0xbf85ffea, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xf469003a, 0xfa000000, + 0xf469013a, 0xfa000010, + 0xf469023a, 0xfa000020, + 0x8074b074, 0x82758075, + 0xbef4037b, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb97b4306, + 0x877bc17b, 0xbf840044, + 0xbf8a0000, 0x877aff73, + 0x04000000, 0xbf840040, + 0x8f7b867b, 0x8f7b827b, + 0xbef6037b, 0xb9702a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0x8070ff70, + 0x00000200, 0x8070ff70, + 0x00000080, 0xbef603ff, + 0x01000000, 0xd7650000, + 0x000100c1, 0xd7660000, + 0x000200c1, 0x16000084, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbefc0380, + 0xbf850012, 0xbe8303ff, + 0x00000080, 0xbf800000, + 0xbf800000, 0xbf800000, + 0xd8d80000, 0x01000000, + 0xbf8c0000, 0xe0704000, + 0x705d0100, 0x807c037c, + 0x80700370, 0xd5250000, + 0x0001ff00, 0x00000080, + 0xbf0a7b7c, 0xbf85fff4, + 0xbf820011, 0xbe8303ff, + 0x00000100, 0xbf800000, + 0xbf800000, 0xbf800000, + 0xd8d80000, 0x01000000, + 0xbf8c0000, 0xe0704000, + 0x705d0100, 0x807c037c, + 0x80700370, 0xd5250000, + 0x0001ff00, 0x00000100, + 0xbf0a7b7c, 0xbf85fff4, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850002, 0xbeff0380, - 0xbf820001, 0xbeff03c1, - 0xb97b4306, 0x877bc17b, - 0xbf840044, 0xbf8a0000, - 0x877aff73, 0x04000000, - 0xbf840040, 0x8f7b867b, - 0x8f7b827b, 0xbef6037b, - 0xb9702a05, 0x80708170, - 0xbf0d9973, 0xbf850002, - 0x8f708970, 0xbf820001, - 0x8f708a70, 0xb97a1e06, - 0x8f7a8a7a, 0x80707a70, - 0x8070ff70, 0x00000200, - 0x8070ff70, 0x00000080, - 0xbef603ff, 0x01000000, - 0xd7650000, 0x000100c1, - 0xd7660000, 0x000200c1, - 0x16000084, 0x907c9973, + 0xbf850004, 0xbef003ff, + 0x00000200, 0xbeff0380, + 0xbf820003, 0xbef003ff, + 0x00000400, 0xbeff03c1, + 0xb97b2a05, 0x807b817b, + 0x8f7b827b, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbefc0380, 0xbf850012, - 0xbe8303ff, 0x00000080, - 0xbf800000, 0xbf800000, - 0xbf800000, 0xd8d80000, - 0x01000000, 0xbf8c0000, - 0xe0704000, 0x705d0100, - 0x807c037c, 0x80700370, - 0xd5250000, 0x0001ff00, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff4, 0xbf820011, - 0xbe8303ff, 0x00000100, - 0xbf800000, 0xbf800000, - 0xbf800000, 0xd8d80000, - 0x01000000, 0xbf8c0000, - 0xe0704000, 0x705d0100, - 0x807c037c, 0x80700370, - 0xd5250000, 0x0001ff00, - 0x00000100, 0xbf0a7b7c, - 0xbf85fff4, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850004, - 0xbef003ff, 0x00000200, - 0xbeff0380, 0xbf820003, - 0xbef003ff, 0x00000400, - 0xbeff03c1, 0xb97b2a05, - 0x807b817b, 0x8f7b827b, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850017, + 0xbf850017, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840037, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, + 0xe0704000, 0x705d0000, + 0xe0704080, 0x705d0100, + 0xe0704100, 0x705d0200, + 0xe0704180, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000200, 0xbf0a7b7c, + 0xbf85ffef, 0xbf820025, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840037, 0x7e008700, + 0xbf840020, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704080, - 0x705d0100, 0xe0704100, - 0x705d0200, 0xe0704180, + 0x705d0000, 0xe0704100, + 0x705d0100, 0xe0704200, + 0x705d0200, 0xe0704300, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000400, 0xbf0a7b7c, 0xbf85ffef, - 0xbf820025, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840020, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, + 0xb97b1e06, 0x877bc17b, + 0xbf84000c, 0x8f7b837b, + 0x807b7c7b, 0xbefe03c1, + 0xbeff0380, 0x7e008700, 0xe0704000, 0x705d0000, - 0xe0704100, 0x705d0100, - 0xe0704200, 0x705d0200, - 0xe0704300, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000400, 0xbf0a7b7c, - 0xbf85ffef, 0xb97b1e06, - 0x877bc17b, 0xbf84000c, - 0x8f7b837b, 0x807b7c7b, - 0xbefe03c1, 0xbeff0380, - 0x7e008700, 0xe0704000, - 0x705d0000, 0x807c817c, - 0x8070ff70, 0x00000080, - 0xbf0a7b7c, 0xbf85fff8, - 0xbf82014f, 0xbef4037e, - 0x8775ff7f, 0x0000ffff, - 0x8875ff75, 0x00040000, - 0xbef60380, 0xbef703ff, - 0x10807fac, 0x876eff7f, - 0x08000000, 0x906e836e, - 0x88776e77, 0x876eff7f, - 0x70000000, 0x906e816e, - 0x88776e77, 0xb97202dc, - 0x8f729972, 0x8872727f, - 0x876eff7f, 0x04000000, - 0xbf840034, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f4306, - 0x876fc16f, 0xbf840029, - 0x8f6f866f, 0x8f6f826f, - 0xbef6036f, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000080, 0xbef603ff, - 0x01000000, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbefc0380, 0xbf850009, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000080, - 0x8078ff78, 0x00000080, - 0xbf0a6f7c, 0xbf85fff8, - 0xbf820008, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000100, 0x8078ff78, - 0x00000100, 0xbf0a6f7c, - 0xbf85fff8, 0xbef80380, + 0x807c817c, 0x8070ff70, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff8, 0xbf820150, + 0xbef4037e, 0x8775ff7f, + 0x0000ffff, 0x8875ff75, + 0x00040000, 0xbef60380, + 0xbef703ff, 0x10807fac, + 0x876eff7f, 0x08000000, + 0x906e836e, 0x88776e77, + 0x876eff7f, 0x70000000, + 0x906e816e, 0x88776e77, + 0xb97202dc, 0x8f729972, + 0x8872727f, 0x876eff7f, + 0x04000000, 0xbf840034, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f2a05, 0x806f816f, - 0x8f6f826f, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbf850021, 0xbef603ff, - 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000200, - 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304080, - 0x785d0100, 0xe0304100, - 0x785d0200, 0xe0304180, - 0x785d0300, 0xbf8c3f70, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807c847c, 0x8078ff78, - 0x00000200, 0xbf0a6f7c, - 0xbf85ffee, 0xe0304000, - 0x6e5d0000, 0xe0304080, - 0x6e5d0100, 0xe0304100, - 0x6e5d0200, 0xe0304180, - 0x6e5d0300, 0xbf820032, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000400, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304100, 0x785d0100, - 0xe0304200, 0x785d0200, - 0xe0304300, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000400, - 0xbf0a6f7c, 0xbf85ffee, - 0xb96f1e06, 0x876fc16f, - 0xbf84000e, 0x8f6f836f, - 0x806f7c6f, 0xbefe03c1, - 0xbeff0380, 0xe0304000, - 0x785d0000, 0xbf8c3f70, - 0x7e008500, 0x807c817c, - 0x8078ff78, 0x00000080, - 0xbf0a6f7c, 0xbf85fff7, - 0xbeff03c1, 0xe0304000, - 0x6e5d0000, 0xe0304100, - 0x6e5d0100, 0xe0304200, - 0x6e5d0200, 0xe0304300, - 0x6e5d0300, 0xbf8c3f70, + 0xb96f4306, 0x876fc16f, + 0xbf840029, 0x8f6f866f, + 0x8f6f826f, 0xbef6036f, 0xb9782a05, 0x80788178, 0xbf0d9972, 0xbf850002, 0x8f788978, 0xbf820001, 0x8f788a78, 0xb96e1e06, 0x8f6e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, - 0x80f8ff78, 0x00000050, + 0x8078ff78, 0x00000080, 0xbef603ff, 0x01000000, - 0xbefc03ff, 0x0000006c, - 0x80f89078, 0xf429003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc847c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0x80f8a078, 0xf42d003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc887c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0xbe843104, 0xbe863106, - 0x80f8c078, 0xf431003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc907c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0xbe843104, 0xbe863106, - 0xbe883108, 0xbe8a310a, - 0xbe8c310c, 0xbe8e310e, - 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbefc0380, + 0xbf850009, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000080, 0x8078ff78, + 0x00000080, 0xbf0a6f7c, + 0xbf85fff8, 0xbf820008, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000100, + 0x8078ff78, 0x00000100, + 0xbf0a6f7c, 0xbf85fff8, + 0xbef80380, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f2a05, + 0x806f816f, 0x8f6f826f, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850021, 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbeee0378, 0x8078ff78, + 0x00000200, 0xbefc0384, + 0xe0304000, 0x785d0000, + 0xe0304080, 0x785d0100, + 0xe0304100, 0x785d0200, + 0xe0304180, 0x785d0300, + 0xbf8c3f70, 0x7e008500, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000200, + 0xbf0a6f7c, 0xbf85ffee, + 0xe0304000, 0x6e5d0000, + 0xe0304080, 0x6e5d0100, + 0xe0304100, 0x6e5d0200, + 0xe0304180, 0x6e5d0300, + 0xbf820032, 0xbef603ff, + 0x01000000, 0xbeee0378, + 0x8078ff78, 0x00000400, + 0xbefc0384, 0xe0304000, + 0x785d0000, 0xe0304100, + 0x785d0100, 0xe0304200, + 0x785d0200, 0xe0304300, + 0x785d0300, 0xbf8c3f70, + 0x7e008500, 0x7e028501, + 0x7e048502, 0x7e068503, + 0x807c847c, 0x8078ff78, + 0x00000400, 0xbf0a6f7c, + 0xbf85ffee, 0xb96f1e06, + 0x876fc16f, 0xbf84000e, + 0x8f6f836f, 0x806f7c6f, + 0xbefe03c1, 0xbeff0380, + 0xe0304000, 0x785d0000, + 0xbf8c3f70, 0x7e008500, + 0x807c817c, 0x8078ff78, + 0x00000080, 0xbf0a6f7c, + 0xbf85fff7, 0xbeff03c1, + 0xe0304000, 0x6e5d0000, + 0xe0304100, 0x6e5d0100, + 0xe0304200, 0x6e5d0200, + 0xe0304300, 0x6e5d0300, + 0xbf8c3f70, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x80f8ff78, + 0x00000050, 0xbef603ff, + 0x01000000, 0xbefc03ff, + 0x0000006c, 0x80f89078, + 0xf429003a, 0xf0000000, + 0xbf8cc07f, 0x80fc847c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0x80f8a078, + 0xf42d003a, 0xf0000000, + 0xbf8cc07f, 0x80fc887c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0xbe843104, + 0xbe863106, 0x80f8c078, + 0xf431003a, 0xf0000000, + 0xbf8cc07f, 0x80fc907c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0xbe843104, + 0xbe863106, 0xbe883108, + 0xbe8a310a, 0xbe8c310c, + 0xbe8e310e, 0xbf06807c, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, @@ -1575,7 +1576,7 @@ static const uint32_t cwsr_trap_arcturus_hex[] = { }; static const uint32_t cwsr_trap_gfx10_hex[] = { - 0xbf820001, 0xbf8201cf, + 0xbf820001, 0xbf8201d0, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -1657,288 +1658,289 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xd7610002, 0x0000f87a, 0x807c817c, 0xd7610002, 0x0000f87b, 0x807c817c, - 0xb971f801, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xb971f814, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xb971f815, 0xd7610002, - 0x0000f871, 0x807c817c, - 0xbeff0380, 0xe0704000, - 0x705d0200, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0xbef603ff, - 0x01000000, 0xbef90380, - 0xbefc0380, 0xbf800000, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xbe8c2f0c, 0xbe8e2f0e, - 0xd7610002, 0x0000f200, - 0x80798179, 0xd7610002, - 0x0000f201, 0x80798179, - 0xd7610002, 0x0000f202, - 0x80798179, 0xd7610002, - 0x0000f203, 0x80798179, - 0xd7610002, 0x0000f204, + 0x80708470, 0xb971f801, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xb971f814, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xb971f815, + 0xd7610002, 0x0000f871, + 0x807c817c, 0xbeff0380, + 0xe0704000, 0x705d0200, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0xbef603ff, 0x01000000, + 0xbef90380, 0xbefc0380, + 0xbf800000, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xbe8c2f0c, + 0xbe8e2f0e, 0xd7610002, + 0x0000f200, 0x80798179, + 0xd7610002, 0x0000f201, 0x80798179, 0xd7610002, - 0x0000f205, 0x80798179, - 0xd7610002, 0x0000f206, + 0x0000f202, 0x80798179, + 0xd7610002, 0x0000f203, 0x80798179, 0xd7610002, - 0x0000f207, 0x80798179, - 0xd7610002, 0x0000f208, + 0x0000f204, 0x80798179, + 0xd7610002, 0x0000f205, 0x80798179, 0xd7610002, - 0x0000f209, 0x80798179, - 0xd7610002, 0x0000f20a, + 0x0000f206, 0x80798179, + 0xd7610002, 0x0000f207, 0x80798179, 0xd7610002, - 0x0000f20b, 0x80798179, - 0xd7610002, 0x0000f20c, + 0x0000f208, 0x80798179, + 0xd7610002, 0x0000f209, 0x80798179, 0xd7610002, - 0x0000f20d, 0x80798179, - 0xd7610002, 0x0000f20e, + 0x0000f20a, 0x80798179, + 0xd7610002, 0x0000f20b, 0x80798179, 0xd7610002, - 0x0000f20f, 0x80798179, - 0xbf06a079, 0xbf840006, - 0xe0704000, 0x705d0200, - 0x8070ff70, 0x00000080, - 0xbef90380, 0x7e040280, - 0x807c907c, 0xbf0aff7c, - 0x00000060, 0xbf85ffbc, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xd7610002, 0x0000f200, + 0x0000f20c, 0x80798179, + 0xd7610002, 0x0000f20d, 0x80798179, 0xd7610002, - 0x0000f201, 0x80798179, - 0xd7610002, 0x0000f202, + 0x0000f20e, 0x80798179, + 0xd7610002, 0x0000f20f, + 0x80798179, 0xbf06a079, + 0xbf840006, 0xe0704000, + 0x705d0200, 0x8070ff70, + 0x00000080, 0xbef90380, + 0x7e040280, 0x807c907c, + 0xbf0aff7c, 0x00000060, + 0xbf85ffbc, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xd7610002, + 0x0000f200, 0x80798179, + 0xd7610002, 0x0000f201, 0x80798179, 0xd7610002, - 0x0000f203, 0x80798179, - 0xd7610002, 0x0000f204, + 0x0000f202, 0x80798179, + 0xd7610002, 0x0000f203, 0x80798179, 0xd7610002, - 0x0000f205, 0x80798179, - 0xd7610002, 0x0000f206, + 0x0000f204, 0x80798179, + 0xd7610002, 0x0000f205, 0x80798179, 0xd7610002, - 0x0000f207, 0x80798179, - 0xd7610002, 0x0000f208, + 0x0000f206, 0x80798179, + 0xd7610002, 0x0000f207, 0x80798179, 0xd7610002, - 0x0000f209, 0x80798179, - 0xd7610002, 0x0000f20a, + 0x0000f208, 0x80798179, + 0xd7610002, 0x0000f209, 0x80798179, 0xd7610002, - 0x0000f20b, 0x80798179, - 0xe0704000, 0x705d0200, + 0x0000f20a, 0x80798179, + 0xd7610002, 0x0000f20b, + 0x80798179, 0xe0704000, + 0x705d0200, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb97b4306, + 0x877bc17b, 0xbf840044, + 0xbf8a0000, 0x877aff73, + 0x04000000, 0xbf840040, + 0x8f7b867b, 0x8f7b827b, + 0xbef6037b, 0xb9702a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0x8070ff70, + 0x00000200, 0x8070ff70, + 0x00000080, 0xbef603ff, + 0x01000000, 0xd7650000, + 0x000100c1, 0xd7660000, + 0x000200c1, 0x16000084, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbefc0380, + 0xbf850012, 0xbe8303ff, + 0x00000080, 0xbf800000, + 0xbf800000, 0xbf800000, + 0xd8d80000, 0x01000000, + 0xbf8c0000, 0xe0704000, + 0x705d0100, 0x807c037c, + 0x80700370, 0xd5250000, + 0x0001ff00, 0x00000080, + 0xbf0a7b7c, 0xbf85fff4, + 0xbf820011, 0xbe8303ff, + 0x00000100, 0xbf800000, + 0xbf800000, 0xbf800000, + 0xd8d80000, 0x01000000, + 0xbf8c0000, 0xe0704000, + 0x705d0100, 0x807c037c, + 0x80700370, 0xd5250000, + 0x0001ff00, 0x00000100, + 0xbf0a7b7c, 0xbf85fff4, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850002, 0xbeff0380, - 0xbf820001, 0xbeff03c1, - 0xb97b4306, 0x877bc17b, - 0xbf840044, 0xbf8a0000, - 0x877aff73, 0x04000000, - 0xbf840040, 0x8f7b867b, - 0x8f7b827b, 0xbef6037b, - 0xb9702a05, 0x80708170, - 0xbf0d9973, 0xbf850002, - 0x8f708970, 0xbf820001, - 0x8f708a70, 0xb97a1e06, - 0x8f7a8a7a, 0x80707a70, - 0x8070ff70, 0x00000200, - 0x8070ff70, 0x00000080, - 0xbef603ff, 0x01000000, - 0xd7650000, 0x000100c1, - 0xd7660000, 0x000200c1, - 0x16000084, 0x907c9973, + 0xbf850004, 0xbef003ff, + 0x00000200, 0xbeff0380, + 0xbf820003, 0xbef003ff, + 0x00000400, 0xbeff03c1, + 0xb97b2a05, 0x807b817b, + 0x8f7b827b, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbefc0380, 0xbf850012, - 0xbe8303ff, 0x00000080, - 0xbf800000, 0xbf800000, - 0xbf800000, 0xd8d80000, - 0x01000000, 0xbf8c0000, - 0xe0704000, 0x705d0100, - 0x807c037c, 0x80700370, - 0xd5250000, 0x0001ff00, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff4, 0xbf820011, - 0xbe8303ff, 0x00000100, - 0xbf800000, 0xbf800000, - 0xbf800000, 0xd8d80000, - 0x01000000, 0xbf8c0000, - 0xe0704000, 0x705d0100, - 0x807c037c, 0x80700370, - 0xd5250000, 0x0001ff00, - 0x00000100, 0xbf0a7b7c, - 0xbf85fff4, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850004, - 0xbef003ff, 0x00000200, - 0xbeff0380, 0xbf820003, - 0xbef003ff, 0x00000400, - 0xbeff03c1, 0xb97b2a05, - 0x807b817b, 0x8f7b827b, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850017, + 0xbf850017, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840037, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, + 0xe0704000, 0x705d0000, + 0xe0704080, 0x705d0100, + 0xe0704100, 0x705d0200, + 0xe0704180, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000200, 0xbf0a7b7c, + 0xbf85ffef, 0xbf820025, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840037, 0x7e008700, + 0xbf840020, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704080, - 0x705d0100, 0xe0704100, - 0x705d0200, 0xe0704180, + 0x705d0000, 0xe0704100, + 0x705d0100, 0xe0704200, + 0x705d0200, 0xe0704300, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000400, 0xbf0a7b7c, 0xbf85ffef, - 0xbf820025, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840020, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, + 0xb97b1e06, 0x877bc17b, + 0xbf84000c, 0x8f7b837b, + 0x807b7c7b, 0xbefe03c1, + 0xbeff0380, 0x7e008700, 0xe0704000, 0x705d0000, - 0xe0704100, 0x705d0100, - 0xe0704200, 0x705d0200, - 0xe0704300, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000400, 0xbf0a7b7c, - 0xbf85ffef, 0xb97b1e06, - 0x877bc17b, 0xbf84000c, - 0x8f7b837b, 0x807b7c7b, - 0xbefe03c1, 0xbeff0380, - 0x7e008700, 0xe0704000, - 0x705d0000, 0x807c817c, - 0x8070ff70, 0x00000080, - 0xbf0a7b7c, 0xbf85fff8, - 0xbf82013a, 0xbef4037e, - 0x8775ff7f, 0x0000ffff, - 0x8875ff75, 0x00040000, - 0xbef60380, 0xbef703ff, - 0x10807fac, 0x876eff7f, - 0x08000000, 0x906e836e, - 0x88776e77, 0x876eff7f, - 0x70000000, 0x906e816e, - 0x88776e77, 0xb97202dc, - 0x8f729972, 0x8872727f, - 0x876eff7f, 0x04000000, - 0xbf840034, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f4306, - 0x876fc16f, 0xbf840029, - 0x8f6f866f, 0x8f6f826f, - 0xbef6036f, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x8078ff78, - 0x00000080, 0xbef603ff, - 0x01000000, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbefc0380, 0xbf850009, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000080, - 0x8078ff78, 0x00000080, - 0xbf0a6f7c, 0xbf85fff8, - 0xbf820008, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000100, 0x8078ff78, - 0x00000100, 0xbf0a6f7c, - 0xbf85fff8, 0xbef80380, + 0x807c817c, 0x8070ff70, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff8, 0xbf82013b, + 0xbef4037e, 0x8775ff7f, + 0x0000ffff, 0x8875ff75, + 0x00040000, 0xbef60380, + 0xbef703ff, 0x10807fac, + 0x876eff7f, 0x08000000, + 0x906e836e, 0x88776e77, + 0x876eff7f, 0x70000000, + 0x906e816e, 0x88776e77, + 0xb97202dc, 0x8f729972, + 0x8872727f, 0x876eff7f, + 0x04000000, 0xbf840034, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f2a05, 0x806f816f, - 0x8f6f826f, 0x907c9972, - 0x877c817c, 0xbf06817c, - 0xbf850021, 0xbef603ff, - 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000200, - 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304080, - 0x785d0100, 0xe0304100, - 0x785d0200, 0xe0304180, - 0x785d0300, 0xbf8c3f70, - 0x7e008500, 0x7e028501, - 0x7e048502, 0x7e068503, - 0x807c847c, 0x8078ff78, - 0x00000200, 0xbf0a6f7c, - 0xbf85ffee, 0xe0304000, - 0x6e5d0000, 0xe0304080, - 0x6e5d0100, 0xe0304100, - 0x6e5d0200, 0xe0304180, - 0x6e5d0300, 0xbf820032, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000400, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304100, 0x785d0100, - 0xe0304200, 0x785d0200, - 0xe0304300, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000400, - 0xbf0a6f7c, 0xbf85ffee, - 0xb96f1e06, 0x876fc16f, - 0xbf84000e, 0x8f6f836f, - 0x806f7c6f, 0xbefe03c1, - 0xbeff0380, 0xe0304000, - 0x785d0000, 0xbf8c3f70, - 0x7e008500, 0x807c817c, - 0x8078ff78, 0x00000080, - 0xbf0a6f7c, 0xbf85fff7, - 0xbeff03c1, 0xe0304000, - 0x6e5d0000, 0xe0304100, - 0x6e5d0100, 0xe0304200, - 0x6e5d0200, 0xe0304300, - 0x6e5d0300, 0xbf8c3f70, + 0xb96f4306, 0x876fc16f, + 0xbf840029, 0x8f6f866f, + 0x8f6f826f, 0xbef6036f, 0xb9782a05, 0x80788178, 0xbf0d9972, 0xbf850002, 0x8f788978, 0xbf820001, 0x8f788a78, 0xb96e1e06, 0x8f6e8a6e, 0x80786e78, 0x8078ff78, 0x00000200, - 0x80f8ff78, 0x00000050, + 0x8078ff78, 0x00000080, 0xbef603ff, 0x01000000, - 0xbefc03ff, 0x0000006c, - 0x80f89078, 0xf429003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc847c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0x80f8a078, 0xf42d003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc887c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0xbe843104, 0xbe863106, - 0x80f8c078, 0xf431003a, - 0xf0000000, 0xbf8cc07f, - 0x80fc907c, 0xbf800000, - 0xbe803100, 0xbe823102, - 0xbe843104, 0xbe863106, - 0xbe883108, 0xbe8a310a, - 0xbe8c310c, 0xbe8e310e, - 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbefc0380, + 0xbf850009, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000080, 0x8078ff78, + 0x00000080, 0xbf0a6f7c, + 0xbf85fff8, 0xbf820008, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000100, + 0x8078ff78, 0x00000100, + 0xbf0a6f7c, 0xbf85fff8, + 0xbef80380, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f2a05, + 0x806f816f, 0x8f6f826f, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850021, 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbeee0378, 0x8078ff78, + 0x00000200, 0xbefc0384, + 0xe0304000, 0x785d0000, + 0xe0304080, 0x785d0100, + 0xe0304100, 0x785d0200, + 0xe0304180, 0x785d0300, + 0xbf8c3f70, 0x7e008500, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000200, + 0xbf0a6f7c, 0xbf85ffee, + 0xe0304000, 0x6e5d0000, + 0xe0304080, 0x6e5d0100, + 0xe0304100, 0x6e5d0200, + 0xe0304180, 0x6e5d0300, + 0xbf820032, 0xbef603ff, + 0x01000000, 0xbeee0378, + 0x8078ff78, 0x00000400, + 0xbefc0384, 0xe0304000, + 0x785d0000, 0xe0304100, + 0x785d0100, 0xe0304200, + 0x785d0200, 0xe0304300, + 0x785d0300, 0xbf8c3f70, + 0x7e008500, 0x7e028501, + 0x7e048502, 0x7e068503, + 0x807c847c, 0x8078ff78, + 0x00000400, 0xbf0a6f7c, + 0xbf85ffee, 0xb96f1e06, + 0x876fc16f, 0xbf84000e, + 0x8f6f836f, 0x806f7c6f, + 0xbefe03c1, 0xbeff0380, + 0xe0304000, 0x785d0000, + 0xbf8c3f70, 0x7e008500, + 0x807c817c, 0x8078ff78, + 0x00000080, 0xbf0a6f7c, + 0xbf85fff7, 0xbeff03c1, + 0xe0304000, 0x6e5d0000, + 0xe0304100, 0x6e5d0100, + 0xe0304200, 0x6e5d0200, + 0xe0304300, 0x6e5d0300, + 0xbf8c3f70, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x80f8ff78, + 0x00000050, 0xbef603ff, + 0x01000000, 0xbefc03ff, + 0x0000006c, 0x80f89078, + 0xf429003a, 0xf0000000, + 0xbf8cc07f, 0x80fc847c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0x80f8a078, + 0xf42d003a, 0xf0000000, + 0xbf8cc07f, 0x80fc887c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0xbe843104, + 0xbe863106, 0x80f8c078, + 0xf431003a, 0xf0000000, + 0xbf8cc07f, 0x80fc907c, + 0xbf800000, 0xbe803100, + 0xbe823102, 0xbe843104, + 0xbe863106, 0xbe883108, + 0xbe8a310a, 0xbe8c310c, + 0xbe8e310e, 0xbf06807c, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 5b220f2a7501f..4569db452160d 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -407,6 +407,7 @@ L_SAVE_HWREG: // Not used on Sienna_Cichlid but keep layout same for debugger. write_hwreg_to_mem(s_save_xnack_mask, s_save_buf_rsrc0, s_save_mem_offset) + s_add_u32 s_save_mem_offset, s_save_mem_offset, 4 s_getreg_b32 s_save_m0, hwreg(HW_REG_MODE) write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) @@ -912,6 +913,7 @@ L_RESTORE_HWREG: read_hwreg_from_mem(s_restore_status, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_trapsts, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_xnack_mask, s_restore_buf_rsrc0, s_restore_mem_offset) + s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4 read_hwreg_from_mem(s_restore_mode, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_flat_scratch, s_restore_buf_rsrc0, s_restore_mem_offset) s_waitcnt lgkmcnt(0) -- GitLab From 156589f74d07fbf4083b05712a3d71f834fdf2af Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Thu, 23 Jul 2020 11:07:52 -0400 Subject: [PATCH 0047/1494] drm/amdgpu/jpeg3.0: remove extra asic type check jpeg ip block is already selected based on ASIC type during set_ip_blocks. Signed-off-by: James Zhu <James.Zhu@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index 42f1a516005ec..c41e5590a7019 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -49,12 +49,11 @@ static int jpeg_v3_0_set_powergating_state(void *handle, static int jpeg_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { - u32 harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING); + u32 harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING); + + if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) + return -ENOENT; - if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) - return -ENOENT; - } adev->jpeg.num_jpeg_inst = 1; jpeg_v3_0_set_dec_ring_funcs(adev); -- GitLab From 309182389e367a806744c94a8bca75d472434015 Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Thu, 23 Jul 2020 11:42:33 -0400 Subject: [PATCH 0048/1494] drm/amdgpu/vcn3.0: remove extra asic type check vcn ip block is already selected based on ASIC type during set_ip_blocks. Signed-off-by: James Zhu <James.Zhu@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 910a4a32ff78f..4edd5c426e248 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -88,23 +88,20 @@ static int vcn_v3_0_early_init(void *handle) adev->vcn.num_enc_rings = 1; } else { - if (adev->asic_type == CHIP_SIENNA_CICHLID) { - u32 harvest; - int i; - - adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); - if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) - adev->vcn.harvest_config |= 1 << i; - } + u32 harvest; + int i; + + adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); + if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) + adev->vcn.harvest_config |= 1 << i; + } - if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | - AMDGPU_VCN_HARVEST_VCN1)) - /* both instances are harvested, disable the block */ - return -ENOENT; - } else - adev->vcn.num_vcn_inst = 1; + if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | + AMDGPU_VCN_HARVEST_VCN1)) + /* both instances are harvested, disable the block */ + return -ENOENT; adev->vcn.num_enc_rings = 2; } -- GitLab From 6c3e0504339d0819ee0d296e857fd100d9170dfa Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Thu, 23 Jul 2020 15:36:37 +0100 Subject: [PATCH 0049/1494] drm/amd/display: remove redundant initialization of variable result The variable result is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 5d83e8174005e..0853bc9917c75 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c @@ -1017,7 +1017,7 @@ enum dc_status dce112_add_stream_to_ctx( struct dc_state *new_ctx, struct dc_stream_state *dc_stream) { - enum dc_status result = DC_ERROR_UNEXPECTED; + enum dc_status result; result = resource_map_pool_resources(dc, new_ctx, dc_stream); -- GitLab From c5079f35c0ec315c944398e687821c1ceb6c6d4f Mon Sep 17 00:00:00 2001 From: Boyuan Zhang <boyuan.zhang@amd.com> Date: Thu, 23 Jul 2020 22:34:22 -0400 Subject: [PATCH 0050/1494] drm/amdgpu: update dec ring test for VCN 3.0 Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 4edd5c426e248..101fc4948110e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1656,7 +1656,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = { .emit_ib = vcn_v2_0_dec_ring_emit_ib, .emit_fence = vcn_v2_0_dec_ring_emit_fence, .emit_vm_flush = vcn_v2_0_dec_ring_emit_vm_flush, - .test_ring = amdgpu_vcn_dec_ring_test_ring, + .test_ring = vcn_v2_0_dec_ring_test_ring, .test_ib = amdgpu_vcn_dec_ring_test_ib, .insert_nop = vcn_v2_0_dec_ring_insert_nop, .insert_start = vcn_v2_0_dec_ring_insert_start, -- GitLab From df9c8d1aa278c435c30a69b8f2418b4a52fcb929 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Wed, 8 Jul 2020 15:07:13 +0800 Subject: [PATCH 0051/1494] drm/amdgpu: fix system hang issue during GPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when GPU hang, driver has multi-paths to enter amdgpu_device_gpu_recover, the atomic adev->in_gpu_reset and hive->in_reset are used to avoid re-entering GPU recovery. During GPU reset and resume, it is unsafe that other threads access GPU, which maybe cause GPU reset failed. Therefore the new rw_semaphore adev->reset_sem is introduced, which protect GPU from being accessed by external threads during recovery. v2: 1. add rwlock for some ioctls, debugfs and file-close function. 2. change to use dqm->is_resetting and dqm_lock for protection in kfd driver. 3. remove try_lock and change adev->in_gpu_reset as atomic, to avoid re-enter GPU recovery for the same GPU hang. v3: 1. change back to use adev->reset_sem to protect kfd callback functions, because dqm_lock couldn't protect all codes, for example: free_mqd must be called outside of dqm_lock; [ 1230.176199] Hardware name: Supermicro SYS-7049GP-TRT/X11DPG-QT, BIOS 3.1 05/23/2019 [ 1230.177221] Call Trace: [ 1230.178249] dump_stack+0x98/0xd5 [ 1230.179443] amdgpu_virt_kiq_reg_write_reg_wait+0x181/0x190 [amdgpu] [ 1230.180673] gmc_v9_0_flush_gpu_tlb+0xcc/0x310 [amdgpu] [ 1230.181882] amdgpu_gart_unbind+0xa9/0xe0 [amdgpu] [ 1230.183098] amdgpu_ttm_backend_unbind+0x46/0x180 [amdgpu] [ 1230.184239] ? ttm_bo_put+0x171/0x5f0 [ttm] [ 1230.185394] ttm_tt_unbind+0x21/0x40 [ttm] [ 1230.186558] ttm_tt_destroy.part.12+0x12/0x60 [ttm] [ 1230.187707] ttm_tt_destroy+0x13/0x20 [ttm] [ 1230.188832] ttm_bo_cleanup_memtype_use+0x36/0x80 [ttm] [ 1230.189979] ttm_bo_put+0x1be/0x5f0 [ttm] [ 1230.191230] amdgpu_bo_unref+0x1e/0x30 [amdgpu] [ 1230.192522] amdgpu_amdkfd_free_gtt_mem+0xaf/0x140 [amdgpu] [ 1230.193833] free_mqd+0x25/0x40 [amdgpu] [ 1230.195143] destroy_queue_cpsch+0x1a7/0x270 [amdgpu] [ 1230.196475] pqm_destroy_queue+0x105/0x260 [amdgpu] [ 1230.197819] kfd_ioctl_destroy_queue+0x37/0x70 [amdgpu] [ 1230.199154] kfd_ioctl+0x277/0x500 [amdgpu] [ 1230.200458] ? kfd_ioctl_get_clock_counters+0x60/0x60 [amdgpu] [ 1230.201656] ? tomoyo_file_ioctl+0x19/0x20 [ 1230.202831] ksys_ioctl+0x98/0xb0 [ 1230.204004] __x64_sys_ioctl+0x1a/0x20 [ 1230.205174] do_syscall_64+0x5f/0x250 [ 1230.206339] entry_SYSCALL_64_after_hwframe+0x49/0xbe 2. remove try_lock and introduce atomic hive->in_reset, to avoid re-enter GPU recovery. v4: 1. remove an unnecessary whitespace change in kfd_chardev.c 2. remove comment codes in amdgpu_device.c 3. add more detailed comment in commit message 4. define a wrap function amdgpu_in_reset v5: 1. Fix some style issues. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Suggested-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Suggested-by: Christian König <christian.koenig@amd.com> Suggested-by: Felix Kuehling <Felix.Kuehling@amd.com> Suggested-by: Lijo Lazar <Lijo.Lazar@amd.com> Suggested-by: Luben Tukov <luben.tuikov@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 40 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 7 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 53 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 350 ++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 3 +- drivers/gpu/drm/amd/amdgpu/atom.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 13 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 13 +- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 16 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 4 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 2 +- 39 files changed, 463 insertions(+), 183 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 327a0daf4a1dc..58e39429395fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -961,9 +961,9 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate; - bool in_gpu_reset; + atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; - struct mutex lock_reset; + struct rw_semaphore reset_sem; struct amdgpu_doorbell_index doorbell_index; struct mutex notifier_lock; @@ -1278,4 +1278,9 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) return adev->gmc.tmz_enabled; } +static inline bool amdgpu_in_reset(struct amdgpu_device *adev) +{ + return atomic_read(&adev->in_gpu_reset) ? true : false; +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 1b865fed74ca8..a0ea663ecdbc9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -244,11 +244,14 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, if (cp_mqd_gfx9) bp.flags |= AMDGPU_GEM_CREATE_CP_MQD_GFX9; + if (!down_read_trylock(&adev->reset_sem)) + return -EIO; + r = amdgpu_bo_create(adev, &bp, &bo); if (r) { dev_err(adev->dev, "failed to allocate BO for amdkfd (%d)\n", r); - return r; + goto err; } /* map the buffer */ @@ -283,6 +286,7 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, amdgpu_bo_unreserve(bo); + up_read(&adev->reset_sem); return 0; allocate_mem_kmap_bo_failed: @@ -291,19 +295,25 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, amdgpu_bo_unreserve(bo); allocate_mem_reserve_bo_failed: amdgpu_bo_unref(&bo); - +err: + up_read(&adev->reset_sem); return r; } void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj) { + struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj; + down_read(&adev->reset_sem); + amdgpu_bo_reserve(bo, true); amdgpu_bo_kunmap(bo); amdgpu_bo_unpin(bo); amdgpu_bo_unreserve(bo); amdgpu_bo_unref(&(bo)); + + up_read(&adev->reset_sem); } int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, @@ -335,9 +345,14 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj) { + struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj; + down_read(&adev->reset_sem); + amdgpu_bo_unref(&bo); + + up_read(&adev->reset_sem); } uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd, @@ -611,12 +626,19 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, /* This works for NO_HWS. TODO: need to handle without knowing VMID */ job->vmid = vmid; + if (!down_read_trylock(&adev->reset_sem)) { + ret = -EIO; + goto err_ib_sched; + } + ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; } + up_read(&adev->reset_sem); + ret = dma_fence_wait(f, false); err_ib_sched: @@ -647,6 +669,9 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; + if (!down_read_trylock(&adev->reset_sem)) + return -EIO; + if (adev->family == AMDGPU_FAMILY_AI) { int i; @@ -656,6 +681,8 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB_0, 0); } + up_read(&adev->reset_sem); + return 0; } @@ -664,11 +691,18 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid) struct amdgpu_device *adev = (struct amdgpu_device *)kgd; const uint32_t flush_type = 0; bool all_hub = false; + int ret = -EIO; if (adev->family == AMDGPU_FAMILY_AI) all_hub = true; - return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub); + if (down_read_trylock(&adev->reset_sem)) { + ret = amdgpu_gmc_flush_gpu_tlb_pasid(adev, + pasid, flush_type, all_hub); + up_read(&adev->reset_sem); + } + + return ret; } bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index bf927f432506d..b0dcc800251ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -542,7 +542,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v10_compute_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; #if 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 744366c7ee85d..275f20399373f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -423,7 +423,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, unsigned long flags, end_jiffies; int retry; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index feab4cc6e8367..4997189d8b368 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -419,7 +419,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, int retry; struct vi_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index c7fd0c47b2545..73728181b88f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -539,7 +539,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v9_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index e5a5ba869eb4a..a21cf84b882c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1190,6 +1190,9 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( return -EINVAL; } + if (!down_read_trylock(&adev->reset_sem)) + return -EIO; + *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); if (!*mem) { ret = -ENOMEM; @@ -1256,6 +1259,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( if (offset) *offset = amdgpu_bo_mmap_offset(bo); + up_read(&adev->reset_sem); return 0; allocate_init_user_pages_failed: @@ -1273,6 +1277,9 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( sg_free_table(sg); kfree(sg); } + + up_read(&adev->reset_sem); + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a512ccbc4deae..a3b150304daef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1292,6 +1292,8 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) parser.adev = adev; parser.filp = filp; + down_read(&adev->reset_sem); + r = amdgpu_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser %d!\n", r); @@ -1331,6 +1333,8 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); + up_read(&adev->reset_sem); + return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 8842c55d4490b..d85d13f7a0435 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -358,6 +358,8 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, if (atomic_read(&ctx->guilty)) out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY; + down_read(&adev->reset_sem); + /*query ue count*/ ras_counter = amdgpu_ras_query_error_count(adev, false); /*ras counter is monotonic increasing*/ @@ -373,6 +375,8 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, ctx->ras_counter_ce = ras_counter; } + up_read(&adev->reset_sem); + mutex_unlock(&mgr->lock); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 193ffdb957b67..3a4b31b1c4f2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -100,14 +100,14 @@ static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) file->private_data = adev; - mutex_lock(&adev->lock_reset); + down_read(&adev->reset_sem); if (adev->autodump.dumping.done) { reinit_completion(&adev->autodump.dumping); ret = 0; } else { ret = -EBUSY; } - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); return ret; } @@ -126,7 +126,7 @@ static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_ poll_wait(file, &adev->autodump.gpu_hang, poll_table); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return POLLIN | POLLRDNORM | POLLWRNORM; return 0; @@ -1241,7 +1241,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) } /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + down_read(&adev->reset_sem); /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -1268,7 +1268,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) kthread_unpark(ring->sched.thread); } - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1458,7 +1458,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) return -ENOMEM; /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + down_read(&adev->reset_sem); /* stop the scheduler */ kthread_park(ring->sched.thread); @@ -1499,7 +1499,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) /* restart the scheduler */ kthread_unpark(ring->sched.thread); - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index aa5b54e5a1d7c..62ecac97fbd2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1935,7 +1935,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) if (adev->ip_blocks[i].status.hw == true) break; - if (adev->in_gpu_reset || adev->in_suspend) { + if (amdgpu_in_reset(adev) || adev->in_suspend) { r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { DRM_ERROR("resume of IP block <%s> failed %d\n", @@ -2106,7 +2106,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev) AMDGPU_RESET_MAGIC_NUM)) return true; - if (!adev->in_gpu_reset) + if (!amdgpu_in_reset(adev)) return false; /* @@ -3036,7 +3036,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->mn_lock); mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); - mutex_init(&adev->lock_reset); + init_rwsem(&adev->reset_sem); + atomic_set(&adev->in_gpu_reset, 0); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4064,8 +4065,11 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (need_full_reset) { /* post card */ - if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) - DRM_WARN("asic atom init failed!"); + if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) { + dev_warn(tmp_adev->dev, "asic atom init failed!"); + r = -EAGAIN; + goto out; + } if (!r) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); @@ -4141,16 +4145,14 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) { - if (trylock) { - if (!mutex_trylock(&adev->lock_reset)) - return false; - } else - mutex_lock(&adev->lock_reset); + if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) + return false; + + down_write(&adev->reset_sem); atomic_inc(&adev->gpu_reset_counter); - adev->in_gpu_reset = true; switch (amdgpu_asic_reset_method(adev)) { case AMD_RESET_METHOD_MODE1: adev->mp1_state = PP_MP1_STATE_SHUTDOWN; @@ -4170,8 +4172,8 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) { amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; - adev->in_gpu_reset = false; - mutex_unlock(&adev->lock_reset); + atomic_set(&adev->in_gpu_reset, 0); + up_write(&adev->reset_sem); } static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) @@ -4281,12 +4283,14 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, true); - if (hive && !mutex_trylock(&hive->reset_lock)) { - DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", - job ? job->base.id : -1, hive->hive_id); - mutex_unlock(&hive->hive_lock); - return 0; + hive = amdgpu_get_xgmi_hive(adev, false); + if (hive) { + if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", + job ? job->base.id : -1, hive->hive_id); + return 0; + } + mutex_lock(&hive->hive_lock); } /* @@ -4308,11 +4312,11 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev, !hive)) { + if (!amdgpu_device_lock_adev(tmp_adev)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); - mutex_unlock(&hive->hive_lock); - return 0; + r = 0; + goto skip_recovery; } /* @@ -4445,8 +4449,9 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, amdgpu_device_unlock_adev(tmp_adev); } +skip_recovery: if (hive) { - mutex_unlock(&hive->reset_lock); + atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7f9e50247413d..73cc68ab53d06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -671,6 +671,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, bo_va = NULL; } + down_read(&adev->reset_sem); + switch (args->operation) { case AMDGPU_VA_OP_MAP: va_flags = amdgpu_gem_va_map_flags(adev, args->flags); @@ -700,6 +702,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va, args->operation); + up_read(&adev->reset_sem); + error_backoff: ttm_eu_backoff_reservation(&ticket, &list); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 78d37f92c7be5..8eff0173360de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -724,7 +724,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); @@ -782,7 +782,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_write; might_sleep(); @@ -801,5 +801,5 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_write: - pr_err("failed to write reg:%x\n", reg); + dev_warn(adev->dev, "failed to write reg:%x\n", reg); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 937029ad5271a..75d37dfb51aa7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -220,17 +220,17 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) trace_amdgpu_sched_run_job(job); - if (job->vram_lost_counter != atomic_read(&ring->adev->vram_lost_counter)) - dma_fence_set_error(finished, -ECANCELED);/* skip IB as well if VRAM lost */ - - if (finished->error < 0) { - DRM_INFO("Skip scheduling IBs!\n"); - } else { + if (down_read_trylock(&ring->adev->reset_sem)) { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, - &fence); + &fence); + up_read(&ring->adev->reset_sem); if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); + } else { + dma_fence_set_error(finished, -ECANCELED); + DRM_INFO("Skip scheduling IBs!\n"); } + /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index a8c47aecd342e..b9c1fce6da793 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1084,6 +1084,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (!fpriv) return; + down_read(&adev->reset_sem); + pm_runtime_get_sync(dev->dev); if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL) @@ -1122,6 +1124,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); + + up_read(&adev->reset_sem); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 0a05db9b71320..2f7b0550ff16f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -163,7 +163,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, enum amd_pm_state_type pm; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -172,6 +172,8 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { if (adev->smu.ppt_funcs->get_current_power_state) pm = smu_get_current_power_state(&adev->smu); @@ -183,6 +185,8 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, pm = adev->pm.dpm.user_state; } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -201,7 +205,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("battery", buf, strlen("battery")) == 0) @@ -219,6 +223,8 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { mutex_lock(&adev->pm.mutex); adev->pm.dpm.user_state = state; @@ -232,6 +238,9 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, amdgpu_pm_compute_clocks(adev); } + + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -307,7 +316,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level = 0xff; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -316,6 +325,8 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -323,6 +334,8 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, else level = adev->pm.dpm.forced_level; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -349,7 +362,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level current_level = 0xff; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("low", buf, strlen("low")) == 0) { @@ -380,6 +393,8 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) current_level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -388,7 +403,8 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (current_level == level) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return count; + ret = count; + goto pro_end; } if (adev->asic_type == CHIP_RAVEN) { @@ -409,7 +425,8 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pr_err("Currently not in any profile mode!\n"); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } if (is_support_sw_smu(adev)) { @@ -417,7 +434,8 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } } else if (adev->powerplay.pp_funcs->force_performance_level) { mutex_lock(&adev->pm.mutex); @@ -425,14 +443,16 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } ret = amdgpu_dpm_force_performance_level(adev, level); if (ret) { mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } else { adev->pm.dpm.forced_level = level; } @@ -441,7 +461,9 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return count; +pro_end: + up_read(&adev->reset_sem); + return ret; } static ssize_t amdgpu_get_pp_num_states(struct device *dev, @@ -453,7 +475,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -497,7 +519,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0, ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -538,7 +560,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->pp_force_state_enabled) @@ -558,7 +580,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, unsigned long idx; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strlen(buf) == 1) @@ -584,6 +606,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, return ret; } + down_read(&adev->reset_sem); /* only set user selected power states */ if (state != POWER_STATE_TYPE_INTERNAL_BOOT && state != POWER_STATE_TYPE_DEFAULT) { @@ -591,6 +614,8 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, AMD_PP_TASK_ENABLE_USER_STATE, &state); adev->pp_force_state_enabled = true; } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); } @@ -618,7 +643,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -662,7 +687,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -671,16 +696,21 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_table(&adev->smu, (void *)buf, count); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + up_read(&adev->reset_sem); return ret; } } else if (adev->powerplay.pp_funcs->set_pp_table) amdgpu_dpm_set_pp_table(adev, buf, count); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -815,7 +845,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, const char delimiter[3] = {' ', '\n', '\0'}; uint32_t type; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (count > 127) @@ -858,6 +888,10 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return ret; } + ret = count; + + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { ret = smu_od_edit_dpm_table(&adev->smu, type, parameter, parameter_size); @@ -865,7 +899,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } } else { if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { @@ -874,7 +909,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } } @@ -885,18 +921,22 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, NULL); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return count; + ret = count; + goto pro_end; } else { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; + ret = -EINVAL; + goto pro_end; } } } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - return count; +pro_end: + up_read(&adev->reset_sem); + return ret; } static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, @@ -908,7 +948,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -962,7 +1002,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtou64(buf, 0, &featuremask); @@ -977,11 +1017,13 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, return ret; } + down_read(&adev->reset_sem); if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_feature_mask(&adev->smu, featuremask); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } } else if (adev->powerplay.pp_funcs->set_ppfeature_status) { @@ -989,9 +1031,12 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1007,7 +1052,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1016,6 +1061,8 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_sys_get_pp_feature_mask(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_ppfeature_status) @@ -1023,6 +1070,8 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1068,7 +1117,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1077,6 +1126,8 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1084,6 +1135,8 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1135,7 +1188,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1148,11 +1201,15 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1171,7 +1228,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1180,6 +1237,8 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_MCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1187,6 +1246,8 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1203,7 +1264,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, uint32_t mask = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1216,11 +1277,15 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_MCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1239,7 +1304,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1248,6 +1313,8 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SOCCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1255,6 +1322,8 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1271,7 +1340,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1284,6 +1353,8 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SOCCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1291,6 +1362,8 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, else ret = 0; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1309,7 +1382,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1318,6 +1391,8 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_FCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1325,6 +1400,8 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1341,7 +1418,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1354,6 +1431,8 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_FCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1361,6 +1440,8 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, else ret = 0; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1379,7 +1460,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1388,6 +1469,8 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_DCEFCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1395,6 +1478,8 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1411,7 +1496,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1424,6 +1509,8 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_DCEFCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1431,6 +1518,8 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, else ret = 0; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1449,7 +1538,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1458,6 +1547,8 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_PCIE, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1465,6 +1556,8 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1481,7 +1574,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1494,6 +1587,8 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_PCIE, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1501,6 +1596,8 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, else ret = 0; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1519,7 +1616,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1528,11 +1625,15 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK); else if (adev->powerplay.pp_funcs->get_sclk_od) value = amdgpu_dpm_get_sclk_od(adev); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1549,7 +1650,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1563,6 +1664,8 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value); } else { @@ -1577,6 +1680,8 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, } } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1592,7 +1697,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1601,11 +1706,15 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK); else if (adev->powerplay.pp_funcs->get_mclk_od) value = amdgpu_dpm_get_mclk_od(adev); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1622,7 +1731,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1636,6 +1745,8 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value); } else { @@ -1650,6 +1761,8 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, } } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1685,7 +1798,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1694,6 +1807,8 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) size = smu_get_power_profile_mode(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_power_profile_mode) @@ -1701,6 +1816,8 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1725,7 +1842,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; tmp[0] = *(buf); @@ -1758,11 +1875,15 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) ret = smu_set_power_profile_mode(&adev->smu, parameter, parameter_size, true); else if (adev->powerplay.pp_funcs->set_power_profile_mode) ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1788,7 +1909,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1797,9 +1918,11 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, return r; } + down_read(&adev->reset_sem); /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1826,7 +1949,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1835,10 +1958,14 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, return r; } + down_read(&adev->reset_sem); + /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1869,7 +1996,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, uint64_t count0 = 0, count1 = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->flags & AMD_IS_APU) @@ -1884,8 +2011,12 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, return ret; } + down_read(&adev->reset_sem); + amdgpu_asic_get_pcie_usage(adev, &count0, &count1); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1910,7 +2041,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->unique_id) @@ -2177,7 +2308,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, int channel = to_sensor_dev_attr(attr)->index; int r, temp = 0, size = sizeof(temp); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (channel >= PP_TEMP_MAX) @@ -2189,6 +2320,8 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, return r; } + down_read(&adev->reset_sem); + switch (channel) { case PP_TEMP_JUNCTION: /* get current junction temperature */ @@ -2210,6 +2343,8 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, break; } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2313,7 +2448,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2322,18 +2457,23 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2349,7 +2489,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err, ret; int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2362,18 +2502,23 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, value); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, value); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2403,7 +2548,7 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2412,11 +2557,15 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + up_read(&adev->reset_sem); + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); pm_runtime_mark_last_busy(adev->ddev->dev); @@ -2457,7 +2606,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2466,6 +2615,8 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) err = smu_get_fan_speed_percent(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_percent) @@ -2473,6 +2624,8 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, else err = -EINVAL; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2492,7 +2645,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2501,6 +2654,8 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2508,6 +2663,8 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, else err = -EINVAL; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2526,7 +2683,7 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, u32 size = sizeof(min_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2535,9 +2692,13 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, return r; } + down_read(&adev->reset_sem); + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, (void *)&min_rpm, &size); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2556,7 +2717,7 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, u32 size = sizeof(max_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2565,9 +2726,13 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, return r; } + down_read(&adev->reset_sem); + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, (void *)&max_rpm, &size); + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2585,7 +2750,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, int err; u32 rpm = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2594,6 +2759,8 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &rpm); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2601,6 +2768,8 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, else err = -EINVAL; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2619,7 +2788,7 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2628,11 +2797,15 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + up_read(&adev->reset_sem); + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2646,6 +2819,8 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) err = smu_set_fan_speed_rpm(&adev->smu, value); else if (adev->powerplay.pp_funcs->set_fan_speed_rpm) @@ -2653,6 +2828,8 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, else err = -EINVAL; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2670,7 +2847,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2679,18 +2856,23 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, return ret; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2707,7 +2889,7 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, int value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2727,17 +2909,22 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, pwm_mode); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); + up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2752,7 +2939,7 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, u32 vddgfx; int r, size = sizeof(vddgfx); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2761,9 +2948,11 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, return r; } + down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&vddgfx, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2789,7 +2978,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, u32 vddnb; int r, size = sizeof(vddnb); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; /* only APUs have vddnb */ @@ -2802,9 +2991,11 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, return r; } + down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&vddnb, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2831,7 +3022,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, int r, size = sizeof(u32); unsigned uw; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2840,9 +3031,11 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, return r; } + down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2872,7 +3065,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2881,6 +3074,8 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, return r; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, true); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -2891,6 +3086,8 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2906,7 +3103,7 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2915,6 +3112,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, return r; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, false); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -2925,6 +3124,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2941,7 +3142,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, int err; u32 value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (amdgpu_sriov_vf(adev)) @@ -2960,6 +3161,8 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return err; } + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) err = smu_set_power_limit(&adev->smu, value); else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_power_limit) @@ -2967,6 +3170,8 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, else err = -EINVAL; + up_read(&adev->reset_sem); + pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2984,7 +3189,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, uint32_t sclk; int r, size = sizeof(sclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2993,9 +3198,11 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, return r; } + down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&sclk, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3021,7 +3228,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, uint32_t mclk; int r, size = sizeof(mclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3030,9 +3237,11 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, return r; } + down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&mclk, &size); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3913,7 +4122,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) u32 flags = 0; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(dev->dev); @@ -3922,7 +4131,10 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return r; } + down_read(&adev->reset_sem); amdgpu_device_ip_get_clockgating_state(adev, &flags); + up_read(&adev->reset_sem); + seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); amdgpu_parse_cg_state(m, flags); seq_printf(m, "\n"); @@ -3934,6 +4146,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return 0; } + down_read(&adev->reset_sem); if (!is_support_sw_smu(adev) && adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { mutex_lock(&adev->pm.mutex); @@ -3946,6 +4159,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) } else { r = amdgpu_debugfs_pm_info_pp(m, adev); } + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8034111acd9a6..a053b7af06802 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1684,7 +1684,7 @@ static int psp_load_smu_fw(struct psp_context *psp) return 0; - if (adev->in_gpu_reset && ras && ras->supported) { + if (amdgpu_in_reset(adev) && ras && ras->supported) { ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); if (ret) { DRM_WARN("Failed to set MP1 state prepare for reload\n"); @@ -1799,7 +1799,7 @@ static int psp_load_fw(struct amdgpu_device *adev) int ret; struct psp_context *psp = &adev->psp; - if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { + if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ goto skip_memalloc; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index bcce4c0be4623..5680f7eafcb18 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1978,7 +1978,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, amdgpu_ras_request_reset_on_boot(adev, ras_block->block); return 0; - } else if (adev->in_suspend || adev->in_gpu_reset) { + } else if (adev->in_suspend || amdgpu_in_reset(adev)) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -1987,7 +1987,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, } /* in resume phase, no need to create ras fs node */ - if (adev->in_suspend || adev->in_gpu_reset) + if (adev->in_suspend || amdgpu_in_reset(adev)) return 0; if (ih_info->cb) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5f2f3faad7924..605d266754f69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2088,7 +2088,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) uint64_t size; int r; - if (!adev->mman.initialized || adev->in_gpu_reset || + if (!adev->mman.initialized || amdgpu_in_reset(adev) || adev->mman.buffer_funcs_enabled == enable) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 183743c5fb7bf..039245c98ff87 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -628,7 +628,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ - if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend)) + if (!amdgpu_sriov_vf(adev) && + (amdgpu_in_reset(adev) || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 1203c20491e6d..5cae39d35c044 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -93,7 +93,7 @@ void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq: - pr_err("failed to write reg %x wait reg %x\n", reg0, reg1); + dev_warn(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index f826945989c72..b2046c3a404de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -325,9 +325,9 @@ static inline bool is_virtual_machine(void) #define amdgpu_sriov_is_pp_one_vf(adev) \ ((adev)->virt.gim_feature & AMDGIM_FEATURE_PP_ONE_VF) #define amdgpu_sriov_is_debug(adev) \ - ((!adev->in_gpu_reset) && adev->virt.tdr_debug) + ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ - ((!adev->in_gpu_reset) && (!adev->virt.tdr_debug)) + ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index e3a3755cb999a..4e017f379eb67 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -372,7 +372,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo tmp->hive_id = adev->gmc.xgmi.hive_id; INIT_LIST_HEAD(&tmp->device_list); mutex_init(&tmp->hive_lock); - mutex_init(&tmp->reset_lock); + atomic_set(&tmp->in_reset, 0); task_barrier_init(&tmp->tb); if (lock) @@ -397,6 +397,7 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) hive->hi_req_gpu : adev; bool is_hi_req = pstate == AMDGPU_XGMI_PSTATE_MAX_VEGA20; bool init_low = hive->pstate == AMDGPU_XGMI_PSTATE_UNKNOWN; + bool locked; /* fw bug so temporarily disable pstate switching */ return 0; @@ -404,7 +405,9 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) if (!hive || adev->asic_type != CHIP_VEGA20) return 0; - mutex_lock(&hive->hive_lock); + locked = atomic_read(&hive->in_reset) ? false : true; + if (locked) + mutex_lock(&hive->hive_lock); if (is_hi_req) hive->hi_req_count++; @@ -439,7 +442,8 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) adev : NULL; } out: - mutex_unlock(&hive->hive_lock); + if (locked) + mutex_unlock(&hive->hive_lock); return ret; } @@ -594,7 +598,6 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) if(!(--hive->number_devices)){ amdgpu_xgmi_sysfs_destroy(adev, hive); mutex_destroy(&hive->hive_lock); - mutex_destroy(&hive->reset_lock); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 6999eab16a720..61720cd4a1ee2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -30,7 +30,8 @@ struct amdgpu_hive_info { uint64_t hive_id; struct list_head device_list; int number_devices; - struct mutex hive_lock, reset_lock; + struct mutex hive_lock; + atomic_t in_reset; struct kobject *kobj; struct device_attribute dev_attr; struct amdgpu_device *adev; diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index 4cfc786699c7f..8341bd965202b 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -755,6 +755,7 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) /* jiffies wrap around we will just wait a little longer */ ctx->last_jump_jiffies = jiffies; } + schedule(); } else { ctx->last_jump = ctx->start + target; ctx->last_jump_jiffies = jiffies; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 8344c3b0b9b5c..db9f1e89a0f83 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6180,7 +6180,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) struct v10_gfx_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.gfx_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6192,7 +6192,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { + } else if (amdgpu_in_reset(adev)) { /* reset mqd with the backup copy */ if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6541,7 +6541,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v10_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6577,7 +6577,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6587,7 +6587,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 33f1c4a46ebe0..8d7208959c952 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4632,7 +4632,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4669,7 +4669,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4681,7 +4681,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index cb9d60a4e05ed..e4e751f87092b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3684,7 +3684,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3722,7 +3722,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -3734,7 +3734,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3928,7 +3928,7 @@ static int gfx_v9_0_hw_fini(void *handle) /* Use deinitialize sequence from CAIL when unbinding device from driver, * otherwise KIQ is hanging when binding back */ - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, adev->gfx.kiq.ring.me, adev->gfx.kiq.ring.pipe, @@ -4086,7 +4086,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 19051ce122b1b..1a78073c2f053 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -268,7 +268,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -293,7 +293,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready || - adev->in_gpu_reset || + amdgpu_in_reset(adev) || ring->sched.ready == false) { gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0); mutex_unlock(&adev->mman.gtt_window_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index e18296dc13861..0f8e8aff9114c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -434,7 +434,7 @@ static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index a9e722b8a4583..abe64010f0d57 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -635,7 +635,7 @@ static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6e4f3ff4810f1..c5f94bab4a010 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -501,7 +501,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -596,7 +596,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; if (ring->sched.ready) { @@ -633,7 +633,8 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dev_info(adev->dev, + "wait for kiq fence error: %ld\n", r); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 5fd67e1cc2a04..fe31cbeccfe91 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -238,20 +238,16 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" + * we can unlock the reset_sem to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - adev->in_gpu_reset = true; - + down_read(&adev->reset_sem); do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -261,10 +257,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - adev->in_gpu_reset = false; - mutex_unlock(&adev->lock_reset); - } + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index ce2bf1fb79ed1..6f55172e83374 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -259,20 +259,16 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" + * we can unlock the reset_sem to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - adev->in_gpu_reset = true; - + down_read(&adev->reset_sem); do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -282,10 +278,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - adev->in_gpu_reset = false; - mutex_unlock(&adev->lock_reset); - } + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index e0e60b0d0669e..7ad1537820b54 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -304,15 +304,17 @@ static void deallocate_vmid(struct device_queue_manager *dqm, struct qcm_process_device *qpd, struct queue *q) { - /* On GFX v7, CP doesn't flush TC at dequeue */ - if (q->device->device_info->asic_family == CHIP_HAWAII) - if (flush_texture_cache_nocpsch(q->device, qpd)) - pr_err("Failed to flush TC\n"); + if (!dqm->is_resetting) { + /* On GFX v7, CP doesn't flush TC at dequeue */ + if (q->device->device_info->asic_family == CHIP_HAWAII) + if (flush_texture_cache_nocpsch(q->device, qpd)) + pr_err("Failed to flush TC\n"); - kfd_flush_tlb(qpd_to_pdd(qpd)); + kfd_flush_tlb(qpd_to_pdd(qpd)); - /* Release the vmid mapping */ - set_pasid_vmid_mapping(dqm, 0, qpd->vmid); + /* Release the vmid mapping */ + set_pasid_vmid_mapping(dqm, 0, qpd->vmid); + } dqm->vmid_pasid[qpd->vmid] = 0; qpd->vmid = 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 40695d52e9a8d..ee2258404c8fa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1551,6 +1551,10 @@ int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process, void kfd_flush_tlb(struct kfd_process_device *pdd) { struct kfd_dev *dev = pdd->dev; + struct device_queue_manager *dqm = dev->dqm; + + if (dqm->is_resetting) + return; if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { /* Nothing to flush until a VMID is assigned, which diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 03a60c7498344..cf79857ece539 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1647,7 +1647,7 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { mutex_lock(&dm->dc_lock); dm->cached_dc_state = dc_copy_state(dm->dc->current_state); @@ -1833,7 +1833,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { dc_state = dm->cached_dc_state; r = dm_dmub_hw_init(adev); diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 727cb9fd4aee1..0eeccf3341a32 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -992,7 +992,7 @@ static int smu_disable_dpms(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; bool use_baco = !smu->is_apu && - ((adev->in_gpu_reset && + ((amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 3b8839641770b..bacbe2fa1f9ac 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -484,7 +484,7 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; - bool use_baco = (adev->in_gpu_reset && + bool use_baco = (amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || (adev->in_runpm && amdgpu_asic_supports_baco(adev)); -- GitLab From 2c2b0d880f1b4c01f30e14242977b82fa527342d Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Thu, 23 Jul 2020 23:09:57 -0400 Subject: [PATCH 0052/1494] drm/amdkfd: Add thermal throttling SMI event Add support for reporting thermal throttling events through SMI. Also, add a counter to count the number of throttling interrupts observed and report the count in the SMI event message. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 4 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_device.c | 7 ++ drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 67 ++++++++++++++----- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h | 2 + drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 1 + drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 1 + .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 5 ++ include/uapi/linux/kfd_ioctl.h | 3 +- 10 files changed, 74 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index a0ea663ecdbc9..92790db5edc02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -789,4 +789,8 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd) { } + +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) +{ +} #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index ffe149aafc393..a10507ecb7508 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -270,5 +270,6 @@ int kgd2kfd_resume_mm(struct mm_struct *mm); int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm, struct dma_fence *fence); void kgd2kfd_set_sram_ecc_flag(struct kfd_dev *kfd); +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask); #endif /* AMDGPU_AMDKFD_H_INCLUDED */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 4bfedaab183f0..d5e790f046b4b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -29,6 +29,7 @@ #include "cwsr_trap_handler.h" #include "kfd_iommu.h" #include "amdgpu_amdkfd.h" +#include "kfd_smi_events.h" #define MQD_SIZE_ALIGNED 768 @@ -1245,6 +1246,12 @@ void kfd_dec_compute_active(struct kfd_dev *kfd) WARN_ONCE(count < 0, "Compute profile ref. count error"); } +void kgd2kfd_smi_event_throttle(struct kfd_dev *kfd, uint32_t throttle_bitmask) +{ + if (kfd) + kfd_smi_event_update_thermal_throttling(kfd, throttle_bitmask); +} + #if defined(CONFIG_DEBUG_FS) /* This function will send a package to HIQ to hang the HWS diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 7b348bf9df214..86c2c3e97944b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -24,6 +24,7 @@ #include <linux/wait.h> #include <linux/anon_inodes.h> #include <uapi/linux/kfd_ioctl.h> +#include "amdgpu.h" #include "amdgpu_vm.h" #include "kfd_priv.h" #include "kfd_smi_events.h" @@ -148,6 +149,54 @@ static int kfd_smi_ev_release(struct inode *inode, struct file *filep) return 0; } +static void add_event_to_kfifo(struct kfd_dev *dev, unsigned long long smi_event, + char *event_msg, int len) +{ + struct kfd_smi_client *client; + + rcu_read_lock(); + + list_for_each_entry_rcu(client, &dev->smi_clients, list) { + if (!(READ_ONCE(client->events) & smi_event)) + continue; + spin_lock(&client->lock); + if (kfifo_avail(&client->fifo) >= len) { + kfifo_in(&client->fifo, event_msg, len); + wake_up_all(&client->wait_queue); + } else { + pr_debug("smi_event(EventID: %llu): no space left\n", + smi_event); + } + spin_unlock(&client->lock); + } + + rcu_read_unlock(); +} + +void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, + uint32_t throttle_bitmask) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; + /* + * ThermalThrottle msg = throttle_bitmask(8): + * thermal_interrupt_count(16): + * 16 bytes event + 1 byte space + 8 byte throttle_bitmask + + * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n + + * 1 byte \0 = 44 + */ + char fifo_in[44]; + int len; + + if (list_empty(&dev->smi_clients)) + return; + + len = snprintf(fifo_in, 44, "%x %x:%llx\n", + KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, + atomic64_read(&adev->smu.throttle_int_counter)); + + add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); +} + void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) { struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; @@ -156,7 +205,6 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) /* 16 bytes event + 1 byte space + 25 bytes msg + 1 byte \n = 43 */ char fifo_in[43]; - struct kfd_smi_client *client; int len; if (list_empty(&dev->smi_clients)) @@ -171,22 +219,7 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) len = snprintf(fifo_in, 43, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, task_info.pid, task_info.task_name); - rcu_read_lock(); - - list_for_each_entry_rcu(client, &dev->smi_clients, list) { - if (!(READ_ONCE(client->events) & KFD_SMI_EVENT_VMFAULT)) - continue; - spin_lock(&client->lock); - if (kfifo_avail(&client->fifo) >= len) { - kfifo_in(&client->fifo, fifo_in, len); - wake_up_all(&client->wait_queue); - } - else - pr_debug("smi_event(vmfault): no space left\n"); - spin_unlock(&client->lock); - } - - rcu_read_unlock(); + add_event_to_kfifo(dev, KFD_SMI_EVENT_VMFAULT, fifo_in, len); } int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h index a9cb218fef96e..15537b2cccb58 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h @@ -25,5 +25,7 @@ int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); +void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, + uint32_t throttle_bitmask); #endif diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 0eeccf3341a32..7d9c40ad57801 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -640,6 +640,7 @@ static int smu_sw_init(void *handle) mutex_init(&smu->message_lock); INIT_WORK(&smu->throttling_logging_work, smu_throttling_logging_work_fn); + atomic64_set(&smu->throttle_int_counter, 0); smu->watermarks_bitmap = 0; smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 3b9182c8c53f8..f13979687b9e6 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2251,6 +2251,7 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu) dev_warn(adev->dev, "WARN: GPU thermal throttling temperature reached, expect performance decrease. %s.\n", log_buf); + kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status); } static const struct pptable_funcs arcturus_ppt_funcs = { diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 28312d6dc187c..b57b104063907 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -446,6 +446,7 @@ struct smu_context bool dc_controlled_by_gpio; struct work_struct throttling_logging_work; + atomic64_t throttle_int_counter; }; struct i2c_adapter; diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index fd82402065e63..a9453ec01619d 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1311,6 +1311,11 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, smu_v11_0_ack_ac_dc_interrupt(&adev->smu); break; case 0x7: + /* + * Increment the throttle interrupt counter + */ + atomic64_inc(&smu->throttle_int_counter); + if (!atomic_read(&adev->throttling_logging_enabled)) return 0; diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index f738c3b53f4ea..df6c7a43aadcf 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -450,7 +450,8 @@ struct kfd_ioctl_import_dmabuf_args { * KFD SMI(System Management Interface) events */ /* Event type (defined by bitmask) */ -#define KFD_SMI_EVENT_VMFAULT 0x0000000000000001 +#define KFD_SMI_EVENT_VMFAULT 0x0000000000000001 +#define KFD_SMI_EVENT_THERMAL_THROTTLE 0x0000000000000002 struct kfd_ioctl_smi_events_args { __u32 gpuid; /* to KFD */ -- GitLab From 059ea10abdddfbfb3ec4c29c120344846745223b Mon Sep 17 00:00:00 2001 From: Changfeng <Changfeng.Zhu@amd.com> Date: Fri, 24 Jul 2020 13:15:10 +0800 Subject: [PATCH 0053/1494] drm/amd/powerplay: drop unnecessary message support check(v2) Take back patch:drop unnecessary message support check Because the gpu reset fail problem on renoir can be fixed by: drm/amd/powerplay: skip invalid msg when smu set mp1 state It needs to remove SWSMU_CODE_LAYER_L1 in smu_cmn.h to guard a clear code layer. Signed-off-by: changfeng <Changfeng.Zhu@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 9 --------- drivers/gpu/drm/amd/powerplay/smu_cmn.h | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 7d9c40ad57801..3b427fa099fec 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -34,7 +34,6 @@ #include "sienna_cichlid_ppt.h" #include "renoir_ppt.h" #include "amd_pcie.h" -#include "smu_cmn.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -1591,14 +1590,6 @@ int smu_set_mp1_state(struct smu_context *smu, return 0; } - /* some asics may not support those messages */ - if (smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_MSG, - msg) < 0) { - mutex_unlock(&smu->mutex); - return 0; - } - ret = smu_send_smc_msg(smu, msg, NULL); /* some asics may not support those messages */ if (ret == -EINVAL) diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/powerplay/smu_cmn.h index f9e63f18b1570..98face8c5fd61 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.h +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.h @@ -25,7 +25,7 @@ #include "amdgpu_smu.h" -#if defined(SWSMU_CODE_LAYER_L1) || defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4) +#if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4) int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, enum smu_message_type msg, uint32_t param, -- GitLab From ea368183ae900e376b66d3f23da22acde48e385a Mon Sep 17 00:00:00 2001 From: Jay Cornwall <jay.cornwall@amd.com> Date: Fri, 24 Jul 2020 16:58:48 -0700 Subject: [PATCH 0054/1494] drm/amdkfd: Fix spurious debug exception on gfx10 s_barrier triggers a debug exception when issued with PRIV=1, DEBUG_EN=1. This causes spurious notifications to rocm-gdb. Clear MODE before issuing s_barrier and restore MODE afterwards in the context restore handler. Signed-off-by: Jay Cornwall <jay.cornwall@amd.com> Tested-by: Laurent Morichetti <laurent.morichetti@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 178 +++++++++--------- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 7 +- 2 files changed, 95 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 7290a30f26caa..a5cf735daf48d 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -911,7 +911,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf820150, + 0xbf85fff8, 0xbf820152, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1024,62 +1024,63 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0xbf84fff0, 0xba80f801, + 0x00000000, 0xbf8a0000, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0xb9f9f816, - 0x876f7bff, 0xfffff800, - 0x906f8b6f, 0xb9efa2c3, - 0xb9f3f801, 0xb96e2a05, - 0x806e816e, 0xbf0d9972, - 0xbf850002, 0x8f6e896e, - 0xbf820001, 0x8f6e8a6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876fff6d, - 0xfc000000, 0x906f9a6f, - 0x8f6f906f, 0xbeee0380, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0xb9f9f816, 0x876f7bff, + 0xfffff800, 0x906f8b6f, + 0xb9efa2c3, 0xb9f3f801, + 0xb96e2a05, 0x806e816e, + 0xbf0d9972, 0xbf850002, + 0x8f6e896e, 0xbf820001, + 0x8f6e8a6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876fff6d, 0xfc000000, + 0x906f9a6f, 0x8f6f906f, + 0xbeee0380, 0x886e6f6e, + 0x876fff6d, 0x02000000, + 0x906f996f, 0x8f6f8f6f, 0x886e6f6e, 0x876fff6d, - 0x02000000, 0x906f996f, - 0x8f6f8f6f, 0x886e6f6e, - 0x876fff6d, 0x01000000, - 0x906f986f, 0x8f6f996f, - 0x886e6f6e, 0x876fff7a, - 0x00800000, 0x906f976f, - 0xb9eef807, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, - 0xbf8a0000, 0xbe80226c, + 0x01000000, 0x906f986f, + 0x8f6f996f, 0x886e6f6e, + 0x876fff7a, 0x00800000, + 0x906f976f, 0xb9eef807, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, @@ -1808,7 +1809,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013b, + 0xbf85fff8, 0xbf82013d, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1921,51 +1922,52 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0xbf84fff0, 0xba80f801, + 0x00000000, 0xbf8a0000, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e2a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0x806eff6e, - 0x00000200, 0x806e746e, - 0x826f8075, 0x876fff6f, - 0x0000ffff, 0xf4091c37, - 0xfa000050, 0xf4091d37, - 0xfa000060, 0xf4011e77, - 0xfa000074, 0xbf8cc07f, - 0x876dff6d, 0x0000ffff, - 0x87fe7e7e, 0x87ea6a6a, - 0xb9faf802, 0xbf8a0000, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e2a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0x806eff6e, 0x00000200, + 0x806e746e, 0x826f8075, + 0x876fff6f, 0x0000ffff, + 0xf4091c37, 0xfa000050, + 0xf4091d37, 0xfa000060, + 0xf4011e77, 0xfa000074, + 0xbf8cc07f, 0x876dff6d, + 0x0000ffff, 0x87fe7e7e, + 0x87ea6a6a, 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 4569db452160d..0f8e06a2ea8d9 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -895,6 +895,11 @@ L_RESTORE_SGPR: s_cmp_eq_u32 m0, 0 //scc = (m0 < s_sgpr_save_num) ? 1 : 0 s_cbranch_scc0 L_RESTORE_SGPR_LOOP + // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. + // Clear DEBUG_EN before and restore MODE after the barrier. + s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 + s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG + /* restore HW registers */ L_RESTORE_HWREG: // HWREG SR memory offset : size(VGPR)+size(SVGPR)+size(SGPR) @@ -978,8 +983,6 @@ L_RESTORE_HWREG: s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu - s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG - s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: -- GitLab From 1df67a4ecedd34046a867afa6b29c12baf03cd25 Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Sat, 25 Jul 2020 09:30:35 -0400 Subject: [PATCH 0055/1494] Revert "drm/amdgpu/vcn3.0: remove extra asic type check" This reverts commit 058c07201ec7d373fc6a0a570b38a8a9d62c29fb. Chip NAVY_FLOUNDER uses vcn3.0, but it has only one VCN instance. Signed-off-by: James Zhu <James.Zhu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 29 +++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 101fc4948110e..63e5547cfb16d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -88,20 +88,23 @@ static int vcn_v3_0_early_init(void *handle) adev->vcn.num_enc_rings = 1; } else { - u32 harvest; - int i; - - adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); - if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) - adev->vcn.harvest_config |= 1 << i; - } + if (adev->asic_type == CHIP_SIENNA_CICHLID) { + u32 harvest; + int i; + + adev->vcn.num_vcn_inst = VCN_INSTANCES_SIENNA_CICHLID; + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + harvest = RREG32_SOC15(VCN, i, mmCC_UVD_HARVESTING); + if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) + adev->vcn.harvest_config |= 1 << i; + } - if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | - AMDGPU_VCN_HARVEST_VCN1)) - /* both instances are harvested, disable the block */ - return -ENOENT; + if (adev->vcn.harvest_config == (AMDGPU_VCN_HARVEST_VCN0 | + AMDGPU_VCN_HARVEST_VCN1)) + /* both instances are harvested, disable the block */ + return -ENOENT; + } else + adev->vcn.num_vcn_inst = 1; adev->vcn.num_enc_rings = 2; } -- GitLab From 81b41ff5d287bc2346ee7ffb544ace3557f05642 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 14 Jul 2020 14:25:39 +0800 Subject: [PATCH 0056/1494] drm/amd/powerplay: revise the outputs layout of amdgpu_pm_info debugfs The current outputs of amdgpu_pm_info debugfs come with clock gating status and followed by current clock/power information. However the clock gating status retrieving may pull GFX out of CG status. That will make the succeeding clock/power information retrieving inaccurate. To overcome this and be with minimum impact, the outputs are updated to show current clock/power information first. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 2f7b0550ff16f..581b2d6bea3b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -4131,14 +4131,6 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return r; } - down_read(&adev->reset_sem); - amdgpu_device_ip_get_clockgating_state(adev, &flags); - up_read(&adev->reset_sem); - - seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); - amdgpu_parse_cg_state(m, flags); - seq_printf(m, "\n"); - if (!adev->pm.dpm_enabled) { seq_printf(m, "dpm not enabled\n"); pm_runtime_mark_last_busy(dev->dev); @@ -4160,7 +4152,18 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) r = amdgpu_debugfs_pm_info_pp(m, adev); } up_read(&adev->reset_sem); + if (r) + goto out; + + down_read(&adev->reset_sem); + amdgpu_device_ip_get_clockgating_state(adev, &flags); + up_read(&adev->reset_sem); + + seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); + amdgpu_parse_cg_state(m, flags); + seq_printf(m, "\n"); +out: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); -- GitLab From 6b36fa6143f6caa16bfe92c639b3dad4694b58b0 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Mon, 27 Jul 2020 10:41:44 +0800 Subject: [PATCH 0057/1494] drm/amdgpu: add umc v8_7_0 IP headers the change introduces IP headers for unified memory controller (umc) Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../include/asic_reg/umc/umc_8_7_0_offset.h | 33 ++++++++ .../include/asic_reg/umc/umc_8_7_0_sh_mask.h | 79 +++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_offset.h create mode 100644 drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h diff --git a/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_offset.h new file mode 100644 index 0000000000000..3685766c4d566 --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_offset.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _umc_8_7_0_OFFSET_HEADER +#define _umc_8_7_0_OFFSET_HEADER + +#define mmUMCCH0_0_GeccErrCntSel 0x0328 +#define mmUMCCH0_0_GeccErrCntSel_BASE_IDX 0 +#define mmUMCCH0_0_GeccErrCnt 0x0329 +#define mmUMCCH0_0_GeccErrCnt_BASE_IDX 0 +#define mmMCA_UMC_UMC0_MCUMC_STATUST0 0x03c2 +#define mmMCA_UMC_UMC0_MCUMC_STATUST0_BASE_IDX 0 +#define mmMCA_UMC_UMC0_MCUMC_ADDRT0 0x03c4 +#define mmMCA_UMC_UMC0_MCUMC_ADDRT0_BASE_IDX 0 + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h new file mode 100644 index 0000000000000..4c5097fa0c098 --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/umc/umc_8_7_0_sh_mask.h @@ -0,0 +1,79 @@ +#ifndef _umc_8_7_0_SH_MASK_HEADER +#define _umc_8_7_0_SH_MASK_HEADER + +//UMCCH0_0_GeccErrCntSel +#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel__SHIFT 0x0 +#define UMCCH0_0_GeccErrCntSel__GeccErrInt__SHIFT 0xc +#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn__SHIFT 0xf +#define UMCCH0_0_GeccErrCntSel__PoisonCntEn__SHIFT 0x10 +#define UMCCH0_0_GeccErrCntSel__GeccErrCntCsSel_MASK 0x0000000FL +#define UMCCH0_0_GeccErrCntSel__GeccErrInt_MASK 0x00003000L +#define UMCCH0_0_GeccErrCntSel__GeccErrCntEn_MASK 0x00008000L +#define UMCCH0_0_GeccErrCntSel__PoisonCntEn_MASK 0x00030000L +//UMCCH0_0_GeccErrCnt +#define UMCCH0_0_GeccErrCnt__GeccErrCnt__SHIFT 0x0 +#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt__SHIFT 0x10 +#define UMCCH0_0_GeccErrCnt__GeccErrCnt_MASK 0x0000FFFFL +#define UMCCH0_0_GeccErrCnt__GeccUnCorrErrCnt_MASK 0xFFFF0000L +//MCA_UMC_UMC0_MCUMC_STATUST0 +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode__SHIFT 0x0 +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt__SHIFT 0x10 +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22__SHIFT 0x16 +#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb__SHIFT 0x18 +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30__SHIFT 0x1e +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId__SHIFT 0x20 +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38__SHIFT 0x26 +#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub__SHIFT 0x28 +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41__SHIFT 0x29 +#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison__SHIFT 0x2b +#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred__SHIFT 0x2c +#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC__SHIFT 0x2d +#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC__SHIFT 0x2e +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47__SHIFT 0x2f +#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent__SHIFT 0x34 +#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV__SHIFT 0x35 +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54__SHIFT 0x36 +#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC__SHIFT 0x37 +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal__SHIFT 0x38 +#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC__SHIFT 0x39 +#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV__SHIFT 0x3a +#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV__SHIFT 0x3b +#define MCA_UMC_UMC0_MCUMC_STATUST0__En__SHIFT 0x3c +#define MCA_UMC_UMC0_MCUMC_STATUST0__UC__SHIFT 0x3d +#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow__SHIFT 0x3e +#define MCA_UMC_UMC0_MCUMC_STATUST0__Val__SHIFT 0x3f +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCode_MASK 0x000000000000FFFFL +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrorCodeExt_MASK 0x00000000003F0000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV22_MASK 0x0000000000C00000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrLsb_MASK 0x000000003F000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV30_MASK 0x00000000C0000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreId_MASK 0x0000003F00000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV38_MASK 0x000000C000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Scrub_MASK 0x0000010000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV41_MASK 0x0000060000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Poison_MASK 0x0000080000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Deferred_MASK 0x0000100000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__UECC_MASK 0x0000200000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__CECC_MASK 0x0000400000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV47_MASK 0x000F800000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Transparent_MASK 0x0010000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__SyndV_MASK 0x0020000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__RESERV54_MASK 0x0040000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__TCC_MASK 0x0080000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__ErrCoreIdVal_MASK 0x0100000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__PCC_MASK 0x0200000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__AddrV_MASK 0x0400000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__MiscV_MASK 0x0800000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__En_MASK 0x1000000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__UC_MASK 0x2000000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Overflow_MASK 0x4000000000000000L +#define MCA_UMC_UMC0_MCUMC_STATUST0__Val_MASK 0x8000000000000000L +//MCA_UMC_UMC0_MCUMC_ADDRT0 +#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT 0x0 +#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB__SHIFT 0x38 +#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT 0x3e +#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK 0x00FFFFFFFFFFFFFFL +#define MCA_UMC_UMC0_MCUMC_ADDRT0__LSB_MASK 0x3F00000000000000L +#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK 0xC000000000000000L + +#endif -- GitLab From d817f3753e6d31469358d2ae7664b616360d057f Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Fri, 24 Jul 2020 17:24:08 +0800 Subject: [PATCH 0058/1494] drm/amd/powerplay: update driver if file for sienna_cichlid Update sienna_cichlid driver if header and related files. Support new smu metrics for pre & postDS frequency. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../inc/smu11_driver_if_sienna_cichlid.h | 21 +++++++++++++------ drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 11 +++++++--- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h index b2232e24d82f6..aa2708fccb6de 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x33 +#define SMU11_DRIVER_IF_VERSION 0x34 #define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 @@ -968,9 +968,15 @@ typedef struct { typedef struct { uint32_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageFclkFrequency; - uint16_t AverageUclkFrequency ; + + uint16_t AverageGfxclkFrequencyPreDs; + uint16_t AverageGfxclkFrequencyPostDs; + uint16_t AverageFclkFrequencyPreDs; + uint16_t AverageFclkFrequencyPostDs; + uint16_t AverageUclkFrequencyPreDs ; + uint16_t AverageUclkFrequencyPostDs ; + + uint16_t AverageGfxActivity ; uint16_t AverageUclkActivity ; uint8_t CurrSocVoltageOffset ; @@ -988,6 +994,7 @@ typedef struct { uint16_t TemperatureLiquid0 ; uint16_t TemperatureLiquid1 ; uint16_t TemperaturePlx ; + uint16_t Padding16 ; uint32_t ThrottlerStatus ; uint8_t LinkDpmLevel; @@ -1006,8 +1013,10 @@ typedef struct { uint16_t AverageDclk0Frequency ; uint16_t AverageVclk1Frequency ; uint16_t AverageDclk1Frequency ; - uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence - uint16_t padding16_2; + uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence + uint8_t PcieRate ; + uint8_t PcieWidth ; + } SmuMetrics_t; typedef struct { diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 429f5aa8924a0..9504f9954fd3f 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -30,7 +30,7 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x33 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x34 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x2 /* MP Apertures */ diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index dcc5d25a78940..f64a1be94cb8c 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -70,6 +70,8 @@ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \ FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) +#define SMU_11_0_7_GFX_BUSY_THRESHOLD 15 + static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -443,13 +445,16 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, *value = metrics->CurrClock[PPCLK_DCEFCLK]; break; case METRICS_AVERAGE_GFXCLK: - *value = metrics->AverageGfxclkFrequency; + if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) + *value = metrics->AverageGfxclkFrequencyPostDs; + else + *value = metrics->AverageGfxclkFrequencyPreDs; break; case METRICS_AVERAGE_FCLK: - *value = metrics->AverageFclkFrequency; + *value = metrics->AverageFclkFrequencyPostDs; break; case METRICS_AVERAGE_UCLK: - *value = metrics->AverageUclkFrequency; + *value = metrics->AverageUclkFrequencyPostDs; break; case METRICS_AVERAGE_GFXACTIVITY: *value = metrics->AverageGfxActivity; -- GitLab From 48ef409c25a632caeb19093b8513a17028372097 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Mon, 27 Jul 2020 11:36:18 +0800 Subject: [PATCH 0059/1494] drm/amdgpu: add support for umc 8.7 ras functions added support for umc 8.7 error reporting and query Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 331 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/umc_v8_7.h | 51 ++++ 2 files changed, 382 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/umc_v8_7.c create mode 100644 drivers/gpu/drm/amd/amdgpu/umc_v8_7.h diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c new file mode 100644 index 0000000000000..5665c77a9d587 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -0,0 +1,331 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "umc_v8_7.h" +#include "amdgpu_ras.h" +#include "amdgpu.h" + +#include "rsmu/rsmu_0_0_2_offset.h" +#include "rsmu/rsmu_0_0_2_sh_mask.h" +#include "umc/umc_8_7_0_offset.h" +#include "umc/umc_8_7_0_sh_mask.h" + +#define UMC_8_INST_DIST 0x40000 + +const uint32_t + umc_v8_7_channel_idx_tbl[UMC_V8_7_UMC_INSTANCE_NUM][UMC_V8_7_CHANNEL_INSTANCE_NUM] = { + {2, 11}, {4, 13}, + {1, 8}, {7, 14}, + {10, 3}, {12, 5}, + {9, 0}, {15, 6} +}; + +static inline uint32_t get_umc_8_reg_offset(struct amdgpu_device *adev, + uint32_t umc_inst, + uint32_t ch_inst) +{ + return adev->umc.channel_offs*ch_inst + UMC_8_INST_DIST*umc_inst; +} + +static void umc_v8_7_clear_error_count_per_channel(struct amdgpu_device *adev, + uint32_t umc_reg_offset) +{ + uint32_t ecc_err_cnt_addr; + uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr; + + ecc_err_cnt_sel_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel); + ecc_err_cnt_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt); + + /* select the lower chip */ + ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + + umc_reg_offset) * 4); + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, + UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 0); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, + ecc_err_cnt_sel); + + /* clear lower chip error count */ + WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, + UMC_V8_7_CE_CNT_INIT); + + /* select the higher chip */ + ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + + umc_reg_offset) * 4); + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, + UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 1); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, + ecc_err_cnt_sel); + + /* clear higher chip error count */ + WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, + UMC_V8_7_CE_CNT_INIT); +} + +static void umc_v8_7_clear_error_count(struct amdgpu_device *adev) +{ + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_8_reg_offset(adev, + umc_inst, + ch_inst); + + umc_v8_7_clear_error_count_per_channel(adev, + umc_reg_offset); + } +} + +static void umc_v8_7_query_correctable_error_count(struct amdgpu_device *adev, + uint32_t umc_reg_offset, + unsigned long *error_count) +{ + uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr; + uint32_t ecc_err_cnt, ecc_err_cnt_addr; + uint64_t mc_umc_status; + uint32_t mc_umc_status_addr; + + /* UMC 8_7_2 registers */ + ecc_err_cnt_sel_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel); + ecc_err_cnt_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt); + mc_umc_status_addr = + SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0); + + /* select the lower chip and check the error count */ + ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4); + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 0); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel); + + ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4); + *error_count += + (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_GeccErrCnt, GeccErrCnt) - + UMC_V8_7_CE_CNT_INIT); + + /* select the higher chip and check the err counter */ + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 1); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel); + + ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4); + *error_count += + (REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_GeccErrCnt, GeccErrCnt) - + UMC_V8_7_CE_CNT_INIT); + + /* check for SRAM correctable error + MCUMC_STATUS is a 64 bit register */ + mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4); + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, ErrorCodeExt) == 6 && + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) + *error_count += 1; +} + +static void umc_v8_7_querry_uncorrectable_error_count(struct amdgpu_device *adev, + uint32_t umc_reg_offset, + unsigned long *error_count) +{ + uint64_t mc_umc_status; + uint32_t mc_umc_status_addr; + + mc_umc_status_addr = SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0); + + /* check the MCUMC_STATUS */ + mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4); + if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)) + *error_count += 1; +} + +static void umc_v8_7_query_ras_error_count(struct amdgpu_device *adev, + void *ras_error_status) +{ + struct ras_err_data* err_data = (struct ras_err_data*)ras_error_status; + + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_8_reg_offset(adev, + umc_inst, + ch_inst); + + umc_v8_7_query_correctable_error_count(adev, + umc_reg_offset, + &(err_data->ce_count)); + umc_v8_7_querry_uncorrectable_error_count(adev, + umc_reg_offset, + &(err_data->ue_count)); + } + + umc_v8_7_clear_error_count(adev); +} + +static void umc_v8_7_query_error_address(struct amdgpu_device *adev, + struct ras_err_data *err_data, + uint32_t umc_reg_offset, + uint32_t ch_inst, + uint32_t umc_inst) +{ + uint32_t lsb, mc_umc_status_addr; + uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; + struct eeprom_table_record *err_rec; + uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; + + mc_umc_status_addr = + SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_STATUST0); + mc_umc_addrt0 = + SOC15_REG_OFFSET(UMC, 0, mmMCA_UMC_UMC0_MCUMC_ADDRT0); + + mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4); + + if (mc_umc_status == 0) + return; + + if (!err_data->err_addr) { + /* clear umc status */ + WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL); + return; + } + + err_rec = &err_data->err_addr[err_data->err_addr_cnt]; + + /* calculate error address if ue/ce error is detected */ + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) { + + err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4); + /* the lowest lsb bits should be ignored */ + lsb = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, LSB); + err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); + err_addr &= ~((0x1ULL << lsb) - 1); + + /* translate umc channel address to soc pa, 3 parts are included */ + retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + ADDR_OF_256B_BLOCK(channel_index) | + OFFSET_IN_256B_BLOCK(err_addr); + + /* we only save ue error information currently, ce is skipped */ + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) + == 1) { + err_rec->address = err_addr; + /* page frame address is saved */ + err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; + err_rec->ts = (uint64_t)ktime_get_real_seconds(); + err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; + err_rec->cu = 0; + err_rec->mem_channel = channel_index; + err_rec->mcumc_id = umc_inst; + + err_data->err_addr_cnt++; + } + } + + /* clear umc status */ + WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL); +} + +static void umc_v8_7_query_ras_error_address(struct amdgpu_device *adev, + void *ras_error_status) +{ + struct ras_err_data* err_data = (struct ras_err_data*)ras_error_status; + + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_8_reg_offset(adev, + umc_inst, + ch_inst); + + umc_v8_7_query_error_address(adev, + err_data, + umc_reg_offset, + ch_inst, + umc_inst); + } +} + +static void umc_v8_7_err_cnt_init_per_channel(struct amdgpu_device *adev, + uint32_t umc_reg_offset) +{ + uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr; + uint32_t ecc_err_cnt_addr; + + ecc_err_cnt_sel_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCntSel); + ecc_err_cnt_addr = + SOC15_REG_OFFSET(UMC, 0, mmUMCCH0_0_GeccErrCnt); + + /* select the lower chip and check the error count */ + ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4); + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 0); + /* set ce error interrupt type to APIC based interrupt */ + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel, + GeccErrInt, 0x1); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel); + /* set error count to initial value */ + WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V8_7_CE_CNT_INIT); + + /* select the higher chip and check the err counter */ + ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_GeccErrCntSel, + GeccErrCntCsSel, 1); + WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel); + WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4, UMC_V8_7_CE_CNT_INIT); +} + +static void umc_v8_7_err_cnt_init(struct amdgpu_device *adev) +{ + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_8_reg_offset(adev, + umc_inst, + ch_inst); + + umc_v8_7_err_cnt_init_per_channel(adev, umc_reg_offset); + } +} + +const struct amdgpu_umc_funcs umc_v8_7_funcs = { + .err_cnt_init = umc_v8_7_err_cnt_init, + .ras_late_init = amdgpu_umc_ras_late_init, + .query_ras_error_count = umc_v8_7_query_ras_error_count, + .query_ras_error_address = umc_v8_7_query_ras_error_address, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h new file mode 100644 index 0000000000000..d4d0468e3df50 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __UMC_V8_7_H__ +#define __UMC_V8_7_H__ + +#include "soc15_common.h" +#include "amdgpu.h" + +/* HBM Memory Channel Width */ +#define UMC_V8_7_HBM_MEMORY_CHANNEL_WIDTH 128 +/* number of umc channel instance with memory map register access */ +#define UMC_V8_7_CHANNEL_INSTANCE_NUM 2 +/* number of umc instance with memory map register access */ +#define UMC_V8_7_UMC_INSTANCE_NUM 8 +/* total channel instances in one umc block */ +#define UMC_V8_7_TOTAL_CHANNEL_NUM (UMC_V8_7_CHANNEL_INSTANCE_NUM * UMC_V8_7_UMC_INSTANCE_NUM) +/* UMC regiser per channel offset */ +#define UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA 0x400 + +/* EccErrCnt max value */ +#define UMC_V8_7_CE_CNT_MAX 0xffff +/* umc ce interrupt threshold */ +#define UMC_V8_7_CE_INT_THRESHOLD 0xffff +/* umc ce count initial value */ +#define UMC_V8_7_CE_CNT_INIT (UMC_V8_7_CE_CNT_MAX - UMC_V8_7_CE_INT_THRESHOLD) + +extern const struct amdgpu_umc_funcs umc_v8_7_funcs; +extern const uint32_t + umc_v8_7_channel_idx_tbl[UMC_V8_7_UMC_INSTANCE_NUM][UMC_V8_7_CHANNEL_INSTANCE_NUM]; + +#endif -- GitLab From 0eb52d81565588797d031d50f09fe871112f1138 Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevin1.wang@amd.com> Date: Mon, 27 Jul 2020 09:08:22 +0800 Subject: [PATCH 0060/1494] drm/amd/swsmu: allow asic to handle sensor type by itself 1. allow asic to handle sensor type by itself. 2. if not, use smu common sensor to handle it. Signed-off-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 3b427fa099fec..55463e7a11e2a 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -1948,6 +1948,10 @@ int smu_read_sensor(struct smu_context *smu, mutex_lock(&smu->mutex); + if (smu->ppt_funcs->read_sensor) + if (!smu->ppt_funcs->read_sensor(smu, sensor, data, size)) + goto unlock; + switch (sensor) { case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK: *((uint32_t *)data) = pstate_table->gfxclk_pstate.standard * 100; @@ -1978,11 +1982,12 @@ int smu_read_sensor(struct smu_context *smu, *size = 4; break; default: - if (smu->ppt_funcs->read_sensor) - ret = smu->ppt_funcs->read_sensor(smu, sensor, data, size); + *size = 0; + ret = -EOPNOTSUPP; break; } +unlock: mutex_unlock(&smu->mutex); return ret; -- GitLab From a00d8fd405ed7c071b2e3fa12a2e03d0a0d2d6fa Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Mon, 6 Jul 2020 10:54:37 -0400 Subject: [PATCH 0061/1494] drm/amd/display: Clean up global sync param retrieval [Why] This change replaces older looping code in favor of these functions. [How] There are built in functions for extracting global sync params during mode validation now. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Reviewed-by: Eric Bernstein <Eric.Bernstein@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 49 ++----------------- .../drm/amd/display/dc/dml/display_mode_vba.c | 14 +----- .../drm/amd/display/dc/dml/display_mode_vba.h | 7 +-- 3 files changed, 7 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 968a89bbcf242..2a5e7175926ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3069,8 +3069,7 @@ void dcn20_calculate_dlg_params( int pipe_cnt, int vlevel) { - int i, j, pipe_idx, pipe_idx_unsplit; - bool visited[MAX_PIPES] = { 0 }; + int i, pipe_idx; /* Writeback MCIF_WB arbitration parameters */ dc->res_pool->funcs->set_mcif_arb_params(dc, context, pipes, pipe_cnt); @@ -3089,55 +3088,17 @@ void dcn20_calculate_dlg_params( if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz) context->bw_ctx.bw.dcn.clk.dispclk_khz = dc->debug.min_disp_clk_khz; - /* - * An artifact of dml pipe split/odm is that pipes get merged back together for - * calculation. Therefore we need to only extract for first pipe in ascending index order - * and copy into the other split half. - */ - for (i = 0, pipe_idx = 0, pipe_idx_unsplit = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - if (!visited[pipe_idx]) { - display_pipe_source_params_st *src = &pipes[pipe_idx].pipe.src; - display_pipe_dest_params_st *dst = &pipes[pipe_idx].pipe.dest; - - dst->vstartup_start = context->bw_ctx.dml.vba.VStartup[pipe_idx_unsplit]; - dst->vupdate_offset = context->bw_ctx.dml.vba.VUpdateOffsetPix[pipe_idx_unsplit]; - dst->vupdate_width = context->bw_ctx.dml.vba.VUpdateWidthPix[pipe_idx_unsplit]; - dst->vready_offset = context->bw_ctx.dml.vba.VReadyOffsetPix[pipe_idx_unsplit]; - /* - * j iterates inside pipes array, unlike i which iterates inside - * pipe_ctx array - */ - if (src->is_hsplit) - for (j = pipe_idx + 1; j < pipe_cnt; j++) { - display_pipe_source_params_st *src_j = &pipes[j].pipe.src; - display_pipe_dest_params_st *dst_j = &pipes[j].pipe.dest; - - if (src_j->is_hsplit && !visited[j] - && src->hsplit_grp == src_j->hsplit_grp) { - dst_j->vstartup_start = context->bw_ctx.dml.vba.VStartup[pipe_idx_unsplit]; - dst_j->vupdate_offset = context->bw_ctx.dml.vba.VUpdateOffsetPix[pipe_idx_unsplit]; - dst_j->vupdate_width = context->bw_ctx.dml.vba.VUpdateWidthPix[pipe_idx_unsplit]; - dst_j->vready_offset = context->bw_ctx.dml.vba.VReadyOffsetPix[pipe_idx_unsplit]; - visited[j] = true; - } - } - visited[pipe_idx] = true; - pipe_idx_unsplit++; - } - pipe_idx++; - } - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; + pipes[pipe_idx].pipe.dest.vstartup_start = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vupdate_offset = get_vupdate_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vupdate_width = get_vupdate_width(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + pipes[pipe_idx].pipe.dest.vready_offset = get_vready_offset(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000; - ASSERT(visited[pipe_idx]); context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest; pipe_idx++; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 7916a7ea93367..b0064087b9bbb 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -154,23 +154,11 @@ dml_get_pipe_attr_func(refcyc_per_meta_chunk_vblank_c_in_us, mode_lib->vba.TimeP dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_l_in_us, mode_lib->vba.TimePerMetaChunkFlip); dml_get_pipe_attr_func(refcyc_per_meta_chunk_flip_c_in_us, mode_lib->vba.TimePerChromaMetaChunkFlip); +dml_get_pipe_attr_func(vstartup, mode_lib->vba.VStartup); dml_get_pipe_attr_func(vupdate_offset, mode_lib->vba.VUpdateOffsetPix); dml_get_pipe_attr_func(vupdate_width, mode_lib->vba.VUpdateWidthPix); dml_get_pipe_attr_func(vready_offset, mode_lib->vba.VReadyOffsetPix); -unsigned int get_vstartup_calculated( - struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes, - unsigned int which_pipe) -{ - unsigned int which_plane; - - recalculate_params(mode_lib, pipes, num_pipes); - which_plane = mode_lib->vba.pipe_plane[which_pipe]; - return mode_lib->vba.VStartup[which_plane]; -} - double get_total_immediate_flip_bytes( struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 756d8eb1221ca..21e5111ea7a08 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -98,16 +98,11 @@ dml_get_pipe_attr_decl(refcyc_per_meta_chunk_vblank_c_in_us); dml_get_pipe_attr_decl(refcyc_per_meta_chunk_flip_l_in_us); dml_get_pipe_attr_decl(refcyc_per_meta_chunk_flip_c_in_us); +dml_get_pipe_attr_decl(vstartup); dml_get_pipe_attr_decl(vupdate_offset); dml_get_pipe_attr_decl(vupdate_width); dml_get_pipe_attr_decl(vready_offset); -unsigned int get_vstartup_calculated( - struct display_mode_lib *mode_lib, - const display_e2e_pipe_params_st *pipes, - unsigned int num_pipes, - unsigned int which_pipe); - double get_total_immediate_flip_bytes( struct display_mode_lib *mode_lib, const display_e2e_pipe_params_st *pipes, -- GitLab From 91b2e45be439e098f4f2e17be1c87570e5a42928 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Tue, 16 Jun 2020 16:24:11 -0400 Subject: [PATCH 0062/1494] drm/amd/display: Rename bytes_pp to the correct bits_pp [Why] Struct dcn_dsc_state is used for reading current state and parameters of DSC on a pipe, the target rate parameter uses bytes per pixel even though its reading BITS_PER_PIXEL register. [How] Changing it to Bits Per Pixel for consistency. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 +++- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 998f729976bf1..1c177c2ad1dc8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1186,7 +1186,7 @@ static ssize_t dp_dsc_bytes_per_pixel_read(struct file *f, char __user *buf, snprintf(rd_buf_ptr, str_len, "%d\n", - dsc_state.dsc_bytes_per_pixel); + dsc_state.dsc_bits_per_pixel); rd_buf_ptr += str_len; while (size) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index da0897fe3b543..a643927e272bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -390,6 +390,8 @@ void dcn10_log_hw_state(struct dc *dc, } DTN_INFO("\n"); + // dcn_dsc_state struct field bytes_per_pixel was renamed to bits_per_pixel + // TODO: Update golden log header to reflect this name change DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n"); for (i = 0; i < pool->res_cap->num_dsc; i++) { struct display_stream_compressor *dsc = pool->dscs[i]; @@ -400,7 +402,7 @@ void dcn10_log_hw_state(struct dc *dc, dsc->inst, s.dsc_clock_en, s.dsc_slice_width, - s.dsc_bytes_per_pixel); + s.dsc_bits_per_pixel); DTN_INFO("\n"); } DTN_INFO("\n"); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c index ba50214d6c325..79b640e202eb4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c @@ -156,7 +156,7 @@ static void dsc2_read_state(struct display_stream_compressor *dsc, struct dcn_ds REG_GET(DSC_TOP_CONTROL, DSC_CLOCK_EN, &s->dsc_clock_en); REG_GET(DSCC_PPS_CONFIG3, SLICE_WIDTH, &s->dsc_slice_width); - REG_GET(DSCC_PPS_CONFIG1, BITS_PER_PIXEL, &s->dsc_bytes_per_pixel); + REG_GET(DSCC_PPS_CONFIG1, BITS_PER_PIXEL, &s->dsc_bits_per_pixel); REG_GET(DSCC_PPS_CONFIG3, SLICE_HEIGHT, &s->dsc_slice_height); REG_GET(DSCC_PPS_CONFIG1, CHUNK_SIZE, &s->dsc_chunk_size); REG_GET(DSCC_PPS_CONFIG2, PIC_WIDTH, &s->dsc_pic_width); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h index 5915994f9eb84..f520e13aee4c2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h @@ -55,7 +55,7 @@ struct dsc_optc_config { struct dcn_dsc_state { uint32_t dsc_clock_en; uint32_t dsc_slice_width; - uint32_t dsc_bytes_per_pixel; + uint32_t dsc_bits_per_pixel; uint32_t dsc_slice_height; uint32_t dsc_pic_width; uint32_t dsc_pic_height; -- GitLab From f92e25e56137cb410c89dd5d69aed47849b3236c Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Tue, 16 Jun 2020 16:29:19 -0400 Subject: [PATCH 0063/1494] drm/amd/display: Fix naming of DSC Debugfs entry [why] Fix naming and return bits rather than bytes per pixel for naming consistency. Because registers return Bytes per pixel, but DSC Config structure is expecting bits per pixel as input. So when returning the value convert from bytes into bits. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 1c177c2ad1dc8..e5a6d91159498 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -35,6 +35,7 @@ #include "dmub/dmub_srv.h" #include "resource.h" #include "dsc.h" +#include "dc_link_dp.h" struct dmub_debugfs_trace_header { uint32_t entry_count; @@ -1150,7 +1151,7 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, return result; } -static ssize_t dp_dsc_bytes_per_pixel_read(struct file *f, char __user *buf, +static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { char *rd_buf = NULL; @@ -1460,9 +1461,9 @@ static const struct file_operations dp_dsc_slice_height_debugfs_fops = { .llseek = default_llseek }; -static const struct file_operations dp_dsc_bytes_per_pixel_debugfs_fops = { +static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = { .owner = THIS_MODULE, - .read = dp_dsc_bytes_per_pixel_read, + .read = dp_dsc_bits_per_pixel_read, .llseek = default_llseek }; @@ -1552,7 +1553,7 @@ static const struct { {"dsc_clock_en", &dp_dsc_clock_en_debugfs_fops}, {"dsc_slice_width", &dp_dsc_slice_width_debugfs_fops}, {"dsc_slice_height", &dp_dsc_slice_height_debugfs_fops}, - {"dsc_bytes_per_pixel", &dp_dsc_bytes_per_pixel_debugfs_fops}, + {"dsc_bits_per_pixel", &dp_dsc_bits_per_pixel_debugfs_fops}, {"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops}, {"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops}, {"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops}, -- GitLab From be6ccdf861de048833b2000d80db800ab4f8d81b Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Tue, 14 Jul 2020 15:06:40 -0400 Subject: [PATCH 0064/1494] drm/amd/display: Don't compare dppclk before updating DTO [Why] In dcn3_update_clocks there are situations where dppclk is not lowered (i.e. stays the same), but DTO still needs to be increased before we program pipe frontend (i.e. in prepare_bandwidth). If we don't program the new DTO value before we program the pipe, we will underflow as soon as the pipe lock is released until the next call to dcn3_update_clocks where the DTO is updated. [How] Remove dppclk check before programming new DTO value. Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index d8af56a58196a..b0e9b0509568c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -323,9 +323,10 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, /* if clock is being raised, increase refclk before lowering DTO */ if (update_dppclk || update_dispclk) dcn20_update_clocks_update_dentist(clk_mgr); - /* always update dtos unless clock is lowered and not safe to lower */ - if (new_clocks->dppclk_khz >= dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz) - dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); + /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures + * that we do not lower dto when it is not safe to lower. We do not need to + * compare the current and new dppclk before calling this function.*/ + dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); } } -- GitLab From b246f90a09706ecf755c40006fc8b4c07cdfc314 Mon Sep 17 00:00:00 2001 From: Martin Tsai <martin.tsai@amd.com> Date: Wed, 15 Jul 2020 11:21:43 +0800 Subject: [PATCH 0065/1494] drm/amd/display: Check lane status again after link training done [Why] Some monitors could suffer symbol unlock but cannot send HPD IRQ to notic source device to handle link loss. This makes monitor stuck in abnormal status and causes black screen. [How] According to the suggestion from scalar vendor, to check lane status again after link training done. That can improve the comaptibility from current production monitors. Signed-off-by: Martin Tsai <martin.tsai@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 50 +++++++++++++++++++ .../amd/display/include/link_service_types.h | 2 + 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 5cb7b834e459f..1a3dbed3becbd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1133,6 +1133,45 @@ static inline enum link_training_result perform_link_training_int( return status; } +static enum link_training_result check_link_loss_status( + struct dc_link *link, + const struct link_training_settings *link_training_setting) +{ + enum link_training_result status = LINK_TRAINING_SUCCESS; + unsigned int lane01_status_address = DP_LANE0_1_STATUS; + union lane_status lane_status; + uint8_t dpcd_buf[4] = {0}; + uint32_t lane; + + core_link_read_dpcd( + link, + lane01_status_address, + (uint8_t *)(dpcd_buf), + sizeof(dpcd_buf)); + + /*parse lane status*/ + for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { + /* + * check lanes status + */ + lane_status.raw = get_nibble_at_index(&dpcd_buf[0], lane); + + if (!lane_status.bits.CHANNEL_EQ_DONE_0 || + !lane_status.bits.CR_DONE_0 || + !lane_status.bits.SYMBOL_LOCKED_0) { + /* if one of the channel equalization, clock + * recovery or symbol lock is dropped + * consider it as (link has been + * dropped) dp sink status has changed + */ + status = LINK_TRAINING_LINK_LOSS; + break; + } + } + + return status; +} + static void initialize_training_settings( struct dc_link *link, const struct dc_link_settings *link_setting, @@ -1372,6 +1411,9 @@ static void print_status_message( case LINK_TRAINING_LQA_FAIL: lt_result = "LQA failed"; break; + case LINK_TRAINING_LINK_LOSS: + lt_result = "Link loss"; + break; default: break; } @@ -1531,6 +1573,14 @@ enum link_training_result dc_link_dp_perform_link_training( status); } + /* delay 5ms after Main Link output idle pattern and then check + * DPCD 0202h. + */ + if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) { + msleep(5); + status = check_link_loss_status(link, <_settings); + } + /* 6. print status message*/ print_status_message(link, <_settings, status); diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 4869d4562e4d8..550f46e9b95f6 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -66,6 +66,8 @@ enum link_training_result { /* other failure during EQ step */ LINK_TRAINING_EQ_FAIL_EQ, LINK_TRAINING_LQA_FAIL, + /* one of the CR,EQ or symbol lock is dropped */ + LINK_TRAINING_LINK_LOSS, }; struct link_training_settings { -- GitLab From 94bc373b7f1669b0fa227051f6080a6988d9d4ea Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Tue, 21 Jul 2020 13:59:52 -0400 Subject: [PATCH 0066/1494] drm/amd/display: Use seperate dmcub firmware for navy_flounder [Why] Currently navy_flounder is using sienna_cichlid_dmcub.bin. [How] Create a seperate define so navy_flounder will use its own firmware. Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cf79857ece539..3100c59d17078 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -97,6 +97,8 @@ MODULE_FIRMWARE(FIRMWARE_RENOIR_DMUB); #if defined(CONFIG_DRM_AMD_DC_DCN3_0) #define FIRMWARE_SIENNA_CICHLID_DMUB "amdgpu/sienna_cichlid_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID_DMUB); +#define FIRMWARE_NAVY_FLOUNDER_DMUB "amdgpu/navy_flounder_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER_DMUB); #endif #define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin" @@ -1185,10 +1187,13 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) break; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) case CHIP_SIENNA_CICHLID: - case CHIP_NAVY_FLOUNDER: dmub_asic = DMUB_ASIC_DCN30; fw_name_dmub = FIRMWARE_SIENNA_CICHLID_DMUB; break; + case CHIP_NAVY_FLOUNDER: + dmub_asic = DMUB_ASIC_DCN30; + fw_name_dmub = FIRMWARE_NAVY_FLOUNDER_DMUB; + break; #endif default: -- GitLab From 1ee1290363b57361ebf6addbfbbb57dabc4c7a36 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Fri, 24 Jul 2020 16:36:07 -0400 Subject: [PATCH 0067/1494] drm/amd/display: Use proper abm/backlight functions for DCN3 Use DCN21 functions instead of DCE110 Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 1b354c219d0a1..9afee71604902 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -26,6 +26,7 @@ #include "dce110/dce110_hw_sequencer.h" #include "dcn10/dcn10_hw_sequencer.h" #include "dcn20/dcn20_hwseq.h" +#include "dcn21/dcn21_hwseq.h" #include "dcn30_hwseq.h" static const struct hw_sequencer_funcs dcn30_funcs = { @@ -87,8 +88,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .apply_idle_power_optimizations = dcn30_apply_idle_power_optimizations, - .set_backlight_level = dce110_set_backlight_level, - .set_abm_immediate_disable = dce110_set_abm_immediate_disable, + .set_backlight_level = dcn21_set_backlight_level, + .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, }; static const struct hwseq_private_funcs dcn30_private_funcs = { -- GitLab From f5cd85555bf2ced9725a1eb5cd68f2c2096e283a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Mon, 27 Jul 2020 12:34:36 +0200 Subject: [PATCH 0068/1494] drm/radeon: avoid a useless memset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid a memset after a call to 'dma_alloc_coherent()'. This is useless since commit 518a2f1925c3 ("dma-mapping: zero memory returned from dma_alloc_*") Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_gart.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index f178ba3217151..d099fffbc5beb 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -85,7 +85,6 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) } #endif rdev->gart.ptr = ptr; - memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size); return 0; } -- GitLab From 4c0d0bcb224f968510aff5eddef2b294e5aa4b8b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Mon, 27 Jul 2020 12:34:21 +0200 Subject: [PATCH 0069/1494] drm/radeon: switch from 'pci_' to 'dma_' API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The wrappers in include/linux/pci-dma-compat.h should go away. The patch has been generated with the coccinelle script below and has been hand modified to replace GFP_ with a correct flag. It has been compile tested. When memory is allocated in 'radeon_gart_table_ram_alloc()' GFP_KERNEL can be used because its callers already use this flag. Both 'r100_pci_gart_init()' (r100.c) and 'rs400_gart_init()' (rs400.c) call 'radeon_gart_init()'. This function uses 'vmalloc'. @@ @@ - PCI_DMA_BIDIRECTIONAL + DMA_BIDIRECTIONAL @@ @@ - PCI_DMA_TODEVICE + DMA_TO_DEVICE @@ @@ - PCI_DMA_FROMDEVICE + DMA_FROM_DEVICE @@ @@ - PCI_DMA_NONE + DMA_NONE @@ expression e1, e2, e3; @@ - pci_alloc_consistent(e1, e2, e3) + dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3; @@ - pci_zalloc_consistent(e1, e2, e3) + dma_alloc_coherent(&e1->dev, e2, e3, GFP_) @@ expression e1, e2, e3, e4; @@ - pci_free_consistent(e1, e2, e3, e4) + dma_free_coherent(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_map_single(e1, e2, e3, e4) + dma_map_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_unmap_single(e1, e2, e3, e4) + dma_unmap_single(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4, e5; @@ - pci_map_page(e1, e2, e3, e4, e5) + dma_map_page(&e1->dev, e2, e3, e4, e5) @@ expression e1, e2, e3, e4; @@ - pci_unmap_page(e1, e2, e3, e4) + dma_unmap_page(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_map_sg(e1, e2, e3, e4) + dma_map_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_unmap_sg(e1, e2, e3, e4) + dma_unmap_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_single_for_cpu(e1, e2, e3, e4) + dma_sync_single_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_single_for_device(e1, e2, e3, e4) + dma_sync_single_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_sg_for_cpu(e1, e2, e3, e4) + dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_dma_sync_sg_for_device(e1, e2, e3, e4) + dma_sync_sg_for_device(&e1->dev, e2, e3, e4) @@ expression e1, e2; @@ - pci_dma_mapping_error(e1, e2) + dma_mapping_error(&e1->dev, e2) @@ expression e1, e2; @@ - pci_set_dma_mask(e1, e2) + dma_set_mask(&e1->dev, e2) @@ expression e1, e2; @@ - pci_set_consistent_dma_mask(e1, e2) + dma_set_coherent_mask(&e1->dev, e2) Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_gart.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index d099fffbc5beb..3808a753127bc 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -72,8 +72,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) { void *ptr; - ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, - &rdev->gart.table_addr); + ptr = dma_alloc_coherent(&rdev->pdev->dev, rdev->gart.table_size, + &rdev->gart.table_addr, GFP_KERNEL); if (ptr == NULL) { return -ENOMEM; } @@ -109,9 +109,8 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev) rdev->gart.table_size >> PAGE_SHIFT); } #endif - pci_free_consistent(rdev->pdev, rdev->gart.table_size, - (void *)rdev->gart.ptr, - rdev->gart.table_addr); + dma_free_coherent(&rdev->pdev->dev, rdev->gart.table_size, + (void *)rdev->gart.ptr, rdev->gart.table_addr); rdev->gart.ptr = NULL; rdev->gart.table_addr = 0; } -- GitLab From 9b66d6600e6a060333712c54af90631eb6276d93 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Mon, 27 Jul 2020 16:39:40 +0300 Subject: [PATCH 0070/1494] drm/amd/powerplay: off by one bugs in smu_cmn_to_asic_specific_index() These tables have _COUNT number of elements so the comparisons should be >= instead of > to prevent reading one element beyond the end of the array. Fixes: 8264ee69f0d8 ("drm/amd/powerplay: drop unused code") Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index be4b678d0e601..5c23c44c33bdd 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -166,7 +166,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, switch (type) { case CMN2ASIC_MAPPING_MSG: - if (index > SMU_MSG_MAX_COUNT || + if (index >= SMU_MSG_MAX_COUNT || !smu->message_map) return -EINVAL; @@ -181,7 +181,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return msg_mapping.map_to; case CMN2ASIC_MAPPING_CLK: - if (index > SMU_CLK_COUNT || + if (index >= SMU_CLK_COUNT || !smu->clock_map) return -EINVAL; @@ -192,7 +192,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return mapping.map_to; case CMN2ASIC_MAPPING_FEATURE: - if (index > SMU_FEATURE_COUNT || + if (index >= SMU_FEATURE_COUNT || !smu->feature_map) return -EINVAL; @@ -203,7 +203,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return mapping.map_to; case CMN2ASIC_MAPPING_TABLE: - if (index > SMU_TABLE_COUNT || + if (index >= SMU_TABLE_COUNT || !smu->table_map) return -EINVAL; @@ -214,7 +214,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return mapping.map_to; case CMN2ASIC_MAPPING_PWR: - if (index > SMU_POWER_SOURCE_COUNT || + if (index >= SMU_POWER_SOURCE_COUNT || !smu->pwr_src_map) return -EINVAL; -- GitLab From 6863660d72e4fde650658acc10e4558ec1a277fb Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 22 Jun 2020 17:06:14 -0400 Subject: [PATCH 0071/1494] drm/amdgpu: add some required DCE6 registers (v7) To help with the DC port. v2: add missing masks, add additional registers v3: more updates v4: fix accidently dropped changes v5: add missing nb pstate mask v6: add vblank, vline masks v7: add SCL_HORZ_FILTER_INIT regs Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/include/asic_reg/dce/dce_6_0_d.h | 76 +++++++++++++ .../include/asic_reg/dce/dce_6_0_sh_mask.h | 104 ++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h index ae798f7688534..9de01ae574c03 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h @@ -4444,14 +4444,90 @@ /* Registers that spilled out of sid.h */ #define mmDATA_FORMAT 0x1AC0 +#define mmLB0_DATA_FORMAT 0x1AC0 +#define mmLB1_DATA_FORMAT 0x1DC0 +#define mmLB2_DATA_FORMAT 0x40C0 +#define mmLB3_DATA_FORMAT 0x43C0 +#define mmLB4_DATA_FORMAT 0x46C0 +#define mmLB5_DATA_FORMAT 0x49C0 #define mmDESKTOP_HEIGHT 0x1AC1 +#define mmLB0_DESKTOP_HEIGHT 0x1AC1 +#define mmLB1_DESKTOP_HEIGHT 0x1DC1 +#define mmLB2_DESKTOP_HEIGHT 0x40C1 +#define mmLB3_DESKTOP_HEIGHT 0x43C1 +#define mmLB4_DESKTOP_HEIGHT 0x46C1 +#define mmLB5_DESKTOP_HEIGHT 0x49C1 #define mmDC_LB_MEMORY_SPLIT 0x1AC3 +#define mmLB0_DC_LB_MEMORY_SPLIT 0x1AC3 +#define mmLB1_DC_LB_MEMORY_SPLIT 0x1DC3 +#define mmLB2_DC_LB_MEMORY_SPLIT 0x40C3 +#define mmLB3_DC_LB_MEMORY_SPLIT 0x43C3 +#define mmLB4_DC_LB_MEMORY_SPLIT 0x46C3 +#define mmLB5_DC_LB_MEMORY_SPLIT 0x49C3 +#define mmDC_LB_MEM_SIZE 0x1AC4 +#define mmLB0_DC_LB_MEM_SIZE 0x1AC4 +#define mmLB1_DC_LB_MEM_SIZE 0x1DC4 +#define mmLB2_DC_LB_MEM_SIZE 0x40C4 +#define mmLB3_DC_LB_MEM_SIZE 0x43C4 +#define mmLB4_DC_LB_MEM_SIZE 0x46C4 +#define mmLB5_DC_LB_MEM_SIZE 0x49C4 #define mmPRIORITY_A_CNT 0x1AC6 +#define mmLB0_PRIORITY_A_CNT 0x1AC6 +#define mmLB1_PRIORITY_A_CNT 0x1DC6 +#define mmLB2_PRIORITY_A_CNT 0x40C6 +#define mmLB3_PRIORITY_A_CNT 0x43C6 +#define mmLB4_PRIORITY_A_CNT 0x46C6 +#define mmLB5_PRIORITY_A_CNT 0x49C6 #define mmPRIORITY_B_CNT 0x1AC7 +#define mmLB0_PRIORITY_B_CNT 0x1AC7 +#define mmLB1_PRIORITY_B_CNT 0x1DC7 +#define mmLB2_PRIORITY_B_CNT 0x40C7 +#define mmLB3_PRIORITY_B_CNT 0x43C7 +#define mmLB4_PRIORITY_B_CNT 0x46C7 +#define mmLB5_PRIORITY_B_CNT 0x49C7 #define mmDPG_PIPE_ARBITRATION_CONTROL3 0x1B32 +#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL3 0x1B32 +#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL3 0x1E32 +#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL3 0x4132 +#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL3 0x4432 +#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL3 0x4732 +#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL3 0x4A32 #define mmINT_MASK 0x1AD0 +#define mmLB0_INT_MASK 0x1AD0 +#define mmLB1_INT_MASK 0x1DD0 +#define mmLB2_INT_MASK 0x40D0 +#define mmLB3_INT_MASK 0x43D0 +#define mmLB4_INT_MASK 0x46D0 +#define mmLB5_INT_MASK 0x49D0 #define mmVLINE_STATUS 0x1AEE +#define mmLB0_VLINE_STATUS 0x1AEE +#define mmLB1_VLINE_STATUS 0x1DEE +#define mmLB2_VLINE_STATUS 0x40EE +#define mmLB3_VLINE_STATUS 0x43EE +#define mmLB4_VLINE_STATUS 0x46EE +#define mmLB5_VLINE_STATUS 0x49EE #define mmVBLANK_STATUS 0x1AEF +#define mmLB0_VBLANK_STATUS 0x1AEF +#define mmLB1_VBLANK_STATUS 0x1DEF +#define mmLB2_VBLANK_STATUS 0x40EF +#define mmLB3_VBLANK_STATUS 0x43EF +#define mmLB4_VBLANK_STATUS 0x46EF +#define mmLB5_VBLANK_STATUS 0x49EF +#define mmSCL_HORZ_FILTER_INIT_RGB_LUMA 0x1B4C +#define mmSCL0_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x1B4C +#define mmSCL1_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x1E4C +#define mmSCL2_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x414C +#define mmSCL3_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x444C +#define mmSCL4_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x474C +#define mmSCL5_SCL_HORZ_FILTER_INIT_RGB_LUMA 0x4A4C + +#define mmSCL_HORZ_FILTER_INIT_CHROMA 0x1B4D +#define mmSCL0_SCL_HORZ_FILTER_INIT_CHROMA 0x1B4D +#define mmSCL1_SCL_HORZ_FILTER_INIT_CHROMA 0x1E4D +#define mmSCL2_SCL_HORZ_FILTER_INIT_CHROMA 0x414D +#define mmSCL3_SCL_HORZ_FILTER_INIT_CHROMA 0x444D +#define mmSCL4_SCL_HORZ_FILTER_INIT_CHROMA 0x474D +#define mmSCL5_SCL_HORZ_FILTER_INIT_CHROMA 0x4A4D #endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h index abe05bc807523..41c4a46ce3572 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h @@ -2076,6 +2076,8 @@ #define CRTC_CONTROL__CRTC_START_POINT_CNTL__SHIFT 0x0000000c #define CRTC_CONTROL__CRTC_SYNC_RESET_SEL_MASK 0x00000010L #define CRTC_CONTROL__CRTC_SYNC_RESET_SEL__SHIFT 0x00000004 +#define CRTC_CONTROL__CRTC_PREFETCH_EN_MASK 0x10000000L +#define CRTC_CONTROL__CRTC_PREFETCH_EN__SHIFT 0x0000001c #define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN_MASK 0x00000001L #define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN__SHIFT 0x00000000 #define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT_MASK 0x0000001eL @@ -6364,6 +6366,8 @@ #define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x00000000 #define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000L #define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x00000010 +#define DPG_PIPE_ARBITRATION_CONTROL3__URGENCY_WATERMARK_MASK_MASK 0x00030000L +#define DPG_PIPE_ARBITRATION_CONTROL3__URGENCY_WATERMARK_MASK__SHIFT 0x00000010 #define DPG_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x00000001L #define DPG_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x00000000 #define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x00000010L @@ -6384,6 +6388,8 @@ #define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x00000008 #define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x00000010L #define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x00000004 +#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK_MASK 0x00003000L +#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK__SHIFT 0x0000000c #define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff0000L #define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0x00000010 #define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x00000001L @@ -6406,6 +6412,8 @@ #define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x00000008 #define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x00000001L #define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x00000000 +#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK_MASK 0x00003000L +#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK__SHIFT 0x0000000c #define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000L #define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x00000010 #define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x00000010L @@ -7256,6 +7264,8 @@ #define GRPH_CONTROL__GRPH_FORMAT__SHIFT 0x00000008 #define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_MASK 0x000c0000L #define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT__SHIFT 0x00000012 +#define GRPH_CONTROL__GRPH_ARRAY_MODE_MASK 0x00f00000L +#define GRPH_CONTROL__GRPH_ARRAY_MODE__SHIFT 0x00000014 #define GRPH_CONTROL__GRPH_NUM_BANKS_MASK 0x0000000cL #define GRPH_CONTROL__GRPH_NUM_BANKS__SHIFT 0x00000002 #define GRPH_CONTROL__GRPH_PIPE_CONFIG_MASK 0x1f000000L @@ -9835,4 +9845,98 @@ #define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN_MASK 0x00000100L #define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008 +// DATA_FORMAT +#define DATA_FORMAT__INTERLEAVE_EN_MASK 0x00000001L +#define DATA_FORMAT__INTERLEAVE_EN__SHIFT 0x00000000 +#define DATA_FORMAT__RESET_REQ_AT_EOL_MASK 0x00000010L +#define DATA_FORMAT__RESET_REQ_AT_EOL__SHIFT 0x00000004 +#define DATA_FORMAT__PREFETCH_MASK 0x00001000L +#define DATA_FORMAT__PREFETCH__SHIFT 0x0000000c +#define DATA_FORMAT__SOF_READ_PT_MASK 0x001f0000L +#define DATA_FORMAT__SOF_READ_PT__SHIFT 0x00000010 +#define DATA_FORMAT__REQUEST_MODE_MASK 0x03000000L +#define DATA_FORMAT__REQUEST_MODE__SHIFT 0x00000018 +#define DATA_FORMAT__ALLOW_REQ_MODE_1_2_MASK 0x10000000L +#define DATA_FORMAT__ALLOW_REQ_MODE_1_2__SHIFT 0x0000001c + + +// DC_LB_MEMORY_SPLIT +#define DC_LB_MEMORY_SPLIT__LB_NUM_PARTITIONS_MASK 0x000f0000L +#define DC_LB_MEMORY_SPLIT__LB_NUM_PARTITIONS__SHIFT 0x00000010 +#define DC_LB_MEMORY_SPLIT__DC_LB_MEMORY_CONFIG_MASK 0x00300000L +#define DC_LB_MEMORY_SPLIT__DC_LB_MEMORY_CONFIG__SHIFT 0x00000014 + +// DC_LB_MEM_SIZE +#define DC_LB_MEM_SIZE__DC_LB_MEM_SIZE_MASK 0x000007ffL +#define DC_LB_MEM_SIZE__DC_LB_MEM_SIZE__SHIFT 0x00000000 + +// SCL_TAP_CONTROL +#define SCL_TAP_CONTROL__SCL_V_NUM_OF_TAPS_MASK 0x00000007L +#define SCL_TAP_CONTROL__SCL_V_NUM_OF_TAPS__SHIFT 0x00000000 +#define SCL_TAP_CONTROL__SCL_H_NUM_OF_TAPS_MASK 0x00000f00L +#define SCL_TAP_CONTROL__SCL_H_NUM_OF_TAPS__SHIFT 0x00000008 + +// INT_MASK +#define INT_MASK__VBLANK_INT_MASK 0x00000001L +#define INT_MASK__VBLANK_INT__SHIFT 0x00000000 +#define INT_MASK__VLINE_INT_MASK 0x00000010L +#define INT_MASK__VLINE_INT__SHIFT 0x00000004 + +// PRIORITY_A_CNT +#define PRIORITY_A_CNT__PRIORITY_MARK_A_MASK 0x00007fffL +#define PRIORITY_A_CNT__PRIORITY_MARK_A__SHIFT 0x00000000 +#define PRIORITY_A_CNT__PRIORITY_A_OFF_MASK 0x00010000L +#define PRIORITY_A_CNT__PRIORITY_A_OFF__SHIFT 0x00000010 +#define PRIORITY_A_CNT__PRIORITY_A_ALWAYS_ON_MASK 0x00100000L +#define PRIORITY_A_CNT__PRIORITY_A_ALWAYS_ON__SHIFT 0x00000014 +#define PRIORITY_A_CNT__PRIORITY_A_FORCE_MASK_MASK 0x01000000L +#define PRIORITY_A_CNT__PRIORITY_A_FORCE_MASK__SHIFT 0x00000018 + +// PRIORITY_B_CNT +#define PRIORITY_B_CNT__PRIORITY_MARK_B_MASK 0x00007fffL +#define PRIORITY_B_CNT__PRIORITY_MARK_B__SHIFT 0x00000000 +#define PRIORITY_B_CNT__PRIORITY_B_OFF_MASK 0x00010000L +#define PRIORITY_B_CNT__PRIORITY_B_OFF__SHIFT 0x00000010 +#define PRIORITY_B_CNT__PRIORITY_B_ALWAYS_ON_MASK 0x00100000L +#define PRIORITY_B_CNT__PRIORITY_B_ALWAYS_ON__SHIFT 0x00000014 +#define PRIORITY_B_CNT__PRIORITY_B_FORCE_MASK_MASK 0x01000000L +#define PRIORITY_B_CNT__PRIORITY_B_FORCE_MASK__SHIFT 0x00000018 + +// VLINE_STATUS +#define VLINE_STATUS__VLINE_OCCURRED_MASK 0x00000001L +#define VLINE_STATUS__VLINE_OCCURRED__SHIFT 0x00000000 +#define VLINE_STATUS__VLINE_ACK_MASK 0x00000010L +#define VLINE_STATUS__VLINE_ACK__SHIFT 0x00000004 +#define VLINE_STATUS__VLINE_STAT_MASK 0x00001000L +#define VLINE_STATUS__VLINE_STAT__SHIFT 0x0000000c +#define VLINE_STATUS__VLINE_INTERRUPT_MASK 0x00010000L +#define VLINE_STATUS__VLINE_INTERRUPT__SHIFT 0x00000010 +#define VLINE_STATUS__VLINE_INTERRUPT_TYPE_MASK 0x00020000L +#define VLINE_STATUS__VLINE_INTERRUPT_TYPE__SHIFT 0x00000011 + +// VBLANK_STATUS +#define VBLANK_STATUS__VBLANK_OCCURRED_MASK 0x00000001L +#define VBLANK_STATUS__VBLANK_OCCURRED__SHIFT 0x00000000 +#define VBLANK_STATUS__VBLANK_ACK_MASK 0x00000010L +#define VBLANK_STATUS__VBLANK_ACK__SHIFT 0x00000004 +#define VBLANK_STATUS__VBLANK_STAT_MASK 0x00001000L +#define VBLANK_STATUS__VBLANK_STAT__SHIFT 0x0000000c +#define VBLANK_STATUS__VBLANK_INTERRUPT_MASK 0x00010000L +#define VBLANK_STATUS__VBLANK_INTERRUPT__SHIFT 0x00000010 +#define VBLANK_STATUS__VBLANK_INTERRUPT_TYPE_MASK 0x00020000L +#define VBLANK_STATUS__VBLANK_INTERRUPT_TYPE__SHIFT 0x00000011 + +// SCL_HORZ_FILTER_INIT_RGB_LUMA +#define SCL_HORZ_FILTER_INIT_RGB_LUMA__SCL_H_INIT_FRAC_RGB_Y_MASK 0x0000ffffL +#define SCL_HORZ_FILTER_INIT_RGB_LUMA__SCL_H_INIT_FRAC_RGB_Y__SHIFT 0x00000000 +#define SCL_HORZ_FILTER_INIT_RGB_LUMA__SCL_H_INIT_INT_RGB_Y_MASK 0x000f0000L +#define SCL_HORZ_FILTER_INIT_RGB_LUMA__SCL_H_INIT_INT_RGB_Y__SHIFT 0x00000010 + +// SCL_HORZ_FILTER_INIT_CHROMA +#define SCL_HORZ_FILTER_INIT_CHROMA__SCL_H_INIT_FRAC_CBCR_MASK 0x0000ffffL +#define SCL_HORZ_FILTER_INIT_CHROMA__SCL_H_INIT_FRAC_CBCR__SHIFT 0x00000000 +#define SCL_HORZ_FILTER_INIT_CHROMA__SCL_H_INIT_INT_CBCR_MASK 0x00070000L +#define SCL_HORZ_FILTER_INIT_CHROMA__SCL_H_INIT_INT_CBCR__SHIFT 0x00000010 + + #endif -- GitLab From f233c09842bc91a8f7f5dfadc6de77f52273befc Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sat, 11 Jul 2020 21:28:48 +0200 Subject: [PATCH 0072/1494] drm/amd/display: add asics info for SI parts [Why] Asic info for SI parts need to be preliminarly added [How] Asics info retrieved from si_id.h in https://github.com/GPUOpen-Tools/CodeXL Tree path: ./CodeXL/Components/ShaderAnalyzer/AMDTBackEnd/Include/Common/asic_reg/si_id.h Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> --- .../gpu/drm/amd/display/include/dal_asic_id.h | 40 +++++++++++++++++++ .../gpu/drm/amd/display/include/dal_types.h | 3 ++ 2 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index abeb58d544b11..b267987aed068 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -30,6 +30,34 @@ * ASIC internal revision ID */ +/* DCE60 (based on si_id.h in GPUOpen-Tools CodeXL) */ +#define SI_TAHITI_P_A0 0x01 +#define SI_TAHITI_P_B0 0x05 +#define SI_TAHITI_P_B1 0x06 +#define SI_PITCAIRN_PM_A0 0x14 +#define SI_PITCAIRN_PM_A1 0x15 +#define SI_CAPEVERDE_M_A0 0x28 +#define SI_CAPEVERDE_M_A1 0x29 +#define SI_OLAND_M_A0 0x3C +#define SI_HAINAN_V_A0 0x46 + +#define SI_UNKNOWN 0xFF + +#define ASIC_REV_IS_TAHITI_P(rev) \ + ((rev >= SI_TAHITI_P_A0) && (rev < SI_PITCAIRN_PM_A0)) + +#define ASIC_REV_IS_PITCAIRN_PM(rev) \ + ((rev >= SI_PITCAIRN_PM_A0) && (rev < SI_CAPEVERDE_M_A0)) + +#define ASIC_REV_IS_CAPEVERDE_M(rev) \ + ((rev >= SI_CAPEVERDE_M_A0) && (rev < SI_OLAND_M_A0)) + +#define ASIC_REV_IS_OLAND_M(rev) \ + ((rev >= SI_OLAND_M_A0) && (rev < SI_HAINAN_V_A0)) + +#define ASIC_REV_IS_HAINAN_V(rev) \ + ((rev >= SI_HAINAN_V_A0) && (rev < SI_UNKNOWN)) + /* DCE80 (based on ci_id.h in Perforce) */ #define CI_BONAIRE_M_A0 0x14 #define CI_BONAIRE_M_A1 0x15 @@ -181,6 +209,17 @@ enum { /* * ASIC chip ID */ + +/* DCE60 */ +#define DEVICE_ID_SI_TAHITI_P_6780 0x6780 +#define DEVICE_ID_SI_PITCAIRN_PM_6800 0x6800 +#define DEVICE_ID_SI_PITCAIRN_PM_6808 0x6808 +#define DEVICE_ID_SI_CAPEVERDE_M_6820 0x6820 +#define DEVICE_ID_SI_CAPEVERDE_M_6828 0x6828 +#define DEVICE_ID_SI_OLAND_M_6600 0x6600 +#define DEVICE_ID_SI_OLAND_M_6608 0x6608 +#define DEVICE_ID_SI_HAINAN_V_6660 0x6660 + /* DCE80 */ #define DEVICE_ID_KALINDI_9834 0x9834 #define DEVICE_ID_TEMASH_9839 0x9839 @@ -190,6 +229,7 @@ enum { #define DEVICE_ID_RENOIR_1636 0x1636 /* Asic Family IDs for different asic family. */ +#define FAMILY_SI 110 /* Southern Islands: Tahiti (P), Pitcairn (PM), Cape Verde (M), Oland (M), Hainan (V) */ #define FAMILY_CI 120 /* Sea Islands: Hawaii (P), Bonaire (M) */ #define FAMILY_KV 125 /* Fusion => Kaveri: Spectre, Spooky; Kabini: Kalindi */ #define FAMILY_VI 130 /* Volcanic Islands: Iceland (V), Tonga (M) */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index b67c9fa6b9cd4..8aaa3af692021 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -34,6 +34,9 @@ struct dc_bios; enum dce_version { DCE_VERSION_UNKNOWN = (-1), + DCE_VERSION_6_0, + DCE_VERSION_6_1, + DCE_VERSION_6_4, DCE_VERSION_8_0, DCE_VERSION_8_1, DCE_VERSION_8_3, -- GitLab From 7c15fd86aaec3e602e140c242369df2baddc865e Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sat, 11 Jul 2020 21:43:25 +0200 Subject: [PATCH 0073/1494] drm/amd/display: dc/dce: add initial DCE6 support (v10) [Why] DCE6 chipsets have a lot in common with DCE8, let's start from this [How] DCE6 targets are added replicating existing DCE8 implementation. NOTE: dce_8_0_{d,sh_mask}.h headers used instead of dce_6_0_{d,sh_mask}.h initial build prototype due to missing DCE6 macros/registers/masks DCE6 specific macros/registers/masks will be added with later commits (v2b) removed dce_version cases in dc/dce/dce_clock_source.c and updated dce60 due to following kernel 5.0 commits: 24f7dd7 ("drm/amd/display: move pplib/smu notification to dccg block") 9566b67 ("drm/amd/display: remove safe_to_lower flag from dc, use 2 functions instead") 4244381 ("drm/amd/display: clean up base dccg struct") 4c5e8b5 ("drm/amd/display: split dccg clock manager into asic folders") 84e7fc0 ("drm/amd/display: rename dccg to clk_mgr") 77f6916 ("drm/amd/display: Remove duplicate header") 9f7ddbe ("drm/amd/display: fix optimize_bandwidth func pointer for dce80") 4ece61a ("drm/amd/display: set clocks to 0 on suspend on dce80") (v3b) updated dce60 due to following kernel 5.1 commits: 380604e ("drm/amd/display: Use 100 Hz precision for pipe pixel clocks") 32e6136 ("drm/amd/display: Fix 64-bit division for 32-bit builds") 1877ccf ("drm/amd/display: Change from aux_engine to dce_aux") c69dffa ("drm/amd/display: fix eDP fast bootup for pre-raven asic") (v4b) updated dce60 due to following kernel 5.2 commits: e5c4197 ("drm/amd/display: Add plane capabilities to dc_caps") 813d20d ("drm/amd/display: Fix multi-thread writing to 1 state") ea36ad3 ("drm/amd/display: expand plane caps to include fp16 and scaling capability") afcd526 ("drm/amd/display: Add fast_validate parameter") (v5b) updated dce60 due to following kernel 5.3 commits: e7e10c4 ("drm/amd/display: stop external access to internal optc sync params") 78cc70b ("drm/amd/display: Engine-specific encoder allocation") dc88b4a ("drm/amd/display: make clk mgr soc specific") 4fc4dca ("drm/amd: drop use of drmp.h in os_types.h") (v6b) updated dce60 due to following kernel 5.4 commits: 54a9bcb ("drm/amd/display: Fix a typo - dce_aduio_mask --> dce_audio_mask") 9adc805 ("drm/amd/display: make firmware info only load once during dc_bios create") (v7b) updated dce60 due to following kernel 5.5 commits: cabe144 ("drm/amd/display: memory leak") 8276dd8 ("drm/amd/display: update register field access mechanism") f6040a4 ("drm/amd/display: configurable aux timeout support") bf7f5ac ("drm/amd/display: map TRANSMITTER_UNIPHY_x to LINK_REGS_x") (v8b) updated dce60 due to following kernel 5.6 commits: d9e3267 ("drm/amd/display: cleanup of construct and destruct funcs") f42ea55 ("drm/amd/display: add separate of private hwss functions") (v9b) updated dce60 due to following kernel 5.8 commits: bba8289 ("drm/amd/display: code clean up in dce80_hw_sequencer.c") 904fb6e ("drm/amd/display: move panel power seq to new panel struct") d4caa72 ("drm/amd/display: change from panel to panel cntl") (v10) Fix up PLL handling for DCE6: DCE6.0 supports 2 PLLs. DCE6.1 supports 3 PLLs. (Alex) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/Makefile | 4 + drivers/gpu/drm/amd/display/dc/dce60/Makefile | 34 + .../amd/display/dc/dce60/dce60_hw_sequencer.c | 54 + .../amd/display/dc/dce60/dce60_hw_sequencer.h | 37 + .../drm/amd/display/dc/dce60/dce60_resource.c | 1532 +++++++++++++++++ .../drm/amd/display/dc/dce60/dce60_resource.h | 47 + .../display/dc/dce60/dce60_timing_generator.c | 247 +++ .../display/dc/dce60/dce60_timing_generator.h | 39 + 8 files changed, 1994 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c create mode 100644 drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index e0f4f1be16182..047b1e2dd8f11 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -43,6 +43,10 @@ DC_LIBS += dce110 DC_LIBS += dce100 DC_LIBS += dce80 +ifdef CONFIG_DRM_AMD_DC_SI +DC_LIBS += dce60 +endif + ifdef CONFIG_DRM_AMD_DC_HDCP DC_LIBS += hdcp endif diff --git a/drivers/gpu/drm/amd/display/dc/dce60/Makefile b/drivers/gpu/drm/amd/display/dc/dce60/Makefile new file mode 100644 index 0000000000000..7036c3bd0f871 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/Makefile @@ -0,0 +1,34 @@ +# +# Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'controller' sub-component of DAL. +# It provides the control and status of HW CRTC block. + +DCE60 = dce60_timing_generator.o dce60_hw_sequencer.o \ + dce60_resource.o + +AMD_DAL_DCE60 = $(addprefix $(AMDDALPATH)/dc/dce60/,$(DCE60)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCE60) + + + diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c new file mode 100644 index 0000000000000..e30e3510ec4a3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "dc.h" +#include "core_types.h" +#include "dce60_hw_sequencer.h" + +#include "dce/dce_hwseq.h" +#include "dce110/dce110_hw_sequencer.h" +#include "dce100/dce100_hw_sequencer.h" + +/* include DCE8 register header files */ +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + +/******************************************************************************* + * Private definitions + ******************************************************************************/ + +/***************************PIPE_CONTROL***********************************/ + +void dce60_hw_sequencer_construct(struct dc *dc) +{ + dce110_hw_sequencer_construct(dc); + + dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; + dc->hwss.pipe_control_lock = dce_pipe_control_lock; + dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; + dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h new file mode 100644 index 0000000000000..f3b2d8b60d5b7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_HWSS_DCE60_H__ +#define __DC_HWSS_DCE60_H__ + +#include "core_types.h" +#include "hw_sequencer_private.h" + +struct dc; + +void dce60_hw_sequencer_construct(struct dc *dc); + +#endif /* __DC_HWSS_DCE60_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c new file mode 100644 index 0000000000000..18d535c2cc28f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c @@ -0,0 +1,1532 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include <linux/slab.h> + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "dm_services.h" + +#include "link_encoder.h" +#include "stream_encoder.h" + +#include "resource.h" +#include "include/irq_service_interface.h" +#include "irq/dce60/irq_service_dce60.h" +#include "dce110/dce110_timing_generator.h" +#include "dce110/dce110_resource.h" +#include "dce60/dce60_timing_generator.h" +#include "dce/dce_mem_input.h" +#include "dce/dce_link_encoder.h" +#include "dce/dce_stream_encoder.h" +#include "dce/dce_ipp.h" +#include "dce/dce_transform.h" +#include "dce/dce_opp.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_audio.h" +#include "dce/dce_hwseq.h" +#include "dce60/dce60_hw_sequencer.h" +#include "dce100/dce100_resource.h" +#include "dce/dce_panel_cntl.h" + +#include "reg_helper.h" + +#include "dce/dce_dmcu.h" +#include "dce/dce_aux.h" +#include "dce/dce_abm.h" +#include "dce/dce_i2c.h" +/* TODO remove this include */ + +#ifndef mmMC_HUB_RDREQ_DMIF_LIMIT +#include "gmc/gmc_6_0_d.h" +#include "gmc/gmc_6_0_sh_mask.h" +#endif + +#ifndef mmDP_DPHY_INTERNAL_CTRL +#define mmDP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE +#define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE +#define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE +#define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE +#define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE +#define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE +#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE +#endif + + +#ifndef mmBIOS_SCRATCH_2 + #define mmBIOS_SCRATCH_2 0x05CB + #define mmBIOS_SCRATCH_3 0x05CC + #define mmBIOS_SCRATCH_6 0x05CF +#endif + +#ifndef mmDP_DPHY_FAST_TRAINING + #define mmDP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE + #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE + #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE + #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE + #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE + #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE + #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE +#endif + + +#ifndef mmHPD_DC_HPD_CONTROL + #define mmHPD_DC_HPD_CONTROL 0x189A + #define mmHPD0_DC_HPD_CONTROL 0x189A + #define mmHPD1_DC_HPD_CONTROL 0x18A2 + #define mmHPD2_DC_HPD_CONTROL 0x18AA + #define mmHPD3_DC_HPD_CONTROL 0x18B2 + #define mmHPD4_DC_HPD_CONTROL 0x18BA + #define mmHPD5_DC_HPD_CONTROL 0x18C2 +#endif + +#define DCE11_DIG_FE_CNTL 0x4a00 +#define DCE11_DIG_BE_CNTL 0x4a47 +#define DCE11_DP_SEC 0x4ac3 + +static const struct dce110_timing_generator_offsets dce60_tg_offsets[] = { + { + .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + }, + { + .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), + .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), + .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL + - mmDPG_WATERMARK_MASK_CONTROL), + } +}; + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +/* set register offset with instance */ +#define SRI(reg_name, block, id)\ + .reg_name = mm ## block ## id ## _ ## reg_name + +#define ipp_regs(id)\ +[id] = {\ + IPP_COMMON_REG_LIST_DCE_BASE(id)\ +} + +static const struct dce_ipp_registers ipp_regs[] = { + ipp_regs(0), + ipp_regs(1), + ipp_regs(2), + ipp_regs(3), + ipp_regs(4), + ipp_regs(5) +}; + +static const struct dce_ipp_shift ipp_shift = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_ipp_mask ipp_mask = { + IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +#define transform_regs(id)\ +[id] = {\ + XFM_COMMON_REG_LIST_DCE80(id)\ +} + +static const struct dce_transform_registers xfm_regs[] = { + transform_regs(0), + transform_regs(1), + transform_regs(2), + transform_regs(3), + transform_regs(4), + transform_regs(5) +}; + +static const struct dce_transform_shift xfm_shift = { + XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) +}; + +static const struct dce_transform_mask xfm_mask = { + XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) +}; + +#define aux_regs(id)\ +[id] = {\ + AUX_REG_LIST(id)\ +} + +static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1), + aux_regs(2), + aux_regs(3), + aux_regs(4), + aux_regs(5) +}; + +#define hpd_regs(id)\ +[id] = {\ + HPD_REG_LIST(id)\ +} + +static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5) +}; + +#define link_regs(id)\ +[id] = {\ + LE_DCE80_REG_LIST(id)\ +} + +static const struct dce110_link_enc_registers link_enc_regs[] = { + link_regs(0), + link_regs(1), + link_regs(2), + link_regs(3), + link_regs(4), + link_regs(5), + link_regs(6), +}; + +#define stream_enc_regs(id)\ +[id] = {\ + SE_COMMON_REG_LIST_DCE_BASE(id),\ + .AFMT_CNTL = 0,\ +} + +static const struct dce110_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1), + stream_enc_regs(2), + stream_enc_regs(3), + stream_enc_regs(4), + stream_enc_regs(5), + stream_enc_regs(6) +}; + +static const struct dce_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT) +}; + +static const struct dce_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK) +}; + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCE_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +#define opp_regs(id)\ +[id] = {\ + OPP_DCE_80_REG_LIST(id),\ +} + +static const struct dce_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1), + opp_regs(2), + opp_regs(3), + opp_regs(4), + opp_regs(5) +}; + +static const struct dce_opp_shift opp_shift = { + OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) +}; + +static const struct dce_opp_mask opp_mask = { + OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCE10_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCE10_AUX_MASK_SH_LIST(_MASK) +}; + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST(id), \ + .AUX_RESET_MASK = 0 \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1), + aux_engine_regs(2), + aux_engine_regs(3), + aux_engine_regs(4), + aux_engine_regs(5) +}; + +#define audio_regs(id)\ +[id] = {\ + AUD_COMMON_REG_LIST(id)\ +} + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6), +}; + +static const struct dce_audio_shift audio_shift = { + AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +#define clk_src_regs(id)\ +[id] = {\ + CS_COMMON_REG_LIST_DCE_80(id),\ +} + + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0), + clk_src_regs(1), + clk_src_regs(2) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +static const struct bios_registers bios_regs = { + .BIOS_SCRATCH_3 = mmBIOS_SCRATCH_3, + .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6 +}; + +static const struct resource_caps res_cap = { + .num_timing_generator = 6, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 2, + .num_ddc = 6, +}; + +static const struct resource_caps res_cap_61 = { + .num_timing_generator = 4, + .num_audio = 6, + .num_stream_encoder = 6, + .num_pll = 3, + .num_ddc = 6, +}; + +static const struct resource_caps res_cap_64 = { + .num_timing_generator = 2, + .num_audio = 2, + .num_stream_encoder = 2, + .num_pll = 2, + .num_ddc = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCE_RGB, + + .pixel_format_support = { + .argb8888 = true, + .nv12 = false, + .fp16 = false + }, + + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 1, + .fp16 = 1 + }, + + .max_downscale_factor = { + .argb8888 = 250, + .nv12 = 1, + .fp16 = 1 + } +}; + +static const struct dce_dmcu_registers dmcu_regs = { + DMCU_DCE80_REG_LIST() +}; + +static const struct dce_dmcu_shift dmcu_shift = { + DMCU_MASK_SH_LIST_DCE80(__SHIFT) +}; + +static const struct dce_dmcu_mask dmcu_mask = { + DMCU_MASK_SH_LIST_DCE80(_MASK) +}; +static const struct dce_abm_registers abm_regs = { + ABM_DCE110_COMMON_REG_LIST() +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCE110(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCE110(_MASK) +}; + +#define CTX ctx +#define REG(reg) mm ## reg + +#ifndef mmCC_DC_HDMI_STRAPS +#define mmCC_DC_HDMI_STRAPS 0x1918 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40 +#define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700 +#define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8 +#endif + +static int map_transmitter_id_to_phy_instance( + enum transmitter transmitter) +{ + switch (transmitter) { + case TRANSMITTER_UNIPHY_A: + return 0; + break; + case TRANSMITTER_UNIPHY_B: + return 1; + break; + case TRANSMITTER_UNIPHY_C: + return 2; + break; + case TRANSMITTER_UNIPHY_D: + return 3; + break; + case TRANSMITTER_UNIPHY_E: + return 4; + break; + case TRANSMITTER_UNIPHY_F: + return 5; + break; + case TRANSMITTER_UNIPHY_G: + return 6; + break; + default: + ASSERT(0); + return 0; + } +} + +static void read_dce_straps( + struct dc_context *ctx, + struct resource_straps *straps) +{ + REG_GET_2(CC_DC_HDMI_STRAPS, + HDMI_DISABLE, &straps->hdmi_disable, + AUDIO_STREAM_NUMBER, &straps->audio_stream_number); + + REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio); +} + +static struct audio *create_audio( + struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, + &audio_regs[inst], &audio_shift, &audio_mask); +} + +static struct timing_generator *dce60_timing_generator_create( + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + struct dce110_timing_generator *tg110 = + kzalloc(sizeof(struct dce110_timing_generator), GFP_KERNEL); + + if (!tg110) + return NULL; + + dce60_timing_generator_construct(tg110, ctx, instance, offsets); + return &tg110->base; +} + +static struct output_pixel_processor *dce60_opp_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce110_opp *opp = + kzalloc(sizeof(struct dce110_opp), GFP_KERNEL); + + if (!opp) + return NULL; + + dce110_opp_construct(opp, + ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +struct dce_aux *dce60_aux_engine_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = + kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, + SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], + &aux_mask, + &aux_shift, + ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2), + i2c_inst_regs(3), + i2c_inst_regs(4), + i2c_inst_regs(5), + i2c_inst_regs(6), +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) +}; + +struct dce_i2c_hw *dce60_i2c_hw_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = + kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dce_i2c_hw_construct(dce_i2c_hw, ctx, inst, + &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +struct dce_i2c_sw *dce60_i2c_sw_create( + struct dc_context *ctx) +{ + struct dce_i2c_sw *dce_i2c_sw = + kzalloc(sizeof(struct dce_i2c_sw), GFP_KERNEL); + + if (!dce_i2c_sw) + return NULL; + + dce_i2c_sw_construct(dce_i2c_sw, ctx); + + return dce_i2c_sw; +} +static struct stream_encoder *dce60_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dce110_stream_encoder *enc110 = + kzalloc(sizeof(struct dce110_stream_encoder), GFP_KERNEL); + + if (!enc110) + return NULL; + + dce110_stream_encoder_construct(enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], + &se_shift, &se_mask); + return &enc110->base; +} + +#define SRII(reg_name, block, id)\ + .reg_name[id] = mm ## block ## id ## _ ## reg_name + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCE8_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCE8_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dce60_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce60_stream_encoder_create, + .create_hwseq = dce60_hwseq_create, +}; + +#define mi_inst_regs(id) { \ + MI_DCE8_REG_LIST(id), \ + .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ +} +static const struct dce_mem_input_registers mi_regs[] = { + mi_inst_regs(0), + mi_inst_regs(1), + mi_inst_regs(2), + mi_inst_regs(3), + mi_inst_regs(4), + mi_inst_regs(5), +}; + +static const struct dce_mem_input_shift mi_shifts = { + MI_DCE8_MASK_SH_LIST(__SHIFT), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT +}; + +static const struct dce_mem_input_mask mi_masks = { + MI_DCE8_MASK_SH_LIST(_MASK), + .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK +}; + +static struct mem_input *dce60_mem_input_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_mem_input *dce_mi = kzalloc(sizeof(struct dce_mem_input), + GFP_KERNEL); + + if (!dce_mi) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce_mi->wa.single_head_rdreq_dmif_limit = 2; + return &dce_mi->base; +} + +static void dce60_transform_destroy(struct transform **xfm) +{ + kfree(TO_DCE_TRANSFORM(*xfm)); + *xfm = NULL; +} + +static struct transform *dce60_transform_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dce_transform *transform = + kzalloc(sizeof(struct dce_transform), GFP_KERNEL); + + if (!transform) + return NULL; + + dce_transform_construct(transform, ctx, inst, + &xfm_regs[inst], &xfm_shift, &xfm_mask); + transform->prescaler_on = false; + return &transform->base; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 297000, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true +}; + +struct link_encoder *dce60_link_encoder_create( + const struct encoder_init_data *enc_init_data) +{ + struct dce110_link_encoder *enc110 = + kzalloc(sizeof(struct dce110_link_encoder), GFP_KERNEL); + int link_regs_id; + + if (!enc110) + return NULL; + + link_regs_id = + map_transmitter_id_to_phy_instance(enc_init_data->transmitter); + + dce110_link_encoder_construct(enc110, + enc_init_data, + &link_enc_feature, + &link_enc_regs[link_regs_id], + &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source]); + return &enc110->base; +} + +static struct panel_cntl *dce60_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = + kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, + init_data, + &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, + &panel_cntl_mask); + + return &panel_cntl->base; +} + +struct clock_source *dce60_clock_source_create( + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = + kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dce110_clk_src_construct(clk_src, ctx, bios, id, + regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + kfree(clk_src); + BREAK_TO_DEBUGGER(); + return NULL; +} + +void dce60_clock_source_destroy(struct clock_source **clk_src) +{ + kfree(TO_DCE110_CLK_SRC(*clk_src)); + *clk_src = NULL; +} + +static struct input_pixel_processor *dce60_ipp_create( + struct dc_context *ctx, uint32_t inst) +{ + struct dce_ipp *ipp = kzalloc(sizeof(struct dce_ipp), GFP_KERNEL); + + if (!ipp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dce_ipp_construct(ipp, ctx, inst, + &ipp_regs[inst], &ipp_shift, &ipp_mask); + return &ipp->base; +} + +static void dce60_resource_destruct(struct dce110_resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->base.pipe_count; i++) { + if (pool->base.opps[i] != NULL) + dce110_opp_destroy(&pool->base.opps[i]); + + if (pool->base.transforms[i] != NULL) + dce60_transform_destroy(&pool->base.transforms[i]); + + if (pool->base.ipps[i] != NULL) + dce_ipp_destroy(&pool->base.ipps[i]); + + if (pool->base.mis[i] != NULL) { + kfree(TO_DCE_MEM_INPUT(pool->base.mis[i])); + pool->base.mis[i] = NULL; + } + + if (pool->base.timing_generators[i] != NULL) { + kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i])); + pool->base.timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + if (pool->base.engines[i] != NULL) + dce110_engine_destroy(&pool->base.engines[i]); + if (pool->base.hw_i2cs[i] != NULL) { + kfree(pool->base.hw_i2cs[i]); + pool->base.hw_i2cs[i] = NULL; + } + if (pool->base.sw_i2cs[i] != NULL) { + kfree(pool->base.sw_i2cs[i]); + pool->base.sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->base.stream_enc_count; i++) { + if (pool->base.stream_enc[i] != NULL) + kfree(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i])); + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] != NULL) { + dce60_clock_source_destroy(&pool->base.clock_sources[i]); + } + } + + if (pool->base.abm != NULL) + dce_abm_destroy(&pool->base.abm); + + if (pool->base.dmcu != NULL) + dce_dmcu_destroy(&pool->base.dmcu); + + if (pool->base.dp_clock_source != NULL) + dce60_clock_source_destroy(&pool->base.dp_clock_source); + + for (i = 0; i < pool->base.audio_count; i++) { + if (pool->base.audios[i] != NULL) { + dce_aud_destroy(&pool->base.audios[i]); + } + } + + if (pool->base.irqs != NULL) { + dal_irq_service_destroy(&pool->base.irqs); + } +} + +bool dce60_validate_bandwidth( + struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + int i; + bool at_least_one_pipe = false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].stream) + at_least_one_pipe = true; + } + + if (at_least_one_pipe) { + /* TODO implement when needed but for now hardcode max value*/ + context->bw_ctx.bw.dce.dispclk_khz = 681000; + context->bw_ctx.bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ; + } else { + context->bw_ctx.bw.dce.dispclk_khz = 0; + context->bw_ctx.bw.dce.yclk_khz = 0; + } + + return true; +} + +static bool dce60_validate_surface_sets( + struct dc_state *context) +{ + int i; + + for (i = 0; i < context->stream_count; i++) { + if (context->stream_status[i].plane_count == 0) + continue; + + if (context->stream_status[i].plane_count > 1) + return false; + + if (context->stream_status[i].plane_states[0]->format + >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + return false; + } + + return true; +} + +enum dc_status dce60_validate_global( + struct dc *dc, + struct dc_state *context) +{ + if (!dce60_validate_surface_sets(context)) + return DC_FAIL_SURFACE_VALIDATE; + + return DC_OK; +} + +static void dce60_destroy_resource_pool(struct resource_pool **pool) +{ + struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool); + + dce60_resource_destruct(dce110_pool); + kfree(dce110_pool); + *pool = NULL; +} + +static const struct resource_funcs dce60_res_pool_funcs = { + .destroy = dce60_destroy_resource_pool, + .link_enc_create = dce60_link_encoder_create, + .panel_cntl_create = dce60_panel_cntl_create, + .validate_bandwidth = dce60_validate_bandwidth, + .validate_plane = dce100_validate_plane, + .add_stream_to_ctx = dce100_add_stream_to_ctx, + .validate_global = dce60_validate_global, + .find_first_free_match_stream_enc_for_link = dce100_find_first_free_match_stream_enc_for_link +}; + +static bool dce60_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap; + pool->base.funcs = &dce60_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap.num_timing_generator; + pool->base.timing_generator_count = res_cap.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; + dc->caps.dual_link_dvi = true; + dc->caps.extended_aux_timeout_support = false; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clk_src_count = 2; + + } else { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clk_src_count = 1; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce60_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce60_timing_generator_create( + ctx, i, &dce60_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce60_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce60_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce60_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce60_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce60_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce60_resource_destruct(pool); + return false; +} + +struct resource_pool *dce60_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce60_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce61_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_61; + pool->base.funcs = &dce60_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_61.num_timing_generator; + pool->base.timing_generator_count = res_cap_61.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[2] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 3; + + } else { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); + pool->base.clk_src_count = 2; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce60_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce60_timing_generator_create( + ctx, i, &dce60_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce60_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce60_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce60_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce60_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce60_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce60_resource_destruct(pool); + return false; +} + +struct resource_pool *dce61_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce61_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static bool dce64_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct dce110_resource_pool *pool) +{ + unsigned int i; + struct dc_context *ctx = dc->ctx; + struct dc_bios *bp; + + ctx->dc_bios->regs = &bios_regs; + + pool->base.res_cap = &res_cap_64; + pool->base.funcs = &dce60_res_pool_funcs; + + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->base.pipe_count = res_cap_64.num_timing_generator; + pool->base.timing_generator_count = res_cap_64.num_timing_generator; + dc->caps.max_downscale_ratio = 200; + dc->caps.i2c_speed_in_khz = 40; + dc->caps.max_cursor_size = 128; + dc->caps.is_apu = true; + + /************************************************* + * Create resources * + *************************************************/ + + bp = ctx->dc_bios; + + if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); + pool->base.clock_sources[1] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 2; + + } else { + pool->base.dp_clock_source = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); + + pool->base.clock_sources[0] = + dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); + pool->base.clk_src_count = 1; + } + + if (pool->base.dp_clock_source == NULL) { + dm_error("DC: failed to create dp clock source!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + for (i = 0; i < pool->base.clk_src_count; i++) { + if (pool->base.clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + } + + pool->base.dmcu = dce_dmcu_create(ctx, + &dmcu_regs, + &dmcu_shift, + &dmcu_mask); + if (pool->base.dmcu == NULL) { + dm_error("DC: failed to create dmcu!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + pool->base.abm = dce_abm_create(ctx, + &abm_regs, + &abm_shift, + &abm_mask); + if (pool->base.abm == NULL) { + dm_error("DC: failed to create abm!\n"); + BREAK_TO_DEBUGGER(); + goto res_create_fail; + } + + { + struct irq_service_init_data init_data; + init_data.ctx = dc->ctx; + pool->base.irqs = dal_irq_service_dce60_create(&init_data); + if (!pool->base.irqs) + goto res_create_fail; + } + + for (i = 0; i < pool->base.pipe_count; i++) { + pool->base.timing_generators[i] = dce60_timing_generator_create( + ctx, i, &dce60_tg_offsets[i]); + if (pool->base.timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto res_create_fail; + } + + pool->base.mis[i] = dce60_mem_input_create(ctx, i); + if (pool->base.mis[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create memory input!\n"); + goto res_create_fail; + } + + pool->base.ipps[i] = dce60_ipp_create(ctx, i); + if (pool->base.ipps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create input pixel processor!\n"); + goto res_create_fail; + } + + pool->base.transforms[i] = dce60_transform_create(ctx, i); + if (pool->base.transforms[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create transform!\n"); + goto res_create_fail; + } + + pool->base.opps[i] = dce60_opp_create(ctx, i); + if (pool->base.opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto res_create_fail; + } + } + + for (i = 0; i < pool->base.res_cap->num_ddc; i++) { + pool->base.engines[i] = dce60_aux_engine_create(ctx, i); + if (pool->base.engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create aux engine!!\n"); + goto res_create_fail; + } + pool->base.hw_i2cs[i] = dce60_i2c_hw_create(ctx, i); + if (pool->base.hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create i2c engine!!\n"); + goto res_create_fail; + } + pool->base.sw_i2cs[i] = dce60_i2c_sw_create(ctx); + if (pool->base.sw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error( + "DC:failed to create sw i2c!!\n"); + goto res_create_fail; + } + } + + dc->caps.max_planes = pool->base.pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->caps.disable_dp_clk_share = true; + + if (!resource_construct(num_virtual_links, dc, &pool->base, + &res_create_funcs)) + goto res_create_fail; + + /* Create hardware sequencer */ + dce60_hw_sequencer_construct(dc); + + return true; + +res_create_fail: + dce60_resource_destruct(pool); + return false; +} + +struct resource_pool *dce64_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc) +{ + struct dce110_resource_pool *pool = + kzalloc(sizeof(struct dce110_resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dce64_construct(num_virtual_links, dc, pool)) + return &pool->base; + + BREAK_TO_DEBUGGER(); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h new file mode 100644 index 0000000000000..5d653a76b0b05 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_RESOURCE_DCE60_H__ +#define __DC_RESOURCE_DCE60_H__ + +#include "core_types.h" + +struct dc; +struct resource_pool; + +struct resource_pool *dce60_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +struct resource_pool *dce61_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +struct resource_pool *dce64_create_resource_pool( + uint8_t num_virtual_links, + struct dc *dc); + +#endif /* __DC_RESOURCE_DCE60_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c new file mode 100644 index 0000000000000..eb9705e9d40a5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c @@ -0,0 +1,247 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* include DCE6 register header files */ +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + +#include "dc_types.h" + +#include "include/grph_object_id.h" +#include "include/logger_interface.h" +#include "../dce110/dce110_timing_generator.h" +#include "dce60_timing_generator.h" + +#include "timing_generator.h" + +enum black_color_format { + BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0, /* used as index in array */ + BLACK_COLOR_FORMAT_RGB_LIMITED, + BLACK_COLOR_FORMAT_YUV_TV, + BLACK_COLOR_FORMAT_YUV_CV, + BLACK_COLOR_FORMAT_YUV_SUPER_AA, + + BLACK_COLOR_FORMAT_COUNT +}; + +static const struct dce110_timing_generator_offsets reg_offsets[] = { +{ + .crtc = (mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP0_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP1_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP2_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP3_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP4_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +}, +{ + .crtc = (mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL - mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL), + .dcp = (mmDCP5_GRPH_CONTROL - mmDCP0_GRPH_CONTROL), +} +}; + +#define NUMBER_OF_FRAME_TO_WAIT_ON_TRIGGERED_RESET 10 + +#define MAX_H_TOTAL (CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1) +#define MAX_V_TOTAL (CRTC_V_TOTAL__CRTC_V_TOTAL_MASKhw + 1) + +#define CRTC_REG(reg) (reg + tg110->offsets.crtc) +#define DCP_REG(reg) (reg + tg110->offsets.dcp) +#define DMIF_REG(reg) (reg + tg110->offsets.dmif) + +static void program_pix_dur(struct timing_generator *tg, uint32_t pix_clk_100hz) +{ + uint64_t pix_dur; + uint32_t addr = mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 + + DCE110TG_FROM_TG(tg)->offsets.dmif; + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (pix_clk_100hz == 0) + return; + + pix_dur = div_u64(10000000000ull, pix_clk_100hz); + + set_reg_field_value( + value, + pix_dur, + DPG_PIPE_ARBITRATION_CONTROL1, + PIXEL_DURATION); + + dm_write_reg(tg->ctx, addr, value); +} + +static void program_timing(struct timing_generator *tg, + const struct dc_crtc_timing *timing, + int vready_offset, + int vstartup_start, + int vupdate_offset, + int vupdate_width, + const enum signal_type signal, + bool use_vbios) +{ + if (!use_vbios) + program_pix_dur(tg, timing->pix_clk_100hz); + + dce110_tg_program_timing(tg, timing, 0, 0, 0, 0, 0, use_vbios); +} + +static void dce60_timing_generator_enable_advanced_request( + struct timing_generator *tg, + bool enable, + const struct dc_crtc_timing *timing) +{ + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); + uint32_t value = dm_read_reg(tg->ctx, addr); + + if (enable) { + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } else { + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_LEGACY_REQUESTOR_EN); + } + + if ((timing->v_sync_width + timing->v_front_porch) <= 3) { + set_reg_field_value( + value, + 3, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 0, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } else { + set_reg_field_value( + value, + 4, + CRTC_START_LINE_CONTROL, + CRTC_ADVANCED_START_LINE_POSITION); + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PREFETCH_EN); + } + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_PROGRESSIVE_START_LINE_EARLY); + + set_reg_field_value( + value, + 1, + CRTC_START_LINE_CONTROL, + CRTC_INTERLACE_START_LINE_EARLY); + + dm_write_reg(tg->ctx, addr, value); +} + +static const struct timing_generator_funcs dce60_tg_funcs = { + .validate_timing = dce110_tg_validate_timing, + .program_timing = program_timing, + .enable_crtc = dce110_timing_generator_enable_crtc, + .disable_crtc = dce110_timing_generator_disable_crtc, + .is_counter_moving = dce110_timing_generator_is_counter_moving, + .get_position = dce110_timing_generator_get_position, + .get_frame_count = dce110_timing_generator_get_vblank_counter, + .get_scanoutpos = dce110_timing_generator_get_crtc_scanoutpos, + .set_early_control = dce110_timing_generator_set_early_control, + .wait_for_state = dce110_tg_wait_for_state, + .set_blank = dce110_tg_set_blank, + .is_blanked = dce110_tg_is_blanked, + .set_colors = dce110_tg_set_colors, + .set_overscan_blank_color = + dce110_timing_generator_set_overscan_color_black, + .set_blank_color = dce110_timing_generator_program_blank_color, + .disable_vga = dce110_timing_generator_disable_vga, + .did_triggered_reset_occur = + dce110_timing_generator_did_triggered_reset_occur, + .setup_global_swap_lock = + dce110_timing_generator_setup_global_swap_lock, + .enable_reset_trigger = dce110_timing_generator_enable_reset_trigger, + .disable_reset_trigger = dce110_timing_generator_disable_reset_trigger, + .tear_down_global_swap_lock = + dce110_timing_generator_tear_down_global_swap_lock, + .set_drr = dce110_timing_generator_set_drr, + .set_static_screen_control = + dce110_timing_generator_set_static_screen_control, + .set_test_pattern = dce110_timing_generator_set_test_pattern, + .arm_vert_intr = dce110_arm_vert_intr, + + /* DCE6.0 overrides */ + .enable_advanced_request = + dce60_timing_generator_enable_advanced_request, + .configure_crc = dce110_configure_crc, + .get_crc = dce110_get_crc, +}; + +void dce60_timing_generator_construct( + struct dce110_timing_generator *tg110, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets) +{ + tg110->controller_id = CONTROLLER_ID_D0 + instance; + tg110->base.inst = instance; + tg110->offsets = *offsets; + tg110->derived_offsets = reg_offsets[instance]; + + tg110->base.funcs = &dce60_tg_funcs; + + tg110->base.ctx = ctx; + tg110->base.bp = ctx->dc_bios; + + tg110->max_h_total = CRTC_H_TOTAL__CRTC_H_TOTAL_MASK + 1; + tg110->max_v_total = CRTC_V_TOTAL__CRTC_V_TOTAL_MASK + 1; + + tg110->min_h_blank = 56; + tg110->min_h_front_porch = 4; + tg110->min_h_back_porch = 4; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h new file mode 100644 index 0000000000000..81d831233cc5e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DC_TIMING_GENERATOR_DCE60_H__ +#define __DC_TIMING_GENERATOR_DCE60_H__ + +#include "timing_generator.h" +#include "../include/grph_object_id.h" + +/* DCE6.0 implementation inherits from DCE11.0 */ +void dce60_timing_generator_construct( + struct dce110_timing_generator *tg, + struct dc_context *ctx, + uint32_t instance, + const struct dce110_timing_generator_offsets *offsets); + +#endif /* __DC_TIMING_GENERATOR_DCE60_H__ */ -- GitLab From 683b59504d4ecec3251a23fdac7e8775385a18c5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sun, 26 May 2019 17:31:42 +0200 Subject: [PATCH 0074/1494] drm/amd/display: dc/core: add SI/DCE6 support (v2) [Why] resource_parse_asic_id() and dc_create_resource_pool() are missing SI/DCE6 cases [How] SI/DCE6 cases support added using existing DCE8 implementation as a reference (v2) updated due to following kernel 5.2 commit: d9673c9 ("drm/amd/display: Pass init_data into DCN resource creation") Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 7b5f90ebb133b..ca26714c800e6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -42,6 +42,9 @@ #include "virtual/virtual_stream_encoder.h" #include "dpcd_defs.h" +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/dce60_resource.h" +#endif #include "dce80/dce80_resource.h" #include "dce100/dce100_resource.h" #include "dce110/dce110_resource.h" @@ -63,6 +66,18 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) enum dce_version dc_version = DCE_VERSION_UNKNOWN; switch (asic_id.chip_family) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case FAMILY_SI: + if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || + ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || + ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) + dc_version = DCE_VERSION_6_0; + else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) + dc_version = DCE_VERSION_6_4; + else + dc_version = DCE_VERSION_6_1; + break; +#endif case FAMILY_CI: dc_version = DCE_VERSION_8_0; break; @@ -129,6 +144,20 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, struct resource_pool *res_pool = NULL; switch (dc_version) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case DCE_VERSION_6_0: + res_pool = dce60_create_resource_pool( + init_data->num_virtual_links, dc); + break; + case DCE_VERSION_6_1: + res_pool = dce61_create_resource_pool( + init_data->num_virtual_links, dc); + break; + case DCE_VERSION_6_4: + res_pool = dce64_create_resource_pool( + init_data->num_virtual_links, dc); + break; +#endif case DCE_VERSION_8_0: res_pool = dce80_create_resource_pool( init_data->num_virtual_links, dc); -- GitLab From c4a54f70a6afd1a91072ef06cb083221ff189cca Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 5 Oct 2018 22:53:25 +0200 Subject: [PATCH 0075/1494] drm/amd/display: dc/bios: add support for DCE6 [Why] command_table_helper.c requires changes for DCE6 support [How] DCE6 targets added replicating and adapting the existing DCE8 implementation. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 9 + .../display/dc/bios/command_table_helper.c | 8 + .../display/dc/bios/command_table_helper.h | 3 + .../display/dc/bios/command_table_helper2.c | 8 + .../display/dc/bios/command_table_helper2.h | 3 + .../bios/dce60/command_table_helper_dce60.c | 354 ++++++++++++++++++ .../bios/dce60/command_table_helper_dce60.h | 33 ++ 7 files changed, 418 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c create mode 100644 drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.h diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 239e86bbec5a1..ed6b5e9763f64 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/Makefile +++ b/drivers/gpu/drm/amd/display/dc/bios/Makefile @@ -31,6 +31,15 @@ AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS)) AMD_DISPLAY_FILES += $(AMD_DAL_BIOS) +############################################################################### +# DCE 6x +############################################################################### +# All DCE6.x are derived from DCE6.0, so 6.0 MUST be defined if ANY of +# DCE6.x is compiled. +ifdef CONFIG_DRM_AMD_DC_SI +AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce60/command_table_helper_dce60.o +endif + ############################################################################### # DCE 8x ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c index 253bbb1eea609..48b4ef03fc8f8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.c @@ -36,6 +36,14 @@ bool dal_bios_parser_init_cmd_tbl_helper( enum dce_version dce) { switch (dce) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case DCE_VERSION_6_0: + case DCE_VERSION_6_1: + case DCE_VERSION_6_4: + *h = dal_cmd_tbl_helper_dce60_get_table(); + return true; +#endif + case DCE_VERSION_8_0: case DCE_VERSION_8_1: case DCE_VERSION_8_3: diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h index 4c3789df253df..dfd30aaf40326 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper.h @@ -26,6 +26,9 @@ #ifndef __DAL_COMMAND_TABLE_HELPER_H__ #define __DAL_COMMAND_TABLE_HELPER_H__ +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/command_table_helper_dce60.h" +#endif #include "dce80/command_table_helper_dce80.h" #include "dce110/command_table_helper_dce110.h" #include "dce112/command_table_helper_dce112.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 21ff6b686f5f8..74c498b6774d1 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -37,6 +37,14 @@ bool dal_bios_parser_init_cmd_tbl_helper2( enum dce_version dce) { switch (dce) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case DCE_VERSION_6_0: + case DCE_VERSION_6_1: + case DCE_VERSION_6_4: + *h = dal_cmd_tbl_helper_dce60_get_table(); + return true; +#endif + case DCE_VERSION_8_0: case DCE_VERSION_8_1: case DCE_VERSION_8_3: diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h index 785fcb20a1b93..66e0a3e737681 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.h @@ -26,6 +26,9 @@ #ifndef __DAL_COMMAND_TABLE_HELPER2_H__ #define __DAL_COMMAND_TABLE_HELPER2_H__ +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/command_table_helper_dce60.h" +#endif #include "dce80/command_table_helper_dce80.h" #include "dce110/command_table_helper_dce110.h" #include "dce112/command_table_helper2_dce112.h" diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c new file mode 100644 index 0000000000000..710221b4f5c5e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c @@ -0,0 +1,354 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +#include "atom.h" + +#include "include/grph_object_id.h" +#include "include/grph_object_defs.h" +#include "include/bios_parser_types.h" + +#include "../command_table_helper.h" + +static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action) +{ + uint8_t atom_action = 0; + + switch (action) { + case ENCODER_CONTROL_ENABLE: + atom_action = ATOM_ENABLE; + break; + case ENCODER_CONTROL_DISABLE: + atom_action = ATOM_DISABLE; + break; + case ENCODER_CONTROL_SETUP: + atom_action = ATOM_ENCODER_CMD_SETUP; + break; + case ENCODER_CONTROL_INIT: + atom_action = ATOM_ENCODER_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */ + break; + } + + return atom_action; +} + +static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id) +{ + bool result = false; + + if (atom_engine_id != NULL) + switch (id) { + case ENGINE_ID_DIGA: + *atom_engine_id = ASIC_INT_DIG1_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGB: + *atom_engine_id = ASIC_INT_DIG2_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGC: + *atom_engine_id = ASIC_INT_DIG3_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGD: + *atom_engine_id = ASIC_INT_DIG4_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGE: + *atom_engine_id = ASIC_INT_DIG5_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGF: + *atom_engine_id = ASIC_INT_DIG6_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DIGG: + *atom_engine_id = ASIC_INT_DIG7_ENCODER_ID; + result = true; + break; + case ENGINE_ID_DACA: + *atom_engine_id = ASIC_INT_DAC1_ENCODER_ID; + result = true; + break; + default: + break; + } + + return result; +} + +static bool clock_source_id_to_atom( + enum clock_source_id id, + uint32_t *atom_pll_id) +{ + bool result = true; + + if (atom_pll_id != NULL) + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + *atom_pll_id = ATOM_PPLL0; + break; + case CLOCK_SOURCE_ID_PLL1: + *atom_pll_id = ATOM_PPLL1; + break; + case CLOCK_SOURCE_ID_PLL2: + *atom_pll_id = ATOM_PPLL2; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DFS: + *atom_pll_id = ATOM_EXT_PLL1; + break; + case CLOCK_SOURCE_ID_VCE: + /* for VCE encoding, + * we need to pass in ATOM_PPLL_INVALID + */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_DP_DTO: + /* When programming DP DTO PLL ID should be invalid */ + *atom_pll_id = ATOM_PPLL_INVALID; + break; + case CLOCK_SOURCE_ID_UNDEFINED: + BREAK_TO_DEBUGGER(); /* check when this will happen! */ + *atom_pll_id = ATOM_PPLL_INVALID; + result = false; + break; + default: + result = false; + break; + } + + return result; +} + +static uint8_t clock_source_id_to_atom_phy_clk_src_id( + enum clock_source_id id) +{ + uint8_t atom_phy_clk_src_id = 0; + + switch (id) { + case CLOCK_SOURCE_ID_PLL0: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL; + break; + case CLOCK_SOURCE_ID_PLL1: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + case CLOCK_SOURCE_ID_PLL2: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL; + break; + case CLOCK_SOURCE_ID_EXTERNAL: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT; + break; + default: + atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL; + break; + } + + return atom_phy_clk_src_id >> 2; +} + +static uint8_t signal_type_to_atom_dig_mode(enum signal_type s) +{ + uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + + switch (s) { + case SIGNAL_TYPE_DISPLAY_PORT: + case SIGNAL_TYPE_EDP: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP; + break; + case SIGNAL_TYPE_LVDS: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS; + break; + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + case SIGNAL_TYPE_HDMI_TYPE_A: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI; + break; + case SIGNAL_TYPE_DISPLAY_PORT_MST: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST; + break; + default: + atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI; + break; + } + + return atom_dig_mode; +} + +static uint8_t hpd_sel_to_atom(enum hpd_source_id id) +{ + uint8_t atom_hpd_sel = 0; + + switch (id) { + case HPD_SOURCEID1: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL; + break; + case HPD_SOURCEID2: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL; + break; + case HPD_SOURCEID3: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL; + break; + case HPD_SOURCEID4: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL; + break; + case HPD_SOURCEID5: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL; + break; + case HPD_SOURCEID6: + atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL; + break; + case HPD_SOURCEID_UNKNOWN: + default: + atom_hpd_sel = 0; + break; + } + return atom_hpd_sel >> 4; +} + +static uint8_t dig_encoder_sel_to_atom(enum engine_id id) +{ + uint8_t atom_dig_encoder_sel = 0; + + switch (id) { + case ENGINE_ID_DIGA: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + case ENGINE_ID_DIGB: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL; + break; + case ENGINE_ID_DIGC: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL; + break; + case ENGINE_ID_DIGD: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL; + break; + case ENGINE_ID_DIGE: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL; + break; + case ENGINE_ID_DIGF: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL; + break; + case ENGINE_ID_DIGG: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL; + break; + default: + atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL; + break; + } + + return atom_dig_encoder_sel; +} + +static uint8_t phy_id_to_atom(enum transmitter t) +{ + uint8_t atom_phy_id; + + switch (t) { + case TRANSMITTER_UNIPHY_A: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + case TRANSMITTER_UNIPHY_B: + atom_phy_id = ATOM_PHY_ID_UNIPHYB; + break; + case TRANSMITTER_UNIPHY_C: + atom_phy_id = ATOM_PHY_ID_UNIPHYC; + break; + case TRANSMITTER_UNIPHY_D: + atom_phy_id = ATOM_PHY_ID_UNIPHYD; + break; + case TRANSMITTER_UNIPHY_E: + atom_phy_id = ATOM_PHY_ID_UNIPHYE; + break; + case TRANSMITTER_UNIPHY_F: + atom_phy_id = ATOM_PHY_ID_UNIPHYF; + break; + case TRANSMITTER_UNIPHY_G: + atom_phy_id = ATOM_PHY_ID_UNIPHYG; + break; + default: + atom_phy_id = ATOM_PHY_ID_UNIPHYA; + break; + } + return atom_phy_id; +} + +static uint8_t disp_power_gating_action_to_atom( + enum bp_pipe_control_action action) +{ + uint8_t atom_pipe_action = 0; + + switch (action) { + case ASIC_PIPE_DISABLE: + atom_pipe_action = ATOM_DISABLE; + break; + case ASIC_PIPE_ENABLE: + atom_pipe_action = ATOM_ENABLE; + break; + case ASIC_PIPE_INIT: + atom_pipe_action = ATOM_INIT; + break; + default: + BREAK_TO_DEBUGGER(); /* Unhandle action in driver! */ + break; + } + + return atom_pipe_action; +} + +static const struct command_table_helper command_table_helper_funcs = { + .controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom, + .encoder_action_to_atom = encoder_action_to_atom, + .engine_bp_to_atom = engine_bp_to_atom, + .clock_source_id_to_atom = clock_source_id_to_atom, + .clock_source_id_to_atom_phy_clk_src_id = + clock_source_id_to_atom_phy_clk_src_id, + .signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode, + .hpd_sel_to_atom = hpd_sel_to_atom, + .dig_encoder_sel_to_atom = dig_encoder_sel_to_atom, + .phy_id_to_atom = phy_id_to_atom, + .disp_power_gating_action_to_atom = disp_power_gating_action_to_atom, + .assign_control_parameter = + dal_cmd_table_helper_assign_control_parameter, + .clock_source_id_to_ref_clk_src = + dal_cmd_table_helper_clock_source_id_to_ref_clk_src, + .transmitter_bp_to_atom = dal_cmd_table_helper_transmitter_bp_to_atom, + .encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom, + .encoder_mode_bp_to_atom = + dal_cmd_table_helper_encoder_mode_bp_to_atom, +}; + +const struct command_table_helper *dal_cmd_tbl_helper_dce60_get_table(void) +{ + return &command_table_helper_funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.h b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.h new file mode 100644 index 0000000000000..f733be553d5a7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_COMMAND_TABLE_HELPER_DCE60_H__ +#define __DAL_COMMAND_TABLE_HELPER_DCE60_H__ + +struct command_table_helper; + +const struct command_table_helper *dal_cmd_tbl_helper_dce60_get_table(void); + +#endif -- GitLab From b168930d68a95d7696773007b426a0f60a9c3fd7 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sun, 29 Sep 2019 18:41:38 +0200 Subject: [PATCH 0076/1494] drm/amd/display: dc/gpio: add support for DCE6 (v2) [Why] hw_factory.c requires changes for DCE6 support [How] DCE6 targets added replicating and adapting existing DCE8 implementation. (v2) changes due to following commit: 91db931 ("drm/amd/display: refactor gpio to allocate hw_container in constructor") Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 12 + .../display/dc/gpio/dce60/hw_factory_dce60.c | 175 ++++++++ .../display/dc/gpio/dce60/hw_factory_dce60.h | 32 ++ .../dc/gpio/dce60/hw_translate_dce60.c | 411 ++++++++++++++++++ .../dc/gpio/dce60/hw_translate_dce60.h | 32 ++ .../gpu/drm/amd/display/dc/gpio/hw_factory.c | 10 + .../drm/amd/display/dc/gpio/hw_translate.c | 10 + 7 files changed, 682 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.h create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.h diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 0f2f4508e5646..74c0943ed6441 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -30,6 +30,18 @@ AMD_DAL_GPIO = $(addprefix $(AMDDALPATH)/dc/gpio/,$(GPIO)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO) +############################################################################### +# DCE 6x +############################################################################### +# all DCE6.x are derived from DCE6.0 +ifdef CONFIG_DRM_AMD_DC_SI +GPIO_DCE60 = hw_translate_dce60.o hw_factory_dce60.o + +AMD_DAL_GPIO_DCE60 = $(addprefix $(AMDDALPATH)/dc/gpio/dce60/,$(GPIO_DCE60)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE60) +endif + ############################################################################### # DCE 8x ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.c b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.c new file mode 100644 index 0000000000000..cc69acd8ada7c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.c @@ -0,0 +1,175 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" +#include "include/gpio_types.h" +#include "../hw_factory.h" + +#include "hw_factory_dce60.h" + +#include "../hw_gpio.h" +#include "../hw_ddc.h" +#include "../hw_hpd.h" +#include "../hw_generic.h" + +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + + +#define REG(reg_name)\ + mm ## reg_name + +#include "reg_helper.h" +#include "../hpd_regs.h" + +#define HPD_REG_LIST_DCE6(id) \ + HPD_GPIO_REG_LIST(id), \ + .int_status = mmDC_HPD ## id ## _INT_STATUS,\ + .toggle_filt_cntl = mmDC_HPD ## id ## _TOGGLE_FILT_CNTL + +#define HPD_MASK_SH_LIST_DCE6(mask_sh) \ + .DC_HPD_SENSE_DELAYED = DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED ## mask_sh,\ + .DC_HPD_SENSE = DC_HPD1_INT_STATUS__DC_HPD1_SENSE ## mask_sh,\ + .DC_HPD_CONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY ## mask_sh,\ + .DC_HPD_DISCONNECT_INT_DELAY = DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY ## mask_sh + +#define hpd_regs(id) \ +{\ + HPD_REG_LIST_DCE6(id)\ +} + +static const struct hpd_registers hpd_regs[] = { + hpd_regs(1), + hpd_regs(2), + hpd_regs(3), + hpd_regs(4), + hpd_regs(5), + hpd_regs(6) +}; + +static const struct hpd_sh_mask hpd_shift = { + HPD_MASK_SH_LIST_DCE6(__SHIFT) +}; + +static const struct hpd_sh_mask hpd_mask = { + HPD_MASK_SH_LIST_DCE6(_MASK) +}; + +#include "../ddc_regs.h" + + /* set field name */ +#define SF_DDC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +static const struct ddc_registers ddc_data_regs[] = { + ddc_data_regs(1), + ddc_data_regs(2), + ddc_data_regs(3), + ddc_data_regs(4), + ddc_data_regs(5), + ddc_data_regs(6), + ddc_vga_data_regs, + ddc_i2c_data_regs +}; + +static const struct ddc_registers ddc_clk_regs[] = { + ddc_clk_regs(1), + ddc_clk_regs(2), + ddc_clk_regs(3), + ddc_clk_regs(4), + ddc_clk_regs(5), + ddc_clk_regs(6), + ddc_vga_clk_regs, + ddc_i2c_clk_regs +}; + +static const struct ddc_sh_mask ddc_shift = { + DDC_MASK_SH_LIST(__SHIFT) +}; + +static const struct ddc_sh_mask ddc_mask = { + DDC_MASK_SH_LIST(_MASK) +}; + +static void define_ddc_registers( + struct hw_gpio_pin *pin, + uint32_t en) +{ + struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin); + + switch (pin->id) { + case GPIO_ID_DDC_DATA: + ddc->regs = &ddc_data_regs[en]; + ddc->base.regs = &ddc_data_regs[en].gpio; + break; + case GPIO_ID_DDC_CLOCK: + ddc->regs = &ddc_clk_regs[en]; + ddc->base.regs = &ddc_clk_regs[en].gpio; + break; + default: + ASSERT_CRITICAL(false); + return; + } + + ddc->shifts = &ddc_shift; + ddc->masks = &ddc_mask; + +} + +static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin); + + hpd->regs = &hpd_regs[en]; + hpd->shifts = &hpd_shift; + hpd->masks = &hpd_mask; + hpd->base.regs = &hpd_regs[en].gpio; +} + +static const struct hw_factory_funcs funcs = { + .init_ddc_data = dal_hw_ddc_init, + .init_generic = NULL, + .init_hpd = dal_hw_hpd_init, + .get_ddc_pin = dal_hw_ddc_get_pin, + .get_hpd_pin = dal_hw_hpd_get_pin, + .get_generic_pin = NULL, + .define_hpd_registers = define_hpd_registers, + .define_ddc_registers = define_ddc_registers +}; + +void dal_hw_factory_dce60_init( + struct hw_factory *factory) +{ + factory->number_of_pins[GPIO_ID_DDC_DATA] = 8; + factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8; + factory->number_of_pins[GPIO_ID_GENERIC] = 7; + factory->number_of_pins[GPIO_ID_HPD] = 6; + factory->number_of_pins[GPIO_ID_GPIO_PAD] = 31; + factory->number_of_pins[GPIO_ID_VIP_PAD] = 0; + factory->number_of_pins[GPIO_ID_SYNC] = 2; + factory->number_of_pins[GPIO_ID_GSL] = 4; + + factory->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.h b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.h new file mode 100644 index 0000000000000..1fd54ff8979c1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_FACTORY_DCE60_H__ +#define __DAL_HW_FACTORY_DCE60_H__ + +void dal_hw_factory_dce60_init( + struct hw_factory *factory); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c new file mode 100644 index 0000000000000..255df31ec577c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c @@ -0,0 +1,411 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "dm_services.h" + +/* + * Pre-requisites: headers required by header of this unit + */ +#include "include/gpio_types.h" +#include "../hw_translate.h" + +#include "hw_translate_dce60.h" + +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" +#include "smu/smu_6_0_d.h" + +/* + * @brief + * Returns index of first bit (starting with LSB) which is set + */ +static uint32_t index_from_vector( + uint32_t vector) +{ + uint32_t result = 0; + uint32_t mask = 1; + + do { + if (vector == mask) + return result; + + ++result; + mask <<= 1; + } while (mask); + + BREAK_TO_DEBUGGER(); + + return GPIO_ENUM_UNKNOWN; +} + +static bool offset_to_id( + uint32_t offset, + uint32_t mask, + enum gpio_id *id, + uint32_t *en) +{ + switch (offset) { + /* GENERIC */ + case mmDC_GPIO_GENERIC_A: + *id = GPIO_ID_GENERIC; + switch (mask) { + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK: + *en = GPIO_GENERIC_A; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK: + *en = GPIO_GENERIC_B; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK: + *en = GPIO_GENERIC_C; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK: + *en = GPIO_GENERIC_D; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK: + *en = GPIO_GENERIC_E; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK: + *en = GPIO_GENERIC_F; + return true; + case DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK: + *en = GPIO_GENERIC_G; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* HPD */ + case mmDC_GPIO_HPD_A: + *id = GPIO_ID_HPD; + switch (mask) { + case DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK: + *en = GPIO_HPD_1; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK: + *en = GPIO_HPD_2; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK: + *en = GPIO_HPD_3; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK: + *en = GPIO_HPD_4; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK: + *en = GPIO_HPD_5; + return true; + case DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK: + *en = GPIO_HPD_6; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* SYNCA */ + case mmDC_GPIO_SYNCA_A: + *id = GPIO_ID_SYNC; + switch (mask) { + case DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK: + *en = GPIO_SYNC_HSYNC_A; + return true; + case DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK: + *en = GPIO_SYNC_VSYNC_A; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* mmDC_GPIO_GENLK_MASK */ + case mmDC_GPIO_GENLK_A: + *id = GPIO_ID_GSL; + switch (mask) { + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK: + *en = GPIO_GSL_GENLOCK_CLOCK; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK: + *en = GPIO_GSL_GENLOCK_VSYNC; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK: + *en = GPIO_GSL_SWAPLOCK_A; + return true; + case DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK: + *en = GPIO_GSL_SWAPLOCK_B; + return true; + default: + BREAK_TO_DEBUGGER(); + return false; + } + break; + /* GPIOPAD */ + case mmGPIOPAD_A: + *id = GPIO_ID_GPIO_PAD; + *en = index_from_vector(mask); + return (*en <= GPIO_GPIO_PAD_MAX); + /* DDC */ + /* we don't care about the GPIO_ID for DDC + * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK + * directly in the create method */ + case mmDC_GPIO_DDC1_A: + *en = GPIO_DDC_LINE_DDC1; + return true; + case mmDC_GPIO_DDC2_A: + *en = GPIO_DDC_LINE_DDC2; + return true; + case mmDC_GPIO_DDC3_A: + *en = GPIO_DDC_LINE_DDC3; + return true; + case mmDC_GPIO_DDC4_A: + *en = GPIO_DDC_LINE_DDC4; + return true; + case mmDC_GPIO_DDC5_A: + *en = GPIO_DDC_LINE_DDC5; + return true; + case mmDC_GPIO_DDC6_A: + *en = GPIO_DDC_LINE_DDC6; + return true; + case mmDC_GPIO_DDCVGA_A: + *en = GPIO_DDC_LINE_DDC_VGA; + return true; + /* GPIO_I2CPAD */ + case mmDC_GPIO_I2CPAD_A: + *en = GPIO_DDC_LINE_I2C_PAD; + return true; + /* Not implemented */ + case mmDC_GPIO_PWRSEQ_A: + case mmDC_GPIO_PAD_STRENGTH_1: + case mmDC_GPIO_PAD_STRENGTH_2: + case mmDC_GPIO_DEBUG: + return false; + /* UNEXPECTED */ + default: + BREAK_TO_DEBUGGER(); + return false; + } +} + +static bool id_to_offset( + enum gpio_id id, + uint32_t en, + struct gpio_pin_info *info) +{ + bool result = true; + + switch (id) { + case GPIO_ID_DDC_DATA: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_DDC_CLOCK: + info->mask = DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK; + switch (en) { + case GPIO_DDC_LINE_DDC1: + info->offset = mmDC_GPIO_DDC1_A; + break; + case GPIO_DDC_LINE_DDC2: + info->offset = mmDC_GPIO_DDC2_A; + break; + case GPIO_DDC_LINE_DDC3: + info->offset = mmDC_GPIO_DDC3_A; + break; + case GPIO_DDC_LINE_DDC4: + info->offset = mmDC_GPIO_DDC4_A; + break; + case GPIO_DDC_LINE_DDC5: + info->offset = mmDC_GPIO_DDC5_A; + break; + case GPIO_DDC_LINE_DDC6: + info->offset = mmDC_GPIO_DDC6_A; + break; + case GPIO_DDC_LINE_DDC_VGA: + info->offset = mmDC_GPIO_DDCVGA_A; + break; + case GPIO_DDC_LINE_I2C_PAD: + info->offset = mmDC_GPIO_I2CPAD_A; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GENERIC: + info->offset = mmDC_GPIO_GENERIC_A; + switch (en) { + case GPIO_GENERIC_A: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK; + break; + case GPIO_GENERIC_B: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK; + break; + case GPIO_GENERIC_C: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK; + break; + case GPIO_GENERIC_D: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK; + break; + case GPIO_GENERIC_E: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK; + break; + case GPIO_GENERIC_F: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK; + break; + case GPIO_GENERIC_G: + info->mask = DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_HPD: + info->offset = mmDC_GPIO_HPD_A; + switch (en) { + case GPIO_HPD_1: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; + break; + case GPIO_HPD_2: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK; + break; + case GPIO_HPD_3: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK; + break; + case GPIO_HPD_4: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK; + break; + case GPIO_HPD_5: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK; + break; + case GPIO_HPD_6: + info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_SYNC: + switch (en) { + case GPIO_SYNC_HSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK; + break; + case GPIO_SYNC_VSYNC_A: + info->offset = mmDC_GPIO_SYNCA_A; + info->mask = DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK; + break; + case GPIO_SYNC_HSYNC_B: + case GPIO_SYNC_VSYNC_B: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GSL: + switch (en) { + case GPIO_GSL_GENLOCK_CLOCK: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK; + break; + case GPIO_GSL_GENLOCK_VSYNC: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = + DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_A: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK; + break; + case GPIO_GSL_SWAPLOCK_B: + info->offset = mmDC_GPIO_GENLK_A; + info->mask = DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK; + break; + default: + BREAK_TO_DEBUGGER(); + result = false; + } + break; + case GPIO_ID_GPIO_PAD: + info->offset = mmGPIOPAD_A; + info->mask = (1 << en); + result = (info->mask <= GPIO_GPIO_PAD_MAX); + break; + case GPIO_ID_VIP_PAD: + default: + BREAK_TO_DEBUGGER(); + result = false; + } + + if (result) { + info->offset_y = info->offset + 2; + info->offset_en = info->offset + 1; + info->offset_mask = info->offset - 1; + + info->mask_y = info->mask; + info->mask_en = info->mask; + info->mask_mask = info->mask; + } + + return result; +} + +static const struct hw_translate_funcs funcs = { + .offset_to_id = offset_to_id, + .id_to_offset = id_to_offset, +}; + +void dal_hw_translate_dce60_init( + struct hw_translate *translate) +{ + translate->funcs = &funcs; +} diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.h b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.h new file mode 100644 index 0000000000000..1e811f35cec77 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_HW_TRANSLATE_DCE60_H__ +#define __DAL_HW_TRANSLATE_DCE60_H__ + +void dal_hw_translate_dce60_init( + struct hw_translate *tr); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index e5cfe28bc7bfc..6fc8a6e9dc156 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -42,6 +42,9 @@ * Post-requisites: headers required by this unit */ +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/hw_factory_dce60.h" +#endif #include "dce80/hw_factory_dce80.h" #include "dce110/hw_factory_dce110.h" #include "dce120/hw_factory_dce120.h" @@ -71,6 +74,13 @@ bool dal_hw_factory_init( } switch (dce_version) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case DCE_VERSION_6_0: + case DCE_VERSION_6_1: + case DCE_VERSION_6_4: + dal_hw_factory_dce60_init(factory); + return true; +#endif case DCE_VERSION_8_0: case DCE_VERSION_8_1: case DCE_VERSION_8_3: diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index efea7cb0f17c1..3a93c945e57d2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -40,6 +40,9 @@ * Post-requisites: headers required by this unit */ +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/hw_translate_dce60.h" +#endif #include "dce80/hw_translate_dce80.h" #include "dce110/hw_translate_dce110.h" #include "dce120/hw_translate_dce120.h" @@ -69,6 +72,13 @@ bool dal_hw_translate_init( } switch (dce_version) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case DCE_VERSION_6_0: + case DCE_VERSION_6_1: + case DCE_VERSION_6_4: + dal_hw_translate_dce60_init(translate); + return true; +#endif case DCE_VERSION_8_0: case DCE_VERSION_8_1: case DCE_VERSION_8_3: -- GitLab From 61bf32937bdd05fdf74292460d56936d63beaba5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sat, 8 Feb 2020 10:41:01 +0100 Subject: [PATCH 0077/1494] drm/amd/display: dc/irq: add support for DCE6 (v4) [Why] irq service requires changes for DCE6 support [How] (v1) DCE6 targets are added replicating existing DCE8 implementation. due to missing CRTC_VERTICAL_INTERRUPT0_CONTROL registers/masks, dce/dce_8_0_{d,sh_mask}.h used instead of dce/dce_6_0_{d,sh_mask}.h (v2) DCE6 headers used adding the necessary vblank irq registers (INT_MASK and VBLANK_STATUS) and vblank irq masks as implemented in amdgpu driver. Add vblank_irq_info_funcs_dce60 with .set and .ack as per commit b10d51f ("drm/amd/display: Add interrupt entries for VBLANK isr.") and use it in vblank_int_entry(reg_num) macro definition (v3) updated due to following kernel 5.3 commit: 4fc4dca ("drm/amd: drop use of drmp.h in os_types.h") (v4) updated due to following kernel 5.6 commit: d9e3267 ("drm/amd/display: cleanup of construct and destruct funcs") Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/irq/Makefile | 11 + .../display/dc/irq/dce60/irq_service_dce60.c | 395 ++++++++++++++++++ .../display/dc/irq/dce60/irq_service_dce60.h | 40 ++ .../gpu/drm/amd/display/dc/irq/irq_service.c | 3 + 4 files changed, 449 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.h diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 3352b79fb1cbc..405c253226077 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -30,6 +30,17 @@ AMD_DAL_IRQ = $(addprefix $(AMDDALPATH)/dc/irq/,$(IRQ)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ) +############################################################################### +# DCE 6x +############################################################################### +ifdef CONFIG_DRM_AMD_DC_SI +IRQ_DCE60 = irq_service_dce60.o + +AMD_DAL_IRQ_DCE60 = $(addprefix $(AMDDALPATH)/dc/irq/dce60/,$(IRQ_DCE60)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE60) +endif + ############################################################################### # DCE 8x ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c new file mode 100644 index 0000000000000..524481885fd0a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c @@ -0,0 +1,395 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include <linux/slab.h> + +#include "dm_services.h" + +#include "include/logger_interface.h" + +#include "irq_service_dce60.h" +#include "../dce110/irq_service_dce110.h" + +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +#define VISLANDS30_IV_SRCID_D1_VBLANK 1 +#define VISLANDS30_IV_SRCID_D2_VBLANK 2 +#define VISLANDS30_IV_SRCID_D3_VBLANK 3 +#define VISLANDS30_IV_SRCID_D4_VBLANK 4 +#define VISLANDS30_IV_SRCID_D5_VBLANK 5 +#define VISLANDS30_IV_SRCID_D6_VBLANK 6 + +#include "dc_types.h" + +static bool hpd_ack( + struct irq_service *irq_service, + const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = + get_reg_field_value( + value, + DC_HPD1_INT_STATUS, + DC_HPD1_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value( + value, + current_status ? 0 : 1, + DC_HPD1_INT_CONTROL, + DC_HPD1_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = dce110_vblank_set, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs_dce60 = { + .set = NULL, + .ack = NULL +}; + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_INVALID + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\ + },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_irq_info_funcs\ + } + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD6 + reg_num] = {\ + .enable_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + .enable_value = {\ + DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\ + ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\ + .ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\ + .ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\ + .status_reg = mmDC_HPD ## reg_num ## _INT_STATUS,\ + .funcs = &hpd_rx_irq_info_funcs\ + } + +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + .enable_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_CONTROL,\ + .enable_mask =\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + .enable_value = {\ + GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\ + ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\ + .ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\ + .ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\ + .status_reg = mmDCP ## reg_num ##_GRPH_INTERRUPT_STATUS,\ + .funcs = &pflip_irq_info_funcs\ + } + +#define vupdate_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + .enable_reg = mmCRTC ## reg_num ## _CRTC_INTERRUPT_CONTROL,\ + .enable_mask =\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + .enable_value = {\ + CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\ + ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\ + .ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\ + .ack_mask =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .ack_value =\ + CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\ + .funcs = &vblank_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + .enable_reg = mmLB ## reg_num ## _INT_MASK,\ + .enable_mask =\ + INT_MASK__VBLANK_INT_MASK,\ + .enable_value = {\ + INT_MASK__VBLANK_INT_MASK,\ + ~INT_MASK__VBLANK_INT_MASK},\ + .ack_reg = mmLB ## reg_num ## _VBLANK_STATUS,\ + .ack_mask =\ + VBLANK_STATUS__VBLANK_ACK_MASK,\ + .ack_value =\ + VBLANK_STATUS__VBLANK_ACK_MASK,\ + .funcs = &vblank_irq_info_funcs_dce60\ + } + +#define dummy_irq_entry() \ + {\ + .funcs = &dummy_irq_info_funcs\ + } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info +irq_source_info_dce60[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(1), + hpd_int_entry(2), + hpd_int_entry(3), + hpd_int_entry(4), + hpd_int_entry(5), + hpd_int_entry(6), + hpd_rx_int_entry(1), + hpd_rx_int_entry(2), + hpd_rx_int_entry(3), + hpd_rx_int_entry(4), + hpd_rx_int_entry(5), + hpd_rx_int_entry(6), + i2c_int_entry(1), + i2c_int_entry(2), + i2c_int_entry(3), + i2c_int_entry(4), + i2c_int_entry(5), + i2c_int_entry(6), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + dp_sink_int_entry(3), + dp_sink_int_entry(4), + dp_sink_int_entry(5), + dp_sink_int_entry(6), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + pflip_int_entry(2), + pflip_int_entry(3), + pflip_int_entry(4), + pflip_int_entry(5), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + dc_underflow_int_entry(3), + dc_underflow_int_entry(4), + dc_underflow_int_entry(5), + dc_underflow_int_entry(6), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_int_entry(0), + vupdate_int_entry(1), + vupdate_int_entry(2), + vupdate_int_entry(3), + vupdate_int_entry(4), + vupdate_int_entry(5), + vblank_int_entry(0), + vblank_int_entry(1), + vblank_int_entry(2), + vblank_int_entry(3), + vblank_int_entry(4), + vblank_int_entry(5), +}; + +enum dc_irq_source to_dal_irq_source_dce60( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case VISLANDS30_IV_SRCID_D1_VBLANK: + return DC_IRQ_SOURCE_VBLANK1; + case VISLANDS30_IV_SRCID_D2_VBLANK: + return DC_IRQ_SOURCE_VBLANK2; + case VISLANDS30_IV_SRCID_D3_VBLANK: + return DC_IRQ_SOURCE_VBLANK3; + case VISLANDS30_IV_SRCID_D4_VBLANK: + return DC_IRQ_SOURCE_VBLANK4; + case VISLANDS30_IV_SRCID_D5_VBLANK: + return DC_IRQ_SOURCE_VBLANK5; + case VISLANDS30_IV_SRCID_D6_VBLANK: + return DC_IRQ_SOURCE_VBLANK6; + case VISLANDS30_IV_SRCID_D1_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE1; + case VISLANDS30_IV_SRCID_D2_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE2; + case VISLANDS30_IV_SRCID_D3_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE3; + case VISLANDS30_IV_SRCID_D4_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE4; + case VISLANDS30_IV_SRCID_D5_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE5; + case VISLANDS30_IV_SRCID_D6_V_UPDATE_INT: + return DC_IRQ_SOURCE_VUPDATE6; + case VISLANDS30_IV_SRCID_D1_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP1; + case VISLANDS30_IV_SRCID_D2_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP2; + case VISLANDS30_IV_SRCID_D3_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP3; + case VISLANDS30_IV_SRCID_D4_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP4; + case VISLANDS30_IV_SRCID_D5_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP5; + case VISLANDS30_IV_SRCID_D6_GRPH_PFLIP: + return DC_IRQ_SOURCE_PFLIP6; + + case VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_A: + return DC_IRQ_SOURCE_HPD1; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_B: + return DC_IRQ_SOURCE_HPD2; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_C: + return DC_IRQ_SOURCE_HPD3; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_D: + return DC_IRQ_SOURCE_HPD4; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_E: + return DC_IRQ_SOURCE_HPD5; + case VISLANDS30_IV_EXTID_HOTPLUG_DETECT_F: + return DC_IRQ_SOURCE_HPD6; + case VISLANDS30_IV_EXTID_HPD_RX_A: + return DC_IRQ_SOURCE_HPD1RX; + case VISLANDS30_IV_EXTID_HPD_RX_B: + return DC_IRQ_SOURCE_HPD2RX; + case VISLANDS30_IV_EXTID_HPD_RX_C: + return DC_IRQ_SOURCE_HPD3RX; + case VISLANDS30_IV_EXTID_HPD_RX_D: + return DC_IRQ_SOURCE_HPD4RX; + case VISLANDS30_IV_EXTID_HPD_RX_E: + return DC_IRQ_SOURCE_HPD5RX; + case VISLANDS30_IV_EXTID_HPD_RX_F: + return DC_IRQ_SOURCE_HPD6RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static const struct irq_service_funcs irq_service_funcs_dce60 = { + .to_dal_irq_source = to_dal_irq_source_dce60 +}; + +static void dce60_irq_construct( + struct irq_service *irq_service, + struct irq_service_init_data *init_data) +{ + dal_irq_service_construct(irq_service, init_data); + + irq_service->info = irq_source_info_dce60; + irq_service->funcs = &irq_service_funcs_dce60; +} + +struct irq_service *dal_irq_service_dce60_create( + struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), + GFP_KERNEL); + + if (!irq_service) + return NULL; + + dce60_irq_construct(irq_service, init_data); + return irq_service; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.h b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.h new file mode 100644 index 0000000000000..294db29e81157 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DAL_IRQ_SERVICE_DCE60_H__ +#define __DAL_IRQ_SERVICE_DCE60_H__ + +#include "../irq_service.h" + +enum dc_irq_source to_dal_irq_source_dce60( + struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id); + +struct irq_service *dal_irq_service_dce60_create( + struct irq_service_init_data *init_data); + +#endif + diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 33053b9fe6bd1..6bf27bde87240 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -32,6 +32,9 @@ #include "dce110/irq_service_dce110.h" +#if defined(CONFIG_DRM_AMD_DC_SI) +#include "dce60/irq_service_dce60.h" +#endif #include "dce80/irq_service_dce80.h" -- GitLab From 55e56389bdecc4f08524a6ae81940b13f986e125 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sun, 26 May 2019 17:33:45 +0200 Subject: [PATCH 0078/1494] drm/amd/display: amdgpu_dm: add SI support (v4) [Why] amdgpu_dm.c requires changes for SI chipsets init and irq handlers registration [How] SI support: load_dmcu_fw(), amdgpu_dm_initialize_drm_device(), dm_early_init() Add DCE6 specific dce60_register_irq_handlers() function (v1) NOTE: As per Kaveri and older amdgpu.dc=1 kernel cmdline is required (v2) fix for bc011f9 ("drm/amdgpu: Change SI/CI gfx/sdma/smu init sequence") remove CHIP_HAINAN support since it does not have physical DCE6 module (v3) fix vblank irq support for DCE6 using ad hoc dce60_register_irq_handlers() replicating for vblank irq the behavior of dce110_register_irq_handlers() as per commit b57de80 ("drm/amd/display: Register on VLBLANK ISR.") (v4) updated due to following kernel 5.2 commit: b2fddb13 ("drm/amd/display: Drop underlay plane support") Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 3100c59d17078..149da893b7142 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1066,6 +1066,12 @@ static int load_dmcu_fw(struct amdgpu_device *adev) const struct dmcu_firmware_header_v1_0 *hdr; switch(adev->asic_type) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: +#endif case CHIP_BONAIRE: case CHIP_HAWAII: case CHIP_KAVERI: @@ -2473,6 +2479,89 @@ static void register_hpd_handlers(struct amdgpu_device *adev) } } +#if defined(CONFIG_DRM_AMD_DC_SI) +/* Register IRQ sources and initialize IRQ callbacks */ +static int dce60_register_irq_handlers(struct amdgpu_device *adev) +{ + struct dc *dc = adev->dm.dc; + struct common_irq_params *c_irq_params; + struct dc_interrupt_params int_params = {0}; + int r; + int i; + unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY; + + int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT; + int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT; + + /* + * Actions of amdgpu_irq_add_id(): + * 1. Register a set() function with base driver. + * Base driver will call set() function to enable/disable an + * interrupt in DC hardware. + * 2. Register amdgpu_dm_irq_handler(). + * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts + * coming from DC hardware. + * amdgpu_dm_irq_handler() will re-direct the interrupt to DC + * for acknowledging and handling. */ + + /* Use VBLANK interrupt */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq); + if (r) { + DRM_ERROR("Failed to add crtc irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i+1 , 0); + + c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_crtc_high_irq, c_irq_params); + } + + /* Use GRPH_PFLIP interrupt */ + for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP; + i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) { + r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq); + if (r) { + DRM_ERROR("Failed to add page flip irq id!\n"); + return r; + } + + int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT; + int_params.irq_source = + dc_interrupt_to_irq_source(dc, i, 0); + + c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST]; + + c_irq_params->adev = adev; + c_irq_params->irq_src = int_params.irq_source; + + amdgpu_dm_irq_register_interrupt(adev, &int_params, + dm_pflip_high_irq, c_irq_params); + + } + + /* HPD */ + r = amdgpu_irq_add_id(adev, client_id, + VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq); + if (r) { + DRM_ERROR("Failed to add hpd irq id!\n"); + return r; + } + + register_hpd_handlers(adev); + + return 0; +} +#endif + /* Register IRQ sources and initialize IRQ callbacks */ static int dce110_register_irq_handlers(struct amdgpu_device *adev) { @@ -3204,6 +3293,17 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) /* Software is initialized. Now we can register interrupt handlers. */ switch (adev->asic_type) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: + if (dce60_register_irq_handlers(dm->adev)) { + DRM_ERROR("DM: Failed to initialize IRQ\n"); + goto fail; + } + break; +#endif case CHIP_BONAIRE: case CHIP_HAWAII: case CHIP_KAVERI: @@ -3328,6 +3428,20 @@ static int dm_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; switch (adev->asic_type) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + adev->mode_info.num_crtc = 6; + adev->mode_info.num_hpd = 6; + adev->mode_info.num_dig = 6; + break; + case CHIP_OLAND: + adev->mode_info.num_crtc = 2; + adev->mode_info.num_hpd = 2; + adev->mode_info.num_dig = 2; + break; +#endif case CHIP_BONAIRE: case CHIP_HAWAII: adev->mode_info.num_crtc = 6; -- GitLab From 3ecb3b794e2c1793443b72a968cb09d829c01a10 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sat, 11 Jul 2020 22:59:07 +0200 Subject: [PATCH 0079/1494] drm/amd/display: dc/clk_mgr: add support for SI parts (v2) (v1) Changelog [Why] After commit c69dd2d "drm/amd/display: Refactor clk_mgr functions" dc/clk_mgr requires these changes to add SI parts support Necessary to avoid hitting default: ASSERT(0); /* Unknown Asic */ that would cause kernel freeze [How] Add case statement for FAMILY_SI chipsets (v2) Changelog [Why] DCE6 has no DPREFCLK_CNTL register [How] Add DCE6 specific macros definitions for CLK registers and masks Add DCE6 specific dce60/dce60_clk_mgr.c for DCE6 customization Code style: reuse all the public functions in dce100/dce_clk_mgr.h header Code style: use dce60_* static functions as per other DCE implementations Add dce60_get_dp_ref_freq_khz() w/o using DPREFCLK_CNTL register Use dce60_get_dp_ref_freq_khz() function in dce60_funcs Add DCE6 specific dce60_clk_mgr_construct dc/clk_mgr/dce_clk_mgr.c: use dce60_clk_mgr_construct for FAMILY_SI chipsets Add Makefile rules for dce60_clk_mgr.o target conditional to CONFIG_DRM_AMD_DC_SI Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/clk_mgr/Makefile | 11 ++ .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 6 + .../display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 174 ++++++++++++++++++ .../display/dc/clk_mgr/dce60/dce60_clk_mgr.h | 36 ++++ 4 files changed, 227 insertions(+) create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 6874276bb2a10..52b1ce775a1e8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -30,6 +30,17 @@ AMD_DAL_CLK_MGR = $(addprefix $(AMDDALPATH)/dc/clk_mgr/,$(CLK_MGR)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR) +ifdef CONFIG_DRM_AMD_DC_SI +############################################################################### +# DCE 60 +############################################################################### +CLK_MGR_DCE60 = dce60_clk_mgr.o + +AMD_DAL_CLK_MGR_DCE60 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dce60/,$(CLK_MGR_DCE60)) + +AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCE60) +endif + ############################################################################### # DCE 100 and DCE8x ############################################################################### diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 6a345d43028ca..efb909ef7a0f7 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -34,6 +34,7 @@ #include "dce110/dce110_clk_mgr.h" #include "dce112/dce112_clk_mgr.h" #include "dce120/dce120_clk_mgr.h" +#include "dce60/dce60_clk_mgr.h" #include "dcn10/rv1_clk_mgr.h" #include "dcn10/rv2_clk_mgr.h" #include "dcn20/dcn20_clk_mgr.h" @@ -123,6 +124,11 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p } switch (asic_id.chip_family) { +#if defined(CONFIG_DRM_AMD_DC_SI) + case FAMILY_SI: + dce60_clk_mgr_construct(ctx, clk_mgr); + break; +#endif case FAMILY_CI: case FAMILY_KV: dce_clk_mgr_construct(ctx, clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c new file mode 100644 index 0000000000000..c11c6b3a787d2 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -0,0 +1,174 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#include "dccg.h" +#include "clk_mgr_internal.h" +#include "dce100/dce_clk_mgr.h" +#include "dce110/dce110_clk_mgr.h" +#include "dce60_clk_mgr.h" +#include "reg_helper.h" +#include "dmcu.h" +#include "core_types.h" +#include "dal_asic_id.h" + +/* + * Currently the register shifts and masks in this file are used for dce60 + * which has no DPREFCLK_CNTL register + * TODO: remove this when DENTIST_DISPCLK_CNTL + * is moved to dccg, where it belongs + */ +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" + +#define REG(reg) \ + (clk_mgr->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name + +/* set register offset */ +#define SR(reg_name)\ + .reg_name = mm ## reg_name + +static const struct clk_mgr_registers disp_clk_regs = { + CLK_COMMON_REG_LIST_DCE60_BASE() +}; + +static const struct clk_mgr_shift disp_clk_shift = { + CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(__SHIFT) +}; + +static const struct clk_mgr_mask disp_clk_mask = { + CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(_MASK) +}; + + +/* Max clock values for each state indexed by "enum clocks_state": */ +static const struct state_dependent_clocks dce60_max_clks_by_state[] = { +/* ClocksStateInvalid - should not be used */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */ +{ .display_clk_khz = 0, .pixel_clk_khz = 0 }, +/* ClocksStateLow */ +{ .display_clk_khz = 352000, .pixel_clk_khz = 330000}, +/* ClocksStateNominal */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +/* ClocksStatePerformance */ +{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; + +int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + int dprefclk_wdivider; + int dp_ref_clk_khz; + int target_div; + + /* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ + + /* Read the mmDENTIST_DISPCLK_CNTL to get the currently + * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ + target_div = dentist_get_divider_from_did(dprefclk_wdivider); + + /* Calculate the current DFS clock, in kHz.*/ + dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR + * clk_mgr->base.dentist_vco_freq_khz) / target_div; + + return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); +} + +static void dce60_pplib_apply_display_requirements( + struct dc *dc, + struct dc_state *context) +{ + struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; + + pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); + + dce110_fill_display_configs(context, pp_display_cfg); + + if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); +} + +static void dce60_update_clocks(struct clk_mgr *clk_mgr_base, + struct dc_state *context, + bool safe_to_lower) +{ + struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dm_pp_power_level_change_request level_change_req; + int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; + + /*TODO: W/A for dal3 linux, investigate why this works */ + if (!clk_mgr_dce->dfs_bypass_active) + patched_disp_clk = patched_disp_clk * 115 / 100; + + level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); + /* get max clock state from PPLIB */ + if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower) + || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) { + if (dm_pp_apply_power_level_change_request(clk_mgr_base->ctx, &level_change_req)) + clk_mgr_dce->cur_min_clks_state = level_change_req.power_level; + } + + if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr_base->clks.dispclk_khz)) { + patched_disp_clk = dce_set_clock(clk_mgr_base, patched_disp_clk); + clk_mgr_base->clks.dispclk_khz = patched_disp_clk; + } + dce60_pplib_apply_display_requirements(clk_mgr_base->ctx->dc, context); +} + + + + + + + + +static struct clk_mgr_funcs dce60_funcs = { + .get_dp_ref_clk_frequency = dce60_get_dp_ref_freq_khz, + .update_clocks = dce60_update_clocks +}; + +void dce60_clk_mgr_construct( + struct dc_context *ctx, + struct clk_mgr_internal *clk_mgr) +{ + dce_clk_mgr_construct(ctx, clk_mgr); + + memcpy(clk_mgr->max_clks_by_state, + dce60_max_clks_by_state, + sizeof(dce60_max_clks_by_state)); + + clk_mgr->regs = &disp_clk_regs; + clk_mgr->clk_mgr_shift = &disp_clk_shift; + clk_mgr->clk_mgr_mask = &disp_clk_mask; + clk_mgr->base.funcs = &dce60_funcs; +} + diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h new file mode 100644 index 0000000000000..eca3e5168089b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h @@ -0,0 +1,36 @@ +/* + * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + + +#ifndef DAL_DC_DCE_DCE60_CLK_MGR_H_ +#define DAL_DC_DCE_DCE60_CLK_MGR_H_ + +#include "dc.h" + +void dce60_clk_mgr_construct( + struct dc_context *ctx, + struct clk_mgr_internal *clk_mgr_dce); + +#endif /* DAL_DC_DCE_DCE60_CLK_MGR_H_ */ -- GitLab From f17f90f4fe43a4ff157a15d5be1986b2bdfe2aed Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 19 Jun 2020 00:12:05 +0200 Subject: [PATCH 0080/1494] drm/amd/display: dc/dce60: set max_cursor_size to 64 [Why] Issue in the Mouse cursor size in Linux Desktop Environments [How] In DCE6 dc->caps.max_cursor_size need to be set as 64 instead of 128 Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c index 18d535c2cc28f..534db1c4eaa62 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c @@ -970,7 +970,7 @@ static bool dce60_construct( pool->base.timing_generator_count = res_cap.num_timing_generator; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 40; - dc->caps.max_cursor_size = 128; + dc->caps.max_cursor_size = 64; dc->caps.dual_link_dvi = true; dc->caps.extended_aux_timeout_support = false; @@ -1164,7 +1164,7 @@ static bool dce61_construct( pool->base.timing_generator_count = res_cap_61.num_timing_generator; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 40; - dc->caps.max_cursor_size = 128; + dc->caps.max_cursor_size = 64; dc->caps.is_apu = true; /************************************************* @@ -1361,7 +1361,7 @@ static bool dce64_construct( pool->base.timing_generator_count = res_cap_64.num_timing_generator; dc->caps.max_downscale_ratio = 200; dc->caps.i2c_speed_in_khz = 40; - dc->caps.max_cursor_size = 128; + dc->caps.max_cursor_size = 64; dc->caps.is_apu = true; /************************************************* -- GitLab From 2a39b1f16b526528132685e308fe83a64bafb263 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:00:51 +0200 Subject: [PATCH 0081/1494] drm/amd/display: dce_audio: add DCE6 specific macros,functions [Why] DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask in DCCG_AUDIO_DTO_SOURCE register [How] Add DCE6 specific macros definitions for AUD masks DCE6 AUD macros will avoid buiding errors when using DCE6 headers Add dce60_aud_wall_dto_setup() w/o 512*Fs programming Use dce60_aud_wall_dto_setup() in dce60_funcs Add DCE specific dce60_audio_create Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dce/dce_audio.c | 131 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_audio.h | 23 +++ 2 files changed, 154 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index 4080465797127..2a2a0fdb92539 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -867,6 +867,98 @@ void dce_aud_wall_dto_setup( } } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_aud_wall_dto_setup( + struct audio *audio, + enum signal_type signal, + const struct audio_crtc_info *crtc_info, + const struct audio_pll_info *pll_info) +{ + struct dce_audio *aud = DCE_AUD(audio); + + struct azalia_clock_info clock_info = { 0 }; + + if (dc_is_hdmi_signal(signal)) { + uint32_t src_sel; + + /*DTO0 Programming goal: + -generate 24MHz, 128*Fs from 24MHz + -use DTO0 when an active HDMI port is connected + (optionally a DP is connected) */ + + /* calculate DTO settings */ + get_azalia_clock_info_hdmi( + crtc_info->requested_pixel_clock_100Hz, + crtc_info->calculated_pixel_clock_100Hz, + &clock_info); + + DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d"\ + "calculated_pixel_clock_100Hz =%d\n"\ + "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\ + crtc_info->requested_pixel_clock_100Hz,\ + crtc_info->calculated_pixel_clock_100Hz,\ + clock_info.audio_dto_module,\ + clock_info.audio_dto_phase); + + /* On TN/SI, Program DTO source select and DTO select before + programming DTO modulo and DTO phase. These bits must be + programmed first, otherwise there will be no HDMI audio at boot + up. This is a HW sequence change (different from old ASICs). + Caution when changing this programming sequence. + + HDMI enabled, using DTO0 + program master CRTC for DTO0 */ + src_sel = pll_info->dto_source - DTO_SOURCE_ID0; + REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel, + DCCG_AUDIO_DTO_SEL, 0); + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO0_MODULE, + DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO0_PHASE, + DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase); + } else { + /*DTO1 Programming goal: + -generate 24MHz, 128*Fs from 24MHz (DCE6 does not support 512*Fs) + -default is to used DTO1, and switch to DTO0 when an audio + master HDMI port is connected + -use as default for DP + + calculate DTO settings */ + get_azalia_clock_info_dp( + crtc_info->requested_pixel_clock_100Hz, + pll_info, + &clock_info); + + /* Program DTO select before programming DTO modulo and DTO + phase. default to use DTO1 */ + + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, + DCCG_AUDIO_DTO_SEL, 1); + + /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1) + * Cannot select 512fs for DP + * + * DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask + */ + + /* module */ + REG_UPDATE(DCCG_AUDIO_DTO1_MODULE, + DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module); + + /* phase */ + REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, + DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); + + /* DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask in DCCG_AUDIO_DTO_SOURCE reg */ + + } +} +#endif + static bool dce_aud_endpoint_valid(struct audio *audio) { uint32_t value; @@ -926,6 +1018,19 @@ static const struct audio_funcs funcs = { .az_configure = dce_aud_az_configure, .destroy = dce_aud_destroy, }; + +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct audio_funcs dce60_funcs = { + .endpoint_valid = dce_aud_endpoint_valid, + .hw_init = dce_aud_hw_init, + .wall_dto_setup = dce60_aud_wall_dto_setup, + .az_enable = dce_aud_az_enable, + .az_disable = dce_aud_az_disable, + .az_configure = dce_aud_az_configure, + .destroy = dce_aud_destroy, +}; +#endif + void dce_aud_destroy(struct audio **audio) { struct dce_audio *aud = DCE_AUD(*audio); @@ -959,3 +1064,29 @@ struct audio *dce_audio_create( return &audio->base; } +#if defined(CONFIG_DRM_AMD_DC_SI) +struct audio *dce60_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_audio_mask *masks + ) +{ + struct dce_audio *audio = kzalloc(sizeof(*audio), GFP_KERNEL); + + if (audio == NULL) { + ASSERT_CRITICAL(audio); + return NULL; + } + + audio->base.ctx = ctx; + audio->base.inst = inst; + audio->base.funcs = &dce60_funcs; + + audio->regs = reg; + audio->shifts = shifts; + audio->masks = masks; + return &audio->base; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h index 1392fab0860ba..5622d5e32d818 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h @@ -64,6 +64,20 @@ SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define AUD_DCE60_MASK_SH_LIST(mask_sh)\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\ + SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\ + SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\ + SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh), \ + SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh) +#endif struct dce_audio_registers { uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX; @@ -135,6 +149,15 @@ struct audio *dce_audio_create( const struct dce_audio_shift *shifts, const struct dce_audio_mask *masks); +#if defined(CONFIG_DRM_AMD_DC_SI) +struct audio *dce60_audio_create( + struct dc_context *ctx, + unsigned int inst, + const struct dce_audio_registers *reg, + const struct dce_audio_shift *shifts, + const struct dce_audio_mask *masks); +#endif + void dce_aud_destroy(struct audio **audio); void dce_aud_hw_init(struct audio *audio); -- GitLab From eab5a79984b1736a5b2b5b0713e8e179df7f8442 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:05:01 +0200 Subject: [PATCH 0082/1494] drm/amd/display: dce_dmcu: add DCE6 specific macros,functions [Why] DCE6 has no SMU_INTERRUPT_CONTROL register, but it's used for DCN10 and later [How] Add DCE6 specific macros definitions for DMCU registers and masks DCE6 DMCU macros will avoid buiding errors when using DCE6 headers There is no other change needed in dce_dcmu Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h index 5e044c2d3d6d3..93e7f34d4775e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h @@ -46,6 +46,24 @@ SR(SMU_INTERRUPT_CONTROL), \ SR(DC_DMCU_SCRATCH) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define DMCU_DCE60_REG_LIST() \ + SR(DMCU_CTRL), \ + SR(DMCU_STATUS), \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_WR_CTRL), \ + SR(DMCU_IRAM_WR_DATA), \ + SR(MASTER_COMM_DATA_REG1), \ + SR(MASTER_COMM_DATA_REG2), \ + SR(MASTER_COMM_DATA_REG3), \ + SR(MASTER_COMM_CMD_REG), \ + SR(MASTER_COMM_CNTL_REG), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SR(DC_DMCU_SCRATCH) +#endif + #define DMCU_DCE80_REG_LIST() \ SR(DMCU_CTRL), \ SR(DMCU_STATUS), \ @@ -104,6 +122,25 @@ STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \ DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define DMCU_MASK_SH_LIST_DCE60(mask_sh) \ + DMCU_SF(DMCU_CTRL, \ + DMCU_ENABLE, mask_sh), \ + DMCU_SF(DMCU_STATUS, \ + UC_IN_STOP_MODE, mask_sh), \ + DMCU_SF(DMCU_STATUS, \ + UC_IN_RESET, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_HOST_ACCESS_EN, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_WR_ADDR_AUTO_INC, mask_sh), \ + DMCU_SF(DMCU_RAM_ACCESS_CTRL, \ + IRAM_RD_ADDR_AUTO_INC, mask_sh), \ + DMCU_SF(MASTER_COMM_CMD_REG, \ + MASTER_COMM_CMD_REG_BYTE0, mask_sh), \ + DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh) +#endif + #define DMCU_MASK_SH_LIST_DCE80(mask_sh) \ DMCU_SF(DMCU_CTRL, \ DMCU_ENABLE, mask_sh), \ -- GitLab From ff0649f846395690aadc3c43c2c85995e32e8322 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:10:01 +0200 Subject: [PATCH 0083/1494] drm/amd/display: dce_hwseq: add DCE6 specific macros,functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] DCE6 has no BLND_CONTROL register for Blender HW programming DCE6 has no BLND_V_UPDATE_LOCK register for Pipe Locking [How] Add DCE6 specific macros definitions for HWSEQ registers and masks DCE6 HWSEQ macros will avoid buiding errors when using DCE6 headers Add dce60_pipe_control_lock() stub with no op Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c | 9 +++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c index e1c5839a80dcd..4202fadb2c0e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.c @@ -85,6 +85,15 @@ void dce_pipe_control_lock(struct dc *dc, } } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_pipe_control_lock(struct dc *dc, + struct pipe_ctx *pipe, + bool lock) +{ + /* DCE6 has no BLND_V_UPDATE_LOCK register */ +} +#endif + void dce_set_blender_mode(struct dce_hwseq *hws, unsigned int blnd_inst, enum blnd_mode mode) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index 66b88d6ba3987..70bbc1311327f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -110,6 +110,12 @@ SR(BLNDV_CONTROL),\ HWSEQ_PIXEL_RATE_REG_LIST(CRTC) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define HWSEQ_DCE6_REG_LIST() \ + HWSEQ_DCEF_REG_LIST_DCE8(), \ + HWSEQ_PIXEL_RATE_REG_LIST(CRTC) +#endif + #define HWSEQ_DCE8_REG_LIST() \ HWSEQ_DCEF_REG_LIST_DCE8(), \ HWSEQ_BLND_REG_LIST(), \ @@ -488,6 +494,12 @@ struct dce_hwseq_registers { HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh),\ HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define HWSEQ_DCE6_MASK_SH_LIST(mask_sh)\ + .DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \ + HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_) +#endif + #define HWSEQ_DCE8_MASK_SH_LIST(mask_sh)\ .DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \ HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\ @@ -836,6 +848,12 @@ void dce_pipe_control_lock(struct dc *dc, void dce_set_blender_mode(struct dce_hwseq *hws, unsigned int blnd_inst, enum blnd_mode mode); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_pipe_control_lock(struct dc *dc, + struct pipe_ctx *pipe, + bool lock); +#endif + void dce_clock_gating_power_up(struct dce_hwseq *hws, bool enable); -- GitLab From 89571d7c31011abd5673ef22f0da72ecaef7b7a5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:15:01 +0200 Subject: [PATCH 0084/1494] drm/amd/display: dce_ipp: add DCE6 specific macros,functions [Why] DCE6 does not have CURSOR2_DEGAMMA_MODE bit in DEGAMMA_CONTROL register [How] Add DCE6 specific macros definitions for IPP masks DCE6 IPP macros will avoid buiding errors when using DCE6 headers Add dce60_ipp_set_degamma() function w/o Cursor2 Degamma programming Use dce60_ipp_set_degamma() in ipp_funcs dce60_ipp_funcs Add DCE6 specific dce60_ipp_construct Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c | 46 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h | 49 ++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c index ce30dbf579d4f..80569a2734eb6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c @@ -231,6 +231,22 @@ static void dce_ipp_set_degamma( CURSOR2_DEGAMMA_MODE, degamma_type); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_ipp_set_degamma( + struct input_pixel_processor *ipp, + enum ipp_degamma_mode mode) +{ + struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp); + uint32_t degamma_type = (mode == IPP_DEGAMMA_MODE_HW_sRGB) ? 1 : 0; + + ASSERT(mode == IPP_DEGAMMA_MODE_BYPASS || mode == IPP_DEGAMMA_MODE_HW_sRGB); + /* DCE6 does not have CURSOR2_DEGAMMA_MODE bit in DEGAMMA_CONTROL reg */ + REG_SET_2(DEGAMMA_CONTROL, 0, + GRPH_DEGAMMA_MODE, degamma_type, + CURSOR_DEGAMMA_MODE, degamma_type); +} +#endif + static const struct ipp_funcs dce_ipp_funcs = { .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes, .ipp_cursor_set_position = dce_ipp_cursor_set_position, @@ -239,6 +255,17 @@ static const struct ipp_funcs dce_ipp_funcs = { .ipp_set_degamma = dce_ipp_set_degamma }; +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct ipp_funcs dce60_ipp_funcs = { + .ipp_cursor_set_attributes = dce_ipp_cursor_set_attributes, + .ipp_cursor_set_position = dce_ipp_cursor_set_position, + .ipp_program_prescale = dce_ipp_program_prescale, + .ipp_program_input_lut = dce_ipp_program_input_lut, + .ipp_set_degamma = dce60_ipp_set_degamma +}; +#endif + + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -260,6 +287,25 @@ void dce_ipp_construct( ipp_dce->ipp_mask = ipp_mask; } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_ipp_construct( + struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask) +{ + ipp_dce->base.ctx = ctx; + ipp_dce->base.inst = inst; + ipp_dce->base.funcs = &dce60_ipp_funcs; + + ipp_dce->regs = regs; + ipp_dce->ipp_shift = ipp_shift; + ipp_dce->ipp_mask = ipp_mask; +} +#endif + void dce_ipp_destroy(struct input_pixel_processor **ipp) { kfree(TO_DCE_IPP(*ipp)); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h index ca04e97d44c3c..0028d4bdd81bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.h @@ -147,6 +147,46 @@ IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh), \ IPP_SF(DCP0_DEGAMMA_CONTROL, CURSOR2_DEGAMMA_MODE, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define IPP_DCE60_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \ + IPP_SF(CUR_UPDATE, CURSOR_UPDATE_LOCK, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_EN, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_MODE, mask_sh), \ + IPP_SF(CUR_CONTROL, CURSOR_2X_MAGNIFY, mask_sh), \ + IPP_SF(CUR_CONTROL, CUR_INV_TRANS_CLAMP, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_X_POSITION, mask_sh), \ + IPP_SF(CUR_POSITION, CURSOR_Y_POSITION, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_X, mask_sh), \ + IPP_SF(CUR_HOT_SPOT, CURSOR_HOT_SPOT_Y, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR1, CUR_COLOR1_RED, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_BLUE, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_GREEN, mask_sh), \ + IPP_SF(CUR_COLOR2, CUR_COLOR2_RED, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_WIDTH, mask_sh), \ + IPP_SF(CUR_SIZE, CURSOR_HEIGHT, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS_HIGH, CURSOR_SURFACE_ADDRESS_HIGH, mask_sh), \ + IPP_SF(CUR_SURFACE_ADDRESS, CURSOR_SURFACE_ADDRESS, mask_sh), \ + IPP_SF(PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_BYPASS, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_SCALE_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_R, GRPH_PRESCALE_BIAS_R, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_SCALE_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_G, GRPH_PRESCALE_BIAS_G, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_SCALE_B, mask_sh), \ + IPP_SF(PRESCALE_VALUES_GRPH_B, GRPH_PRESCALE_BIAS_B, mask_sh), \ + IPP_SF(INPUT_GAMMA_CONTROL, GRPH_INPUT_GAMMA_MODE, mask_sh), \ + IPP_SF(DC_LUT_WRITE_EN_MASK, DC_LUT_WRITE_EN_MASK, mask_sh), \ + IPP_SF(DC_LUT_RW_MODE, DC_LUT_RW_MODE, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_R_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_G_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_CONTROL, DC_LUT_DATA_B_FORMAT, mask_sh), \ + IPP_SF(DC_LUT_RW_INDEX, DC_LUT_RW_INDEX, mask_sh), \ + IPP_SF(DC_LUT_SEQ_COLOR, DC_LUT_SEQ_COLOR, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, GRPH_DEGAMMA_MODE, mask_sh), \ + IPP_SF(DEGAMMA_CONTROL, CURSOR_DEGAMMA_MODE, mask_sh) +#endif + #define IPP_REG_FIELD_LIST(type) \ type CURSOR_UPDATE_LOCK; \ type CURSOR_EN; \ @@ -233,6 +273,15 @@ void dce_ipp_construct(struct dce_ipp *ipp_dce, const struct dce_ipp_shift *ipp_shift, const struct dce_ipp_mask *ipp_mask); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_ipp_construct(struct dce_ipp *ipp_dce, + struct dc_context *ctx, + int inst, + const struct dce_ipp_registers *regs, + const struct dce_ipp_shift *ipp_shift, + const struct dce_ipp_mask *ipp_mask); +#endif + void dce_ipp_destroy(struct input_pixel_processor **ipp); #endif /* _DCE_IPP_H_ */ -- GitLab From c1a64ebd4d13da1ddc4ec7ddc14a0c86a281a7f8 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:20:01 +0200 Subject: [PATCH 0085/1494] drm/amd/display: dce_link_encoder: add DCE6 specific macros,functions [Why] DCE6 has no DP_DPHY_SCRAM_CNTL register [How] Add DCE6 specific macros definitions for LE registers DCE6 LE macros will avoid buiding errors when using DCE6 headers Add dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2() w/o Scramble Control programming Add dce60_set_dp_phy_pattern_passthrough_mode() w/o Scramble Control programming Add dce60_configure_encoder() w/o Scramble Control programming Add dce60_link_encoder_enable_dp_output() w/ dce60_configure_encoder Add dce60_link_encoder_enable_dp_mst_output() w/ dce60_configure_encoder Add dce60_link_encoder_dp_set_phy_pattern() w/ dce60_set_dp_phy_pattern_passthrough_mode Use dce60_link_encoder_enable_dp_output() in dce60_lnk_enc_funcs Use dce60_link_encoder_enable_dp_mst_output() in dce60_lnk_enc_funcs Use dce60_link_encoder_dp_set_phy_pattern() in dce60_lnk_enc_funcs Add DCE6 specific dce60_link_encoder_construct Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_link_encoder.c | 369 ++++++++++++++++++ .../drm/amd/display/dc/dce/dce_link_encoder.h | 38 ++ 2 files changed, 407 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 8d8c84c81b34e..b409f6b2bfd83 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -425,6 +425,59 @@ static void set_dp_phy_pattern_hbr2_compliance_cp2520_2( enable_phy_bypass_mode(enc110, false); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2( + struct dce110_link_encoder *enc110, + unsigned int cp2520_pattern) +{ + + /* previously there is a register DP_HBR2_EYE_PATTERN + * that is enabled to get the pattern. + * But it does not work with the latest spec change, + * so we are programming the following registers manually. + * + * The following settings have been confirmed + * by Nick Chorney and Sandra Liu */ + + /* Disable PHY Bypass mode to setup the test pattern */ + + enable_phy_bypass_mode(enc110, false); + + /* Setup DIG encoder in DP SST mode */ + enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT); + + /* ensure normal panel mode. */ + setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT); + + /* no vbid after BS (SR) + * DP_LINK_FRAMING_CNTL changed history Sandra Liu + * 11000260 / 11000104 / 110000FC */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0xFC, + DP_VBID_DISABLE, 1, + DP_VID_ENHANCED_FRAME_MODE, 1); + + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */ + + /* select cp2520 patterns */ + if (REG(DP_DPHY_HBR2_PATTERN_CONTROL)) + REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL, + DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern); + else + /* pre-DCE11 can only generate CP2520 pattern 2 */ + ASSERT(cp2520_pattern == 2); + + /* set link training complete */ + set_link_training_complete(enc110, true); + + /* disable video stream */ + REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); +} +#endif + static void set_dp_phy_pattern_passthrough_mode( struct dce110_link_encoder *enc110, enum dp_panel_mode panel_mode) @@ -452,6 +505,35 @@ static void set_dp_phy_pattern_passthrough_mode( disable_prbs_mode(enc110); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_set_dp_phy_pattern_passthrough_mode( + struct dce110_link_encoder *enc110, + enum dp_panel_mode panel_mode) +{ + /* program correct panel mode */ + setup_panel_mode(enc110, panel_mode); + + /* restore LINK_FRAMING_CNTL + * in case we were doing HBR2 compliance pattern before + */ + REG_UPDATE_3(DP_LINK_FRAMING_CNTL, + DP_IDLE_BS_INTERVAL, 0x2000, + DP_VBID_DISABLE, 0, + DP_VID_ENHANCED_FRAME_MODE, 1); + + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */ + + /* set link training complete */ + set_link_training_complete(enc110, true); + + /* Disable PHY Bypass mode to setup the test pattern */ + enable_phy_bypass_mode(enc110, false); + + /* Disable PRBS mode */ + disable_prbs_mode(enc110); +} +#endif + /* return value is bit-vector */ static uint8_t get_frontend_source( enum engine_id engine) @@ -490,6 +572,20 @@ static void configure_encoder( REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_configure_encoder( + struct dce110_link_encoder *enc110, + const struct dc_link_settings *link_settings) +{ + /* set number of lanes */ + + REG_SET(DP_CONFIG, 0, + DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE); + + /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */ +} +#endif + static void aux_initialize( struct dce110_link_encoder *enc110) { @@ -1059,6 +1155,87 @@ void dce110_link_encoder_enable_dp_mst_output( BREAK_TO_DEBUGGER(); } } + +#if defined(CONFIG_DRM_AMD_DC_SI) +/* enables DP PHY output */ +void dce60_link_encoder_enable_dp_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + dce60_configure_encoder(enc110, link_settings); + cntl.connector_obj_id = enc110->base.connector; + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = enc->preferred_engine; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +/* enables DP PHY output in MST mode */ +void dce60_link_encoder_enable_dp_mst_output( + struct link_encoder *enc, + const struct dc_link_settings *link_settings, + enum clock_source_id clock_source) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Enable the PHY */ + + /* number_of_lanes is used for pixel clock adjust, + * but it's not passed to asic_control. + * We need to set number of lanes manually. + */ + dce60_configure_encoder(enc110, link_settings); + + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc110->base.transmitter; + cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc110->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate + * LINK_RATE_REF_FREQ_IN_KHZ; + /* TODO: check if undefined works */ + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + + result = link_transmitter_control(enc110, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} +#endif + /* * @brief * Disable transmitter and its encoder @@ -1208,6 +1385,63 @@ void dce110_link_encoder_dp_set_phy_pattern( } } +#if defined(CONFIG_DRM_AMD_DC_SI) +/* set DP PHY test and training patterns */ +void dce60_link_encoder_dp_set_phy_pattern( + struct link_encoder *enc, + const struct encoder_set_dp_phy_pattern_param *param) +{ + struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); + + switch (param->dp_phy_pattern) { + case DP_TEST_PATTERN_TRAINING_PATTERN1: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN2: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN3: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2); + break; + case DP_TEST_PATTERN_TRAINING_PATTERN4: + dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3); + break; + case DP_TEST_PATTERN_D102: + set_dp_phy_pattern_d102(enc110); + break; + case DP_TEST_PATTERN_SYMBOL_ERROR: + set_dp_phy_pattern_symbol_error(enc110); + break; + case DP_TEST_PATTERN_PRBS7: + set_dp_phy_pattern_prbs7(enc110); + break; + case DP_TEST_PATTERN_80BIT_CUSTOM: + set_dp_phy_pattern_80bit_custom( + enc110, param->custom_pattern); + break; + case DP_TEST_PATTERN_CP2520_1: + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1); + break; + case DP_TEST_PATTERN_CP2520_2: + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2); + break; + case DP_TEST_PATTERN_CP2520_3: + dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3); + break; + case DP_TEST_PATTERN_VIDEO_MODE: { + dce60_set_dp_phy_pattern_passthrough_mode( + enc110, param->dp_panel_mode); + break; + } + + default: + /* invalid phy pattern */ + ASSERT_CRITICAL(false); + break; + } +} +#endif + static void fill_stream_allocation_row_info( const struct link_mst_stream_allocation *stream_allocation, uint32_t *src, @@ -1407,3 +1641,138 @@ void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc, *link_settings = max_link_cap; } + +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct link_encoder_funcs dce60_lnk_enc_funcs = { + .validate_output_with_stream = + dce110_link_encoder_validate_output_with_stream, + .hw_init = dce110_link_encoder_hw_init, + .setup = dce110_link_encoder_setup, + .enable_tmds_output = dce110_link_encoder_enable_tmds_output, + .enable_dp_output = dce60_link_encoder_enable_dp_output, + .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output, + .enable_lvds_output = dce110_link_encoder_enable_lvds_output, + .disable_output = dce110_link_encoder_disable_output, + .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, + .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern, + .update_mst_stream_allocation_table = + dce110_link_encoder_update_mst_stream_allocation_table, + .psr_program_dp_dphy_fast_training = + dce110_psr_program_dp_dphy_fast_training, + .psr_program_secondary_packet = dce110_psr_program_secondary_packet, + .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe, + .enable_hpd = dce110_link_encoder_enable_hpd, + .disable_hpd = dce110_link_encoder_disable_hpd, + .is_dig_enabled = dce110_is_dig_enabled, + .destroy = dce110_link_encoder_destroy, + .get_max_link_cap = dce110_link_encoder_get_max_link_cap +}; + +void dce60_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs) +{ + struct bp_encoder_cap_info bp_cap_info = {0}; + const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; + enum bp_result result = BP_RESULT_OK; + + enc110->base.funcs = &dce60_lnk_enc_funcs; + enc110->base.ctx = init_data->ctx; + enc110->base.id = init_data->encoder; + + enc110->base.hpd_source = init_data->hpd_source; + enc110->base.connector = init_data->connector; + + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc110->base.features = *enc_features; + + enc110->base.transmitter = init_data->transmitter; + + /* set the flag to indicate whether driver poll the I2C data pin + * while doing the DP sink detect + */ + +/* if (dal_adapter_service_is_feature_supported(as, + FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) + enc110->base.features.flags.bits. + DP_SINK_DETECT_POLL_DATA_PIN = true;*/ + + enc110->base.output_signals = + SIGNAL_TYPE_DVI_SINGLE_LINK | + SIGNAL_TYPE_DVI_DUAL_LINK | + SIGNAL_TYPE_LVDS | + SIGNAL_TYPE_DISPLAY_PORT | + SIGNAL_TYPE_DISPLAY_PORT_MST | + SIGNAL_TYPE_EDP | + SIGNAL_TYPE_HDMI_TYPE_A; + + /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE. + * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY. + * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer + * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS. + * Prefer DIG assignment is decided by board design. + * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design + * and VBIOS will filter out 7 UNIPHY for DCE 8.0. + * By this, adding DIGG should not hurt DCE 8.0. + * This will let DCE 8.1 share DCE 8.0 as much as possible + */ + + enc110->link_regs = link_regs; + enc110->aux_regs = aux_regs; + enc110->hpd_regs = hpd_regs; + + switch (enc110->base.transmitter) { + case TRANSMITTER_UNIPHY_A: + enc110->base.preferred_engine = ENGINE_ID_DIGA; + break; + case TRANSMITTER_UNIPHY_B: + enc110->base.preferred_engine = ENGINE_ID_DIGB; + break; + case TRANSMITTER_UNIPHY_C: + enc110->base.preferred_engine = ENGINE_ID_DIGC; + break; + case TRANSMITTER_UNIPHY_D: + enc110->base.preferred_engine = ENGINE_ID_DIGD; + break; + case TRANSMITTER_UNIPHY_E: + enc110->base.preferred_engine = ENGINE_ID_DIGE; + break; + case TRANSMITTER_UNIPHY_F: + enc110->base.preferred_engine = ENGINE_ID_DIGF; + break; + case TRANSMITTER_UNIPHY_G: + enc110->base.preferred_engine = ENGINE_ID_DIGG; + break; + default: + ASSERT_CRITICAL(false); + enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; + } + + /* default to one to mirror Windows behavior */ + enc110->base.features.flags.bits.HDMI_6GB_EN = 1; + + result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios, + enc110->base.id, &bp_cap_info); + + /* Override features with DCE-specific values */ + if (BP_RESULT_OK == result) { + enc110->base.features.flags.bits.IS_HBR2_CAPABLE = + bp_cap_info.DP_HBR2_EN; + enc110->base.features.flags.bits.IS_HBR3_CAPABLE = + bp_cap_info.DP_HBR3_EN; + enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + } else { + DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", + __func__, + result); + } + if (enc110->base.ctx->dc->debug.hdmi20_disable) { + enc110->base.features.flags.bits.HDMI_6GB_EN = 0; + } +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 384389f0e2c31..40ea2220330c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -75,6 +75,34 @@ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ SR(DCI_MEM_PWR_STATUS) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define LE_DCE60_REG_LIST(id)\ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ + SR(DMCU_RAM_ACCESS_CTRL), \ + SR(DMCU_IRAM_RD_CTRL), \ + SR(DMCU_IRAM_RD_DATA), \ + SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \ + SRI(DIG_BE_CNTL, DIG, id), \ + SRI(DIG_BE_EN_CNTL, DIG, id), \ + SRI(DP_CONFIG, DP, id), \ + SRI(DP_DPHY_CNTL, DP, id), \ + SRI(DP_DPHY_PRBS_CNTL, DP, id), \ + SRI(DP_DPHY_SYM0, DP, id), \ + SRI(DP_DPHY_SYM1, DP, id), \ + SRI(DP_DPHY_SYM2, DP, id), \ + SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \ + SRI(DP_LINK_CNTL, DP, id), \ + SRI(DP_LINK_FRAMING_CNTL, DP, id), \ + SRI(DP_MSE_SAT0, DP, id), \ + SRI(DP_MSE_SAT1, DP, id), \ + SRI(DP_MSE_SAT2, DP, id), \ + SRI(DP_MSE_SAT_UPDATE, DP, id), \ + SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_VID_STREAM_CNTL, DP, id), \ + SRI(DP_DPHY_FAST_TRAINING, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id) +#endif + #define LE_DCE80_REG_LIST(id)\ SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \ LE_COMMON_REG_LIST_BASE(id) @@ -169,6 +197,16 @@ void dce110_link_encoder_construct( const struct dce110_link_enc_aux_registers *aux_regs, const struct dce110_link_enc_hpd_registers *hpd_regs); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_link_encoder_construct( + struct dce110_link_encoder *enc110, + const struct encoder_init_data *init_data, + const struct encoder_feature_support *enc_features, + const struct dce110_link_enc_registers *link_regs, + const struct dce110_link_enc_aux_registers *aux_regs, + const struct dce110_link_enc_hpd_registers *hpd_regs); +#endif + bool dce110_link_encoder_validate_dvi_output( const struct dce110_link_encoder *enc110, enum signal_type connector_signal, -- GitLab From b91f056fb5e192411635ce9e9e81f9f741ea1f5f Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:25:01 +0200 Subject: [PATCH 0086/1494] drm/amd/display: dce_mem_input: add DCE6 specific macros,functions (v2) [Why] DCE6 has DPG_PIPE_ARBITRATION_CONTROL3 register for Line Buffer watermark selection DCE6 has STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK mask for Stutter watermark selection DCE6 has NB_PSTATE_CHANGE_WATERMARK_MASK mask for North Bridge watermark selection DCE6 has no GRPH_MICRO_TILE_MODE mask DCE6 has no HW_ROTATION register [How] Add DCE6 specific macros definitions for MI registers and masks Add DCE6 specific registers to dce_mem_input_registers struct Add DCE6 specific masks to dce_mem_input_masks struct DCE6 MI macros/structs changes will avoid buiding errors when using DCE6 headers Add dce60_program_urgency_watermark() function Add dce60_program_nbp_watermark() function Add dce60_program_stutter_watermark() function Add dce60_mi_program_display_marks() function w/ new DCE6 watermark programming Add DCE6 specific tiling programming and modify DCE8 case Add dce60_program_size() fuction w/o Rotation processing Add dce60_mi_program_surface_config() fuction Use dce60_mi_program_display_marks() in dce60_mi_funcs Use dce60_mi_program_surface_config() in dce60_mi_funcs Add DCE6 specific dce60_mem_input_construct v2: remove unused variable (Alex) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_mem_input.c | 176 +++++++++++++++++- .../drm/amd/display/dc/dce/dce_mem_input.h | 103 ++++++++++ 2 files changed, 278 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c index 51481e922eb9c..79a6f261a0da9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c @@ -174,6 +174,22 @@ static void program_urgency_watermark( URGENCY_HIGH_WATERMARK, urgency_high_wm); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_program_urgency_watermark( + struct dce_mem_input *dce_mi, + uint32_t wm_select, + uint32_t urgency_low_wm, + uint32_t urgency_high_wm) +{ + REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL3, + URGENCY_WATERMARK_MASK, wm_select); + + REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0, + URGENCY_LOW_WATERMARK, urgency_low_wm, + URGENCY_HIGH_WATERMARK, urgency_high_wm); +} +#endif + static void dce120_program_urgency_watermark( struct dce_mem_input *dce_mi, uint32_t wm_select, @@ -193,6 +209,25 @@ static void dce120_program_urgency_watermark( } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_program_nbp_watermark( + struct dce_mem_input *dce_mi, + uint32_t wm_select, + uint32_t nbp_wm) +{ + REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select); + + REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_ENABLE, 1, + NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1, + NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1); + + REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, + NB_PSTATE_CHANGE_WATERMARK, nbp_wm); +} +#endif + static void program_nbp_watermark( struct dce_mem_input *dce_mi, uint32_t wm_select, @@ -225,6 +260,20 @@ static void program_nbp_watermark( } } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_program_stutter_watermark( + struct dce_mem_input *dce_mi, + uint32_t wm_select, + uint32_t stutter_mark) +{ + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select); + + REG_UPDATE(DPG_PIPE_STUTTER_CONTROL, + STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark); +} +#endif + static void dce120_program_stutter_watermark( struct dce_mem_input *dce_mi, uint32_t wm_select, @@ -286,6 +335,34 @@ static void dce_mi_program_display_marks( program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */ } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_mi_program_display_marks( + struct mem_input *mi, + struct dce_watermarks nbp, + struct dce_watermarks stutter_exit, + struct dce_watermarks stutter_enter, + struct dce_watermarks urgent, + uint32_t total_dest_line_time_ns) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1; + + dce60_program_urgency_watermark(dce_mi, 2, /* set a */ + urgent.a_mark, total_dest_line_time_ns); + dce60_program_urgency_watermark(dce_mi, 1, /* set d */ + urgent.d_mark, total_dest_line_time_ns); + + REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE, stutter_en, + STUTTER_IGNORE_FBC, 1); + dce60_program_nbp_watermark(dce_mi, 2, nbp.a_mark); /* set a */ + dce60_program_nbp_watermark(dce_mi, 1, nbp.d_mark); /* set d */ + + dce60_program_stutter_watermark(dce_mi, 2, stutter_exit.a_mark); /* set a */ + dce60_program_stutter_watermark(dce_mi, 1, stutter_exit.d_mark); /* set d */ +} +#endif + static void dce112_mi_program_display_marks(struct mem_input *mi, struct dce_watermarks nbp, struct dce_watermarks stutter_exit, @@ -369,7 +446,7 @@ static void program_tiling( */ } - if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */ + if (dce_mi->masks->GRPH_MICRO_TILE_MODE) { /* GFX8 */ REG_UPDATE_9(GRPH_CONTROL, GRPH_NUM_BANKS, info->gfx8.num_banks, GRPH_BANK_WIDTH, info->gfx8.bank_width, @@ -385,6 +462,23 @@ static void program_tiling( GRPH_Z, 0); */ } + + if (dce_mi->masks->GRPH_ARRAY_MODE) { /* GFX6 but reuses gfx8 struct */ + REG_UPDATE_8(GRPH_CONTROL, + GRPH_NUM_BANKS, info->gfx8.num_banks, + GRPH_BANK_WIDTH, info->gfx8.bank_width, + GRPH_BANK_HEIGHT, info->gfx8.bank_height, + GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect, + GRPH_TILE_SPLIT, info->gfx8.tile_split, + /* DCE6 has no GRPH_MICRO_TILE_MODE mask */ + GRPH_PIPE_CONFIG, info->gfx8.pipe_config, + GRPH_ARRAY_MODE, info->gfx8.array_mode, + GRPH_COLOR_EXPANSION_MODE, 1); + /* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */ + /* + GRPH_Z, 0); + */ + } } @@ -429,6 +523,36 @@ static void program_size_and_rotation( GRPH_ROTATION_ANGLE, rotation_angles[rotation]); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_program_size( + struct dce_mem_input *dce_mi, + enum dc_rotation_angle rotation, /* not used in DCE6 */ + const struct plane_size *plane_size) +{ + struct rect hw_rect = plane_size->surface_size; + /* DCE6 has no HW rotation, skip rotation_angles declaration */ + + /* DCE6 has no HW rotation, skip ROTATION_ANGLE_* processing */ + + REG_SET(GRPH_X_START, 0, + GRPH_X_START, hw_rect.x); + + REG_SET(GRPH_Y_START, 0, + GRPH_Y_START, hw_rect.y); + + REG_SET(GRPH_X_END, 0, + GRPH_X_END, hw_rect.width); + + REG_SET(GRPH_Y_END, 0, + GRPH_Y_END, hw_rect.height); + + REG_SET(GRPH_PITCH, 0, + GRPH_PITCH, plane_size->surface_pitch); + + /* DCE6 has no HW_ROTATION register, skip setting rotation_angles */ +} +#endif + static void program_grph_pixel_format( struct dce_mem_input *dce_mi, enum surface_pixel_format format) @@ -521,6 +645,28 @@ static void dce_mi_program_surface_config( program_grph_pixel_format(dce_mi, format); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_mi_program_surface_config( + struct mem_input *mi, + enum surface_pixel_format format, + union dc_tiling_info *tiling_info, + struct plane_size *plane_size, + enum dc_rotation_angle rotation, /* not used in DCE6 */ + struct dc_plane_dcc_param *dcc, + bool horizontal_mirror) +{ + struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi); + REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1); + + program_tiling(dce_mi, tiling_info); + dce60_program_size(dce_mi, rotation, plane_size); + + if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN && + format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) + program_grph_pixel_format(dce_mi, format); +} +#endif + static uint32_t get_dmif_switch_time_us( uint32_t h_total, uint32_t v_total, @@ -741,6 +887,20 @@ static const struct mem_input_funcs dce_mi_funcs = { .mem_input_is_flip_pending = dce_mi_is_flip_pending }; +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct mem_input_funcs dce60_mi_funcs = { + .mem_input_program_display_marks = dce60_mi_program_display_marks, + .allocate_mem_input = dce_mi_allocate_dmif, + .free_mem_input = dce_mi_free_dmif, + .mem_input_program_surface_flip_and_addr = + dce_mi_program_surface_flip_and_addr, + .mem_input_program_pte_vm = dce_mi_program_pte_vm, + .mem_input_program_surface_config = + dce60_mi_program_surface_config, + .mem_input_is_flip_pending = dce_mi_is_flip_pending +}; +#endif + static const struct mem_input_funcs dce112_mi_funcs = { .mem_input_program_display_marks = dce112_mi_program_display_marks, .allocate_mem_input = dce_mi_allocate_dmif, @@ -783,6 +943,20 @@ void dce_mem_input_construct( dce_mi->masks = mi_mask; } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask) +{ + dce_mem_input_construct(dce_mi, ctx, inst, regs, mi_shift, mi_mask); + dce_mi->base.funcs = &dce60_mi_funcs; +} +#endif + void dce112_mem_input_construct( struct dce_mem_input *dce_mi, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index d15b0d7f47fcd..23db5c72f07ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -58,6 +58,31 @@ SRI(DVMM_PTE_CONTROL, DCP, id),\ SRI(DVMM_PTE_ARB_CONTROL, DCP, id) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define MI_DCE6_REG_LIST(id)\ + SRI(GRPH_ENABLE, DCP, id),\ + SRI(GRPH_CONTROL, DCP, id),\ + SRI(GRPH_X_START, DCP, id),\ + SRI(GRPH_Y_START, DCP, id),\ + SRI(GRPH_X_END, DCP, id),\ + SRI(GRPH_Y_END, DCP, id),\ + SRI(GRPH_PITCH, DCP, id),\ + SRI(GRPH_SWAP_CNTL, DCP, id),\ + SRI(PRESCALE_GRPH_CONTROL, DCP, id),\ + SRI(GRPH_UPDATE, DCP, id),\ + SRI(GRPH_FLIP_CONTROL, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS, DCP, id),\ + SRI(GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, DCP, id),\ + SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\ + SRI(DPG_PIPE_ARBITRATION_CONTROL3, DMIF_PG, id),\ + SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\ + SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\ + SRI(DMIF_BUFFER_CONTROL, PIPE, id) +#endif + #define MI_DCE8_REG_LIST(id)\ MI_DCE_BASE_REG_LIST(id),\ SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id) @@ -104,6 +129,9 @@ struct dce_mem_input_registers { uint32_t GRPH_SECONDARY_SURFACE_ADDRESS_HIGH; /* DMIF_PG */ uint32_t DPG_PIPE_ARBITRATION_CONTROL1; +#if defined(CONFIG_DRM_AMD_DC_SI) + uint32_t DPG_PIPE_ARBITRATION_CONTROL3; +#endif uint32_t DPG_WATERMARK_MASK_CONTROL; uint32_t DPG_PIPE_URGENCY_CONTROL; uint32_t DPG_PIPE_URGENT_LEVEL_CONTROL; @@ -126,6 +154,18 @@ struct dce_mem_input_registers { #define SFB(blk_name, reg_name, field_name, post_fix)\ .field_name = blk_name ## reg_name ## __ ## field_name ## post_fix +#if defined(CONFIG_DRM_AMD_DC_SI) +#define MI_GFX6_TILE_MASK_SH_LIST(mask_sh, blk)\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh) +#endif + #define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_BANK_WIDTH, mask_sh),\ @@ -162,6 +202,32 @@ struct dce_mem_input_registers { SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\ SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define MI_DCP_MASK_SH_LIST_DCE6(mask_sh, blk)\ + SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ + SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\ + SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\ + SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\ + SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\ + SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\ + SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\ + SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_SECONDARY_SURFACE_ADDRESS, GRPH_SECONDARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, mask_sh),\ + SFB(blk, GRPH_PRIMARY_SURFACE_ADDRESS, GRPH_PRIMARY_SURFACE_ADDRESS, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING, mask_sh),\ + SFB(blk, GRPH_UPDATE, GRPH_UPDATE_LOCK, mask_sh),\ + SFB(blk, GRPH_FLIP_CONTROL, GRPH_SURFACE_UPDATE_H_RETRACE_EN, mask_sh) +#endif + #define MI_DCP_DCE11_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT, mask_sh) @@ -172,6 +238,33 @@ struct dce_mem_input_registers { SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_PTE_REQ_PER_CHUNK, mask_sh),\ SFB(blk, DVMM_PTE_ARB_CONTROL, DVMM_MAX_PTE_REQ_OUTSTANDING, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define MI_DMIF_PG_MASK_SH_LIST_DCE6(mask_sh, blk)\ + SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\ + SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh) + +#define MI_DMIF_PG_MASK_SH_DCE6(mask_sh, blk)\ + SFB(blk, DPG_PIPE_ARBITRATION_CONTROL3, URGENCY_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\ + SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh) + +#define MI_DCE6_MASK_SH_LIST(mask_sh)\ + MI_DCP_MASK_SH_LIST_DCE6(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_LIST_DCE6(mask_sh, ),\ + MI_DMIF_PG_MASK_SH_DCE6(mask_sh, ),\ + MI_GFX6_TILE_MASK_SH_LIST(mask_sh, ) +#endif + #define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\ SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\ SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\ @@ -345,6 +438,16 @@ void dce_mem_input_construct( const struct dce_mem_input_shift *mi_shift, const struct dce_mem_input_mask *mi_mask); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_mem_input_construct( + struct dce_mem_input *dce_mi, + struct dc_context *ctx, + int inst, + const struct dce_mem_input_registers *regs, + const struct dce_mem_input_shift *mi_shift, + const struct dce_mem_input_mask *mi_mask); +#endif + void dce112_mem_input_construct( struct dce_mem_input *dce_mi, struct dc_context *ctx, -- GitLab From d85a1e536ab8cbc9f96f7a0554703887d603c401 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:30:01 +0200 Subject: [PATCH 0087/1494] drm/amd/display: dce_opp: add DCE6 specific macros,functions [Why] DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL register DCE6 has no FMT_CLAMP_COMPONENT_{R,G,B} registers DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL register [How] Add DCE6 specific macros definitions for OPP registers and masks DCE6 OPP macros will avoid buiding errors when using DCE6 headers Add dce60_set_truncation() w/o FMT_TRUNCATE_MODE bit programming Add dce60_opp_set_clamping() w/o Format Clamp Component programming Add dce60_opp_program_fmt() w/o Format Subsampling bits programming Add dce60_opp_program_bit_depth_reduction() with dce60_set_truncation Use dce60_opp_program_fmt() in dce60_opp_funcs Use dce60_opp_program_bit_depth_reduction() in dce60_opp_funcs Add DCE6 specific dce60_opp_construct Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | 205 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_opp.h | 49 +++++ 2 files changed, 254 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 51081d9ae3fb7..e459ae65aaf76 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c @@ -141,6 +141,47 @@ static void set_truncation( params->flags.TRUNCATE_MODE); } +#if defined(CONFIG_DRM_AMD_DC_SI) +/** + * dce60_set_truncation + * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp + * 2) enable truncation + * 3) HW remove 12bit FMT support for DCE11 power saving reason. + */ +static void dce60_set_truncation( + struct dce110_opp *opp110, + const struct bit_depth_reduction_params *params) +{ + /* DCE6 has no FMT_TRUNCATE_MODE bit in FMT_BIT_DEPTH_CONTROL reg */ + + /*Disable truncation*/ + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 0, + FMT_TRUNCATE_DEPTH, 0); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + /* 8bpc trunc on YCbCr422*/ + if (params->flags.TRUNCATE_DEPTH == 1) + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 1); + else if (params->flags.TRUNCATE_DEPTH == 2) + /* 10bpc trunc on YCbCr422*/ + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, 2); + return; + } + /* on other format-to do */ + if (params->flags.TRUNCATE_ENABLED == 0) + return; + /*Set truncation depth and Enable truncation*/ + REG_UPDATE_2(FMT_BIT_DEPTH_CONTROL, + FMT_TRUNCATE_EN, 1, + FMT_TRUNCATE_DEPTH, + params->flags.TRUNCATE_DEPTH); +} +#endif /** * set_spatial_dither @@ -373,6 +414,57 @@ void dce110_opp_set_clamping( } } +#if defined(CONFIG_DRM_AMD_DC_SI) +/** + * Set Clamping for DCE6 parts + * 1) Set clamping format based on bpc - 0 for 6bpc (No clamping) + * 1 for 8 bpc + * 2 for 10 bpc + * 3 for 12 bpc + * 7 for programable + * 2) Enable clamp if Limited range requested + */ +void dce60_opp_set_clamping( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 0, + FMT_CLAMP_COLOR_FORMAT, 0); + + switch (params->clamping_level) { + case CLAMPING_FULL_RANGE: + break; + case CLAMPING_LIMITED_RANGE_8BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 1); + break; + case CLAMPING_LIMITED_RANGE_10BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 2); + break; + case CLAMPING_LIMITED_RANGE_12BPC: + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 3); + break; + case CLAMPING_LIMITED_RANGE_PROGRAMMABLE: + /*Set clamp control*/ + REG_SET_2(FMT_CLAMP_CNTL, 0, + FMT_CLAMP_DATA_EN, 1, + FMT_CLAMP_COLOR_FORMAT, 7); + + /* DCE6 does have FMT_CLAMP_COMPONENT_{R,G,B} registers */ + + break; + default: + break; + } +} +#endif + /** * set_pixel_encoding * @@ -408,6 +500,39 @@ static void set_pixel_encoding( } +#if defined(CONFIG_DRM_AMD_DC_SI) +/** + * dce60_set_pixel_encoding + * DCE6 has no FMT_SUBSAMPLING_{MODE,ORDER} bits in FMT_CONTROL reg + * Set Pixel Encoding + * 0: RGB 4:4:4 or YCbCr 4:4:4 or YOnly + * 1: YCbCr 4:2:2 + */ +static void dce60_set_pixel_encoding( + struct dce110_opp *opp110, + const struct clamping_and_pixel_encoding_params *params) +{ + if (opp110->opp_mask->FMT_CBCR_BIT_REDUCTION_BYPASS) + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_CBCR_BIT_REDUCTION_BYPASS, 0); + else + REG_UPDATE(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0); + + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + REG_UPDATE(FMT_CONTROL, + FMT_PIXEL_ENCODING, 1); + } + if (params->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + REG_UPDATE_2(FMT_CONTROL, + FMT_PIXEL_ENCODING, 2, + FMT_CBCR_BIT_REDUCTION_BYPASS, 1); + } + +} +#endif + void dce110_opp_program_bit_depth_reduction( struct output_pixel_processor *opp, const struct bit_depth_reduction_params *params) @@ -419,6 +544,19 @@ void dce110_opp_program_bit_depth_reduction( set_temporal_dither(opp110, params); } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_opp_program_bit_depth_reduction( + struct output_pixel_processor *opp, + const struct bit_depth_reduction_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce60_set_truncation(opp110, params); + set_spatial_dither(opp110, params); + set_temporal_dither(opp110, params); +} +#endif + void dce110_opp_program_clamping_and_pixel_encoding( struct output_pixel_processor *opp, const struct clamping_and_pixel_encoding_params *params) @@ -429,6 +567,19 @@ void dce110_opp_program_clamping_and_pixel_encoding( set_pixel_encoding(opp110, params); } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_opp_program_clamping_and_pixel_encoding( + struct output_pixel_processor *opp, + const struct clamping_and_pixel_encoding_params *params) +{ + struct dce110_opp *opp110 = TO_DCE110_OPP(opp); + + dce60_opp_set_clamping(opp110, params); + dce60_set_pixel_encoding(opp110, params); +} +#endif + + static void program_formatter_420_memory(struct output_pixel_processor *opp) { struct dce110_opp *opp110 = TO_DCE110_OPP(opp); @@ -526,7 +677,32 @@ void dce110_opp_program_fmt( return; } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_opp_program_fmt( + struct output_pixel_processor *opp, + struct bit_depth_reduction_params *fmt_bit_depth, + struct clamping_and_pixel_encoding_params *clamping) +{ + /* dithering is affected by <CrtcSourceSelect>, hence should be + * programmed afterwards */ + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_420_memory(opp); + + dce60_opp_program_bit_depth_reduction( + opp, + fmt_bit_depth); + + dce60_opp_program_clamping_and_pixel_encoding( + opp, + clamping); + + if (clamping->pixel_encoding == PIXEL_ENCODING_YCBCR420) + program_formatter_reset_dig_resync_fifo(opp); + return; +} +#endif @@ -541,6 +717,15 @@ static const struct opp_funcs funcs = { .opp_program_bit_depth_reduction = dce110_opp_program_bit_depth_reduction }; +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct opp_funcs dce60_opp_funcs = { + .opp_set_dyn_expansion = dce110_opp_set_dyn_expansion, + .opp_destroy = dce110_opp_destroy, + .opp_program_fmt = dce60_opp_program_fmt, + .opp_program_bit_depth_reduction = dce60_opp_program_bit_depth_reduction +}; +#endif + void dce110_opp_construct(struct dce110_opp *opp110, struct dc_context *ctx, uint32_t inst, @@ -559,6 +744,26 @@ void dce110_opp_construct(struct dce110_opp *opp110, opp110->opp_mask = opp_mask; } +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask) +{ + opp110->base.funcs = &dce60_opp_funcs; + + opp110->base.ctx = ctx; + + opp110->base.inst = inst; + + opp110->regs = regs; + opp110->opp_shift = opp_shift; + opp110->opp_mask = opp_mask; +} +#endif + void dce110_opp_destroy(struct output_pixel_processor **opp) { if (*opp) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index 2ab0147cbd9d4..4d484ef60f357 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -81,6 +81,17 @@ enum dce110_opp_reg_type { OPP_COMMON_REG_LIST_BASE(id), \ SRI(CONTROL, FMT_MEMORY, id) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define OPP_DCE_60_REG_LIST(id) \ + SRI(FMT_DYNAMIC_EXP_CNTL, FMT, id), \ + SRI(FMT_BIT_DEPTH_CONTROL, FMT, id), \ + SRI(FMT_CONTROL, FMT, id), \ + SRI(FMT_DITHER_RAND_R_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_G_SEED, FMT, id), \ + SRI(FMT_DITHER_RAND_B_SEED, FMT, id), \ + SRI(FMT_CLAMP_CNTL, FMT, id) +#endif + #define OPP_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -192,6 +203,35 @@ enum dce110_opp_reg_type { OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_ORDER, mask_sh),\ OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define OPP_COMMON_MASK_SH_LIST_DCE_60(mask_sh)\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_EN, mask_sh),\ + OPP_SF(FMT_DYNAMIC_EXP_CNTL, FMT_DYNAMIC_EXP_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_SPATIAL_DITHER_MODE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_HIGHPASS_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_FRAME_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_RGB_RANDOM_ENABLE, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ + OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_LEVEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_25FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_50FRC_SEL, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_75FRC_SEL, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_DATA_EN, mask_sh),\ + OPP_SF(FMT_CLAMP_CNTL, FMT_CLAMP_COLOR_FORMAT, mask_sh),\ + OPP_SF(FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh) +#endif + #define OPP_REG_FIELD_LIST(type) \ type FMT_DYNAMIC_EXP_EN; \ type FMT_DYNAMIC_EXP_MODE; \ @@ -279,6 +319,15 @@ void dce110_opp_construct(struct dce110_opp *opp110, const struct dce_opp_shift *opp_shift, const struct dce_opp_mask *opp_mask); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_opp_construct(struct dce110_opp *opp110, + struct dc_context *ctx, + uint32_t inst, + const struct dce_opp_registers *regs, + const struct dce_opp_shift *opp_shift, + const struct dce_opp_mask *opp_mask); +#endif + void dce110_opp_destroy(struct output_pixel_processor **opp); -- GitLab From b70aaf5586f214d610ac21606128c0c992db5d9c Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:35:01 +0200 Subject: [PATCH 0088/1494] drm/amd/display: dce_transform: add DCE6 specific macros,functions [Why] DCE6 has no SCL_MODE and no SCL_{HORZ,VERT}_FILTER_INIT registers DCE6 has no SCL_BOUNDARY_MODE bit in SCL_CONTROL register DCE6 has Line Buffer programming registers (DC_LB_MEMORY_SPLIT,DC_LB_MEM_SIZE) DCE6 DATA_FORMAT register has only INTERLEAVE_EN bit DCE6 has no Out Clamp Control programming registers (OUT_CLAMP_CONTROL_*) [How] Add DCE6 specific macros definitions for XFM registers and masks Add DCE6 specific registers to dce_transform_registers struct Add DCE6 specific masks to dce_transform_mask struct DCE6 XFM macros/structs changes will avoid buiding errors when using DCE6 headers Add dce60_setup_scaling_configuration() w/o missing Scaling registers/bit programming Add dce60_transform_set_scaler() using DCE6 Line Buffer programming registers Add dce60_program_bit_depth_reduction() w/o Out Clamp Control programming Add dce60_transform_set_pixel_storage_depth() use dce60_program_bit_depth_reduction() Use dce60_transform_set_scaler() in dce60_transform_funcs Use dce60_transform_set_pixel_storage_depth() in dce60_transform_funcs Add DCE6 specific dce60_transform_construct Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_transform.c | 268 ++++++++++++++++++ .../drm/amd/display/dc/dce/dce_transform.h | 150 ++++++++++ 2 files changed, 418 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index ab63d0d0304cb..3303d01c1aaee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -146,6 +146,33 @@ static bool setup_scaling_configuration( return true; } +#if defined(CONFIG_DRM_AMD_DC_SI) +static bool dce60_setup_scaling_configuration( + struct dce_transform *xfm_dce, + const struct scaler_data *data) +{ + REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0); + + if (data->taps.h_taps + data->taps.v_taps <= 2) { + /* Set bypass */ + + /* DCE6 has no SCL_MODE register, skip scale mode programming */ + + return false; + } + + REG_SET_2(SCL_TAP_CONTROL, 0, + SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1, + SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); + + /* DCE6 has no SCL_MODE register, skip scale mode programming */ + + /* DCE6 has no SCL_BOUNDARY_MODE bit, skip replace out of bound pixels */ + + return true; +} +#endif + static void program_overscan( struct dce_transform *xfm_dce, const struct scaler_data *data) @@ -399,6 +426,89 @@ static void dce_transform_set_scaler( REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_transform_set_scaler( + struct transform *xfm, + const struct scaler_data *data) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + bool is_scaling_required; + bool filter_updated = false; + const uint16_t *coeffs_v, *coeffs_h; + + /*Use whole line buffer memory always*/ + REG_SET(DC_LB_MEMORY_SPLIT, 0, + DC_LB_MEMORY_CONFIG, 0); + + REG_SET(DC_LB_MEM_SIZE, 0, + DC_LB_MEM_SIZE, xfm_dce->lb_memory_size); + + /* Clear SCL_F_SHARP_CONTROL value to 0 */ + REG_WRITE(SCL_F_SHARP_CONTROL, 0); + + /* 1. Program overscan */ + program_overscan(xfm_dce, data); + + /* 2. Program taps and configuration */ + is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data); + + if (is_scaling_required) { + /* 3. Calculate and program ratio, filter initialization */ + struct scl_ratios_inits inits = { 0 }; + + calculate_inits(xfm_dce, data, &inits); + + program_scl_ratios_inits(xfm_dce, &inits); + + coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); + coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); + + if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) { + /* 4. Program vertical filters */ + if (xfm_dce->filter_v == NULL) + REG_SET(SCL_VERT_FILTER_CONTROL, 0, + SCL_V_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_RGB_Y_VERTICAL); + program_multi_taps_filter( + xfm_dce, + data->taps.v_taps, + coeffs_v, + FILTER_TYPE_ALPHA_VERTICAL); + + /* 5. Program horizontal filters */ + if (xfm_dce->filter_h == NULL) + REG_SET(SCL_HORZ_FILTER_CONTROL, 0, + SCL_H_2TAP_HARDCODE_COEF_EN, 0); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_RGB_Y_HORIZONTAL); + program_multi_taps_filter( + xfm_dce, + data->taps.h_taps, + coeffs_h, + FILTER_TYPE_ALPHA_HORIZONTAL); + + xfm_dce->filter_v = coeffs_v; + xfm_dce->filter_h = coeffs_h; + filter_updated = true; + } + } + + /* 6. Program the viewport */ + program_viewport(xfm_dce, &data->viewport); + + /* DCE6 does not have bit to flip to new coefficient memory */ + + /* DCE6 DATA_FORMAT register does not support ALPHA_EN */ +} +#endif + /***************************************************************************** * set_clamp * @@ -664,6 +774,67 @@ static void program_bit_depth_reduction( bit_depth_params->flags.HIGHPASS_RANDOM); } +#if defined(CONFIG_DRM_AMD_DC_SI) +/***************************************************************************** + * dce60_transform_bit_depth_reduction program + * + * @brief + * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, + * Dither) for dce + * + * @param depth : bit depth to set the clamp to (should match denorm) + * + ******************************************************************************/ +static void dce60_program_bit_depth_reduction( + struct dce_transform *xfm_dce, + enum dc_color_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + enum dcp_out_trunc_round_depth trunc_round_depth; + enum dcp_out_trunc_round_mode trunc_mode; + bool spatial_dither_enable; + + ASSERT(depth < COLOR_DEPTH_121212); /* Invalid clamp bit depth */ + + spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED; + /* Default to 12 bit truncation without rounding */ + trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; + trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; + + if (bit_depth_params->flags.TRUNCATE_ENABLED) { + /* Don't enable dithering if truncation is enabled */ + spatial_dither_enable = false; + trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ? + DCP_OUT_TRUNC_ROUND_MODE_ROUND : + DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; + + if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 || + bit_depth_params->flags.TRUNCATE_DEPTH == 1) + trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT; + else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2) + trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT; + else { + /* + * Invalid truncate/round depth. Setting here to 12bit + * to prevent use-before-initialize errors. + */ + trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; + BREAK_TO_DEBUGGER(); + } + } + + /* DCE6 has no OUT_CLAMP_CONTROL_* registers - set_clamp() is skipped */ + set_round(xfm_dce, trunc_mode, trunc_round_depth); + set_dither(xfm_dce, + spatial_dither_enable, + DCP_SPATIAL_DITHER_MODE_A_AA_A, + DCP_SPATIAL_DITHER_DEPTH_30BPP, + bit_depth_params->flags.FRAME_RANDOM, + bit_depth_params->flags.RGB_RANDOM, + bit_depth_params->flags.HIGHPASS_RANDOM); +} +#endif + static int dce_transform_get_max_num_of_supported_lines( struct dce_transform *xfm_dce, enum lb_pixel_depth depth, @@ -797,6 +968,59 @@ static void dce_transform_set_pixel_storage_depth( } } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_transform_set_pixel_storage_depth( + struct transform *xfm, + enum lb_pixel_depth depth, + const struct bit_depth_reduction_params *bit_depth_params) +{ + struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); + int pixel_depth, expan_mode; + enum dc_color_depth color_depth; + + switch (depth) { + case LB_PIXEL_DEPTH_18BPP: + color_depth = COLOR_DEPTH_666; + pixel_depth = 2; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_24BPP: + color_depth = COLOR_DEPTH_888; + pixel_depth = 1; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_30BPP: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + break; + case LB_PIXEL_DEPTH_36BPP: + color_depth = COLOR_DEPTH_121212; + pixel_depth = 3; + expan_mode = 0; + break; + default: + color_depth = COLOR_DEPTH_101010; + pixel_depth = 0; + expan_mode = 1; + BREAK_TO_DEBUGGER(); + break; + } + + set_denormalization(xfm_dce, color_depth); + dce60_program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params); + + /* DATA_FORMAT in DCE6 does not have PIXEL_DEPTH and PIXEL_EXPAN_MODE masks */ + + if (!(xfm_dce->lb_pixel_depth_supported & depth)) { + /*we should use unsupported capabilities + * unless it is required by w/a*/ + DC_LOG_WARNING("%s: Capability not supported", + __func__); + } +} +#endif + static void program_gamut_remap( struct dce_transform *xfm_dce, const uint16_t *reg_val) @@ -1335,6 +1559,21 @@ static const struct transform_funcs dce_transform_funcs = { .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps }; +#if defined(CONFIG_DRM_AMD_DC_SI) +static const struct transform_funcs dce60_transform_funcs = { + .transform_reset = dce_transform_reset, + .transform_set_scaler = dce60_transform_set_scaler, + .transform_set_gamut_remap = dce_transform_set_gamut_remap, + .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, + .opp_set_csc_default = dce110_opp_set_csc_default, + .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, + .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, + .opp_set_regamma_mode = dce110_opp_set_regamma_mode, + .transform_set_pixel_storage_depth = dce60_transform_set_pixel_storage_depth, + .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps +}; +#endif + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -1365,3 +1604,32 @@ void dce_transform_construct( xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ } + +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_transform_construct( + struct dce_transform *xfm_dce, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask) +{ + xfm_dce->base.ctx = ctx; + + xfm_dce->base.inst = inst; + xfm_dce->base.funcs = &dce60_transform_funcs; + + xfm_dce->regs = regs; + xfm_dce->xfm_shift = xfm_shift; + xfm_dce->xfm_mask = xfm_mask; + + xfm_dce->prescaler_on = true; + xfm_dce->lb_pixel_depth_supported = + LB_PIXEL_DEPTH_18BPP | + LB_PIXEL_DEPTH_24BPP | + LB_PIXEL_DEPTH_30BPP; + + xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; + xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 948281d8b6afd..95b28dadc8c5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -108,6 +108,68 @@ SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \ SRI(DCFE_MEM_PWR_STATUS, DCFE, id) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define XFM_COMMON_REG_LIST_DCE60_BASE(id) \ + SRI(DATA_FORMAT, LB, id), \ + SRI(GAMUT_REMAP_CONTROL, DCP, id), \ + SRI(GAMUT_REMAP_C11_C12, DCP, id), \ + SRI(GAMUT_REMAP_C13_C14, DCP, id), \ + SRI(GAMUT_REMAP_C21_C22, DCP, id), \ + SRI(GAMUT_REMAP_C23_C24, DCP, id), \ + SRI(GAMUT_REMAP_C31_C32, DCP, id), \ + SRI(GAMUT_REMAP_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_C11_C12, DCP, id), \ + SRI(OUTPUT_CSC_C13_C14, DCP, id), \ + SRI(OUTPUT_CSC_C21_C22, DCP, id), \ + SRI(OUTPUT_CSC_C23_C24, DCP, id), \ + SRI(OUTPUT_CSC_C31_C32, DCP, id), \ + SRI(OUTPUT_CSC_C33_C34, DCP, id), \ + SRI(OUTPUT_CSC_CONTROL, DCP, id), \ + SRI(REGAMMA_CNTLA_START_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_SLOPE_CNTL, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL1, DCP, id), \ + SRI(REGAMMA_CNTLA_END_CNTL2, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_0_1, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_2_3, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_4_5, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_6_7, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_8_9, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_10_11, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_12_13, DCP, id), \ + SRI(REGAMMA_CNTLA_REGION_14_15, DCP, id), \ + SRI(REGAMMA_LUT_WRITE_EN_MASK, DCP, id), \ + SRI(REGAMMA_LUT_INDEX, DCP, id), \ + SRI(REGAMMA_LUT_DATA, DCP, id), \ + SRI(REGAMMA_CONTROL, DCP, id), \ + SRI(DENORM_CONTROL, DCP, id), \ + SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \ + SRI(OUT_ROUND_CONTROL, DCP, id), \ + SRI(SCL_TAP_CONTROL, SCL, id), \ + SRI(SCL_CONTROL, SCL, id), \ + SRI(SCL_BYPASS_CONTROL, SCL, id), \ + SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \ + SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \ + SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \ + SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \ + SRI(SCL_COEF_RAM_SELECT, SCL, id), \ + SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \ + SRI(VIEWPORT_START, SCL, id), \ + SRI(VIEWPORT_SIZE, SCL, id), \ + SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \ + SRI(SCL_VERT_FILTER_INIT, SCL, id), \ + SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \ + SRI(DC_LB_MEMORY_SPLIT, LB, id), \ + SRI(DC_LB_MEM_SIZE, LB, id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id), \ + SRI(SCL_UPDATE, SCL, id), \ + SRI(SCL_F_SHARP_CONTROL, SCL, id) + +#define XFM_COMMON_REG_LIST_DCE60(id) \ + XFM_COMMON_REG_LIST_DCE60_BASE(id), \ + SRI(DCFE_MEM_LIGHT_SLEEP_CNTL, CRTC, id) +#endif + #define XFM_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix @@ -204,6 +266,75 @@ XFM_SF(DCFE_MEM_PWR_STATUS, DCP_REGAMMA_MEM_PWR_STATE, mask_sh),\ XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define XFM_COMMON_MASK_SH_LIST_DCE60(mask_sh) \ + XFM_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh), \ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, DCP_LUT_LIGHT_SLEEP_DIS, mask_sh),\ + OPP_SF(DCFE_MEM_LIGHT_SLEEP_CNTL, REGAMMA_LUT_MEM_PWR_STATE, mask_sh) + +#define XFM_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \ + XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \ + XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \ + XFM_SF(DATA_FORMAT, INTERLEAVE_EN, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \ + XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \ + XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \ + XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \ + XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \ + XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \ + XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \ + XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C11, mask_sh),\ + XFM_SF(OUTPUT_CSC_C11_C12, OUTPUT_CSC_C12, mask_sh),\ + XFM_SF(OUTPUT_CSC_CONTROL, OUTPUT_CSC_GRPH_MODE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_START_CNTL, REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_SLOPE_CNTL, REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL1, REGAMMA_CNTLA_EXP_REGION_END, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_BASE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_END_CNTL2, REGAMMA_CNTLA_EXP_REGION_END_SLOPE, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + XFM_SF(REGAMMA_CNTLA_REGION_0_1, REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + XFM_SF(REGAMMA_LUT_WRITE_EN_MASK, REGAMMA_LUT_WRITE_EN_MASK, mask_sh),\ + XFM_SF(REGAMMA_CONTROL, GRPH_REGAMMA_MODE, mask_sh),\ + XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \ + XFM_SF(SCL_BYPASS_CONTROL, SCL_BYPASS_MODE, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \ + XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \ + XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \ + XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \ + XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \ + XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(DC_LB_MEMORY_SPLIT, DC_LB_MEMORY_CONFIG, mask_sh), \ + XFM_SF(DC_LB_MEM_SIZE, DC_LB_MEM_SIZE, mask_sh) +#endif + #define XFM_COMMON_MASK_SH_LIST_SOC_BASE(mask_sh) \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \ XFM_SF(DCP0_OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \ @@ -302,6 +433,7 @@ type DCP_RGB_RANDOM_ENABLE; \ type DCP_HIGHPASS_RANDOM_ENABLE; \ type DENORM_MODE; \ + type INTERLEAVE_EN; \ type PIXEL_DEPTH; \ type PIXEL_EXPAN_MODE; \ type GAMUT_REMAP_C11; \ @@ -367,6 +499,8 @@ type SCL_H_INIT_FRAC; \ type SCL_V_INIT_INT; \ type SCL_V_INIT_FRAC; \ + type DC_LB_MEMORY_CONFIG; \ + type DC_LB_MEM_SIZE; \ type LB_MEMORY_CONFIG; \ type LB_MEMORY_SIZE; \ type SCL_V_2TAP_HARDCODE_COEF_EN; \ @@ -383,6 +517,9 @@ struct dce_transform_mask { }; struct dce_transform_registers { +#if defined(CONFIG_DRM_AMD_DC_SI) + uint32_t DATA_FORMAT; +#endif uint32_t LB_DATA_FORMAT; uint32_t GAMUT_REMAP_CONTROL; uint32_t GAMUT_REMAP_C11_C12; @@ -440,6 +577,10 @@ struct dce_transform_registers { uint32_t SCL_HORZ_FILTER_INIT; uint32_t SCL_VERT_FILTER_INIT; uint32_t SCL_AUTOMATIC_MODE_CONTROL; +#if defined(CONFIG_DRM_AMD_DC_SI) + uint32_t DC_LB_MEMORY_SPLIT; + uint32_t DC_LB_MEM_SIZE; +#endif uint32_t LB_MEMORY_CTRL; uint32_t SCL_UPDATE; uint32_t SCL_F_SHARP_CONTROL; @@ -489,6 +630,15 @@ void dce_transform_construct(struct dce_transform *xfm_dce, const struct dce_transform_shift *xfm_shift, const struct dce_transform_mask *xfm_mask); +#if defined(CONFIG_DRM_AMD_DC_SI) +void dce60_transform_construct(struct dce_transform *xfm_dce, + struct dc_context *ctx, + uint32_t inst, + const struct dce_transform_registers *regs, + const struct dce_transform_shift *xfm_shift, + const struct dce_transform_mask *xfm_mask); +#endif + bool dce_transform_get_optimal_number_of_taps( struct transform *xfm, struct scaler_data *scl_data, -- GitLab From 102b2f587ac814afd9ef396dd6fccb99d7f4d649 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Thu, 16 Jul 2020 00:54:08 +0200 Subject: [PATCH 0089/1494] drm/amd/display: dce_transform: DCE6 Scaling Horizontal Filter Init (v2) [Why] DCE6 has specific SCL_HORZ_FILTER_INIT_{LUMA_RGB,CHROMA} registers In DCE6 h_init_luma and h_init_chroma initialization is required Some DCE6 specific SCL_{HORZ,VERT}_FILTER_CONTROL masks were not listed [How] Add the registers and masks in dce_transform.h Add DCE6 specific struct sclh_ratios_inits in dce_transform.h Add dce60_calculate_inits() function Add dce60_program_scl_ratios_inits() function Fix dce60_transform_set_scaler() function v2: remove unused variable (Alex) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce/dce_transform.c | 72 +++++++++++++++++-- .../drm/amd/display/dc/dce/dce_transform.h | 28 ++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 3303d01c1aaee..2a32b66959ba2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -306,6 +306,36 @@ static void calculate_inits( inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5; } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_calculate_inits( + struct dce_transform *xfm_dce, + const struct scaler_data *data, + struct sclh_ratios_inits *inits) +{ + struct fixed31_32 v_init; + + inits->h_int_scale_ratio = + dc_fixpt_u2d19(data->ratios.horz) << 5; + inits->v_int_scale_ratio = + dc_fixpt_u2d19(data->ratios.vert) << 5; + + /* DCE6 h_init_luma setting inspired by DCE110 */ + inits->h_init_luma.integer = 1; + + /* DCE6 h_init_chroma setting inspired by DCE110 */ + inits->h_init_chroma.integer = 1; + + v_init = + dc_fixpt_div_int( + dc_fixpt_add( + data->ratios.vert, + dc_fixpt_from_int(data->taps.v_taps + 1)), + 2); + inits->v_init.integer = dc_fixpt_floor(v_init); + inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5; +} +#endif + static void program_scl_ratios_inits( struct dce_transform *xfm_dce, struct scl_ratios_inits *inits) @@ -328,6 +358,36 @@ static void program_scl_ratios_inits( REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); } +#if defined(CONFIG_DRM_AMD_DC_SI) +static void dce60_program_scl_ratios_inits( + struct dce_transform *xfm_dce, + struct sclh_ratios_inits *inits) +{ + + REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, + SCL_H_SCALE_RATIO, inits->h_int_scale_ratio); + + REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, + SCL_V_SCALE_RATIO, inits->v_int_scale_ratio); + + /* DCE6 has SCL_HORZ_FILTER_INIT_RGB_LUMA register */ + REG_SET_2(SCL_HORZ_FILTER_INIT_RGB_LUMA, 0, + SCL_H_INIT_INT_RGB_Y, inits->h_init_luma.integer, + SCL_H_INIT_FRAC_RGB_Y, inits->h_init_luma.fraction); + + /* DCE6 has SCL_HORZ_FILTER_INIT_CHROMA register */ + REG_SET_2(SCL_HORZ_FILTER_INIT_CHROMA, 0, + SCL_H_INIT_INT_CBCR, inits->h_init_chroma.integer, + SCL_H_INIT_FRAC_CBCR, inits->h_init_chroma.fraction); + + REG_SET_2(SCL_VERT_FILTER_INIT, 0, + SCL_V_INIT_INT, inits->v_init.integer, + SCL_V_INIT_FRAC, inits->v_init.fraction); + + REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); +} +#endif + static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) { if (taps == 4) @@ -453,12 +513,14 @@ static void dce60_transform_set_scaler( is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data); if (is_scaling_required) { - /* 3. Calculate and program ratio, filter initialization */ - struct scl_ratios_inits inits = { 0 }; + /* 3. Calculate and program ratio, DCE6 filter initialization */ + struct sclh_ratios_inits inits = { 0 }; - calculate_inits(xfm_dce, data, &inits); + /* DCE6 has specific calculate_inits() function */ + dce60_calculate_inits(xfm_dce, data, &inits); - program_scl_ratios_inits(xfm_dce, &inits); + /* DCE6 has specific program_scl_ratios_inits() function */ + dce60_program_scl_ratios_inits(xfm_dce, &inits); coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); @@ -503,7 +565,7 @@ static void dce60_transform_set_scaler( /* 6. Program the viewport */ program_viewport(xfm_dce, &data->viewport); - /* DCE6 does not have bit to flip to new coefficient memory */ + /* DCE6 has no SCL_COEF_UPDATE_COMPLETE bit to flip to new coefficient memory */ /* DCE6 DATA_FORMAT register does not support ALPHA_EN */ } diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h index 95b28dadc8c5d..cbce194ec7b82 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.h @@ -331,6 +331,14 @@ XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \ XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \ XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT_RGB_LUMA, SCL_H_INIT_INT_RGB_Y, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT_RGB_LUMA, SCL_H_INIT_FRAC_RGB_Y, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT_CHROMA, SCL_H_INIT_INT_CBCR, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_INIT_CHROMA, SCL_H_INIT_FRAC_CBCR, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \ + XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_FILTER_PICK_NEAREST, mask_sh), \ + XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_FILTER_PICK_NEAREST, mask_sh), \ XFM_SF(DC_LB_MEMORY_SPLIT, DC_LB_MEMORY_CONFIG, mask_sh), \ XFM_SF(DC_LB_MEM_SIZE, DC_LB_MEM_SIZE, mask_sh) #endif @@ -497,6 +505,10 @@ type SCL_V_SCALE_RATIO; \ type SCL_H_INIT_INT; \ type SCL_H_INIT_FRAC; \ + type SCL_H_INIT_INT_RGB_Y; \ + type SCL_H_INIT_FRAC_RGB_Y; \ + type SCL_H_INIT_INT_CBCR; \ + type SCL_H_INIT_FRAC_CBCR; \ type SCL_V_INIT_INT; \ type SCL_V_INIT_FRAC; \ type DC_LB_MEMORY_CONFIG; \ @@ -505,6 +517,8 @@ type LB_MEMORY_SIZE; \ type SCL_V_2TAP_HARDCODE_COEF_EN; \ type SCL_H_2TAP_HARDCODE_COEF_EN; \ + type SCL_V_FILTER_PICK_NEAREST; \ + type SCL_H_FILTER_PICK_NEAREST; \ type SCL_COEF_UPDATE_COMPLETE; \ type ALPHA_EN @@ -575,6 +589,10 @@ struct dce_transform_registers { uint32_t SCL_HORZ_FILTER_SCALE_RATIO; uint32_t SCL_VERT_FILTER_SCALE_RATIO; uint32_t SCL_HORZ_FILTER_INIT; +#if defined(CONFIG_DRM_AMD_DC_SI) + uint32_t SCL_HORZ_FILTER_INIT_RGB_LUMA; + uint32_t SCL_HORZ_FILTER_INIT_CHROMA; +#endif uint32_t SCL_VERT_FILTER_INIT; uint32_t SCL_AUTOMATIC_MODE_CONTROL; #if defined(CONFIG_DRM_AMD_DC_SI) @@ -598,6 +616,16 @@ struct scl_ratios_inits { struct init_int_and_frac v_init; }; +#if defined(CONFIG_DRM_AMD_DC_SI) +struct sclh_ratios_inits { + uint32_t h_int_scale_ratio; + uint32_t v_int_scale_ratio; + struct init_int_and_frac h_init_luma; + struct init_int_and_frac h_init_chroma; + struct init_int_and_frac v_init; +}; +#endif + enum ram_filter_type { FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */ FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */ -- GitLab From 167d74fd7dfc18158c116c84565dda24b40473c6 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:40:01 +0200 Subject: [PATCH 0090/1494] drm/amd/display: dce60_hw_sequencer: add DCE6 specific functions (v2) [Why] DCE6 has no bottom_pipe and no Blender HW DCE6 needs 'blank_target' set to false in order to turn on the display DCE6 has a specific dce60_pipe_control_lock() fuction that is a no op [How] Add DCE6 specific functions with needed private dce60_* dependent fuctions Comment DCE6 specific CTRC program visibility implementation Fix a typo in the initial header includes comment 's/DCE8/DCE6/g' Use dce60_apply_ctx_for_surface() in dce60_hw_sequencer_construct Use dce60_pipe_control_lock() in dce60_hw_sequencer_construct v2: add missing return type (Alex) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/dce60/dce60_hw_sequencer.c | 381 +++++++++++++++++- 1 file changed, 379 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c index e30e3510ec4a3..9d8797ac0c985 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c @@ -32,22 +32,399 @@ #include "dce110/dce110_hw_sequencer.h" #include "dce100/dce100_hw_sequencer.h" -/* include DCE8 register header files */ +/* include DCE6 register header files */ #include "dce/dce_6_0_d.h" #include "dce/dce_6_0_sh_mask.h" +#define DC_LOGGER_INIT() + /******************************************************************************* * Private definitions ******************************************************************************/ /***************************PIPE_CONTROL***********************************/ +/* + * Check if FBC can be enabled + */ +static bool dce60_should_enable_fbc(struct dc *dc, + struct dc_state *context, + uint32_t *pipe_idx) +{ + uint32_t i; + struct pipe_ctx *pipe_ctx = NULL; + struct resource_context *res_ctx = &context->res_ctx; + unsigned int underlay_idx = dc->res_pool->underlay_pipe_index; + + + ASSERT(dc->fbc_compressor); + + /* FBC memory should be allocated */ + if (!dc->ctx->fbc_gpu_addr) + return false; + + /* Only supports single display */ + if (context->stream_count != 1) + return false; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (res_ctx->pipe_ctx[i].stream) { + + pipe_ctx = &res_ctx->pipe_ctx[i]; + + if (!pipe_ctx) + continue; + + /* fbc not applicable on underlay pipe */ + if (pipe_ctx->pipe_idx != underlay_idx) { + *pipe_idx = i; + break; + } + } + } + + if (i == dc->res_pool->pipe_count) + return false; + + if (!pipe_ctx->stream->link) + return false; + + /* Only supports eDP */ + if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP) + return false; + + /* PSR should not be enabled */ + if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled) + return false; + + /* Nothing to compress */ + if (!pipe_ctx->plane_state) + return false; + + /* Only for non-linear tiling */ + if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL) + return false; + + return true; +} + +/* + * Enable FBC + */ +static void dce60_enable_fbc( + struct dc *dc, + struct dc_state *context) +{ + uint32_t pipe_idx = 0; + + if (dce60_should_enable_fbc(dc, context, &pipe_idx)) { + /* Program GRPH COMPRESSED ADDRESS and PITCH */ + struct compr_addr_and_pitch_params params = {0, 0, 0}; + struct compressor *compr = dc->fbc_compressor; + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; + + params.source_view_width = pipe_ctx->stream->timing.h_addressable; + params.source_view_height = pipe_ctx->stream->timing.v_addressable; + params.inst = pipe_ctx->stream_res.tg->inst; + compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr; + + compr->funcs->surface_address_and_pitch(compr, ¶ms); + compr->funcs->set_fbc_invalidation_triggers(compr, 1); + + compr->funcs->enable_fbc(compr, ¶ms); + } +} + + +/******************************************************************************* + * Front End programming + ******************************************************************************/ + +static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx) +{ + struct default_adjustment default_adjust = { 0 }; + + default_adjust.force_hw_default = false; + default_adjust.in_color_space = pipe_ctx->plane_state->color_space; + default_adjust.out_color_space = pipe_ctx->stream->output_color_space; + default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW; + default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format; + + /* display color depth */ + default_adjust.color_depth = + pipe_ctx->stream->timing.display_color_depth; + + /* Lb color depth */ + default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default( + pipe_ctx->plane_res.xfm, &default_adjust); +} + +/******************************************************************************* + * In order to turn on surface we will program + * CRTC + * + * DCE6 has no bottom_pipe and no Blender HW + * We need to set 'blank_target' to false in order to turn on the display + * + * |-----------|------------|---------| + * |curr pipe | set_blank | | + * |Surface |blank_target| CRCT | + * |visibility | argument | | + * |-----------|------------|---------| + * | off | true | blank | + * | on | false | unblank | + * |-----------|------------|---------| + * + ******************************************************************************/ +static void dce60_program_surface_visibility(const struct dc *dc, + struct pipe_ctx *pipe_ctx) +{ + bool blank_target = false; + + /* DCE6 has no bottom_pipe and no Blender HW */ + + if (!pipe_ctx->plane_state->visible) + blank_target = true; + + /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */ + pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target); + +} + + +static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4; + + switch (pipe_ctx->plane_res.scl_data.format) { + case PIXEL_FORMAT_ARGB8888: + /* set boarder color to red */ + color->color_r_cr = color_value; + break; + + case PIXEL_FORMAT_ARGB2101010: + /* set boarder color to blue */ + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP8: + /* set boarder color to green */ + color->color_g_y = color_value; + break; + case PIXEL_FORMAT_420BPP10: + /* set boarder color to yellow */ + color->color_g_y = color_value; + color->color_r_cr = color_value; + break; + case PIXEL_FORMAT_FP16: + /* set boarder color to white */ + color->color_r_cr = color_value; + color->color_b_cb = color_value; + color->color_g_y = color_value; + break; + default: + break; + } +} + +static void dce60_program_scaler(const struct dc *dc, + const struct pipe_ctx *pipe_ctx) +{ + struct tg_color color = {0}; + + /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */ + + if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) + dce60_get_surface_visual_confirm_color(pipe_ctx, &color); + else + color_space_to_black_color(dc, + pipe_ctx->stream->output_color_space, + &color); + + pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth( + pipe_ctx->plane_res.xfm, + pipe_ctx->plane_res.scl_data.lb_params.depth, + &pipe_ctx->stream->bit_depth_params); + + if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) { + /* + * The way 420 is packed, 2 channels carry Y component, 1 channel + * alternate between Cb and Cr, so both channels need the pixel + * value for Y + */ + if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + color.color_r_cr = color.color_g_y; + + pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color( + pipe_ctx->stream_res.tg, + &color); + } + + pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm, + &pipe_ctx->plane_res.scl_data); +} + +static void +dce60_program_front_end_for_pipe( + struct dc *dc, struct pipe_ctx *pipe_ctx) +{ + struct mem_input *mi = pipe_ctx->plane_res.mi; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct xfm_grph_csc_adjustment adjust; + struct out_csc_color_matrix tbl_entry; + unsigned int i; + struct dce_hwseq *hws = dc->hwseq; + + DC_LOGGER_INIT(); + memset(&tbl_entry, 0, sizeof(tbl_entry)); + + memset(&adjust, 0, sizeof(adjust)); + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS; + + dce_enable_fe_clock(dc->hwseq, mi->inst, true); + + dce60_set_default_colors(pipe_ctx); + if (pipe_ctx->stream->csc_color_matrix.enable_adjustment + == true) { + tbl_entry.color_space = + pipe_ctx->stream->output_color_space; + + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = + pipe_ctx->stream->csc_color_matrix.matrix[i]; + + pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment + (pipe_ctx->plane_res.xfm, &tbl_entry); + } + + if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) { + adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW; + + for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++) + adjust.temperature_matrix[i] = + pipe_ctx->stream->gamut_remap_matrix.matrix[i]; + } + + pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust); + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; + + dce60_program_scaler(dc, pipe_ctx); + + mi->funcs->mem_input_program_surface_config( + mi, + plane_state->format, + &plane_state->tiling_info, + &plane_state->plane_size, + plane_state->rotation, + NULL, + false); + if (mi->funcs->set_blank) + mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible); + + if (dc->config.gpu_vm_support) + mi->funcs->mem_input_program_pte_vm( + pipe_ctx->plane_res.mi, + plane_state->format, + &plane_state->tiling_info, + plane_state->rotation); + + /* Moved programming gamma from dc to hwss */ + if (pipe_ctx->plane_state->update_flags.bits.full_update || + pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || + pipe_ctx->plane_state->update_flags.bits.gamma_change) + hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); + + if (pipe_ctx->plane_state->update_flags.bits.full_update) + hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); + + DC_LOG_SURFACE( + "Pipe:%d %p: addr hi:0x%x, " + "addr low:0x%x, " + "src: %d, %d, %d," + " %d; dst: %d, %d, %d, %d;" + "clip: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + (void *) pipe_ctx->plane_state, + pipe_ctx->plane_state->address.grph.addr.high_part, + pipe_ctx->plane_state->address.grph.addr.low_part, + pipe_ctx->plane_state->src_rect.x, + pipe_ctx->plane_state->src_rect.y, + pipe_ctx->plane_state->src_rect.width, + pipe_ctx->plane_state->src_rect.height, + pipe_ctx->plane_state->dst_rect.x, + pipe_ctx->plane_state->dst_rect.y, + pipe_ctx->plane_state->dst_rect.width, + pipe_ctx->plane_state->dst_rect.height, + pipe_ctx->plane_state->clip_rect.x, + pipe_ctx->plane_state->clip_rect.y, + pipe_ctx->plane_state->clip_rect.width, + pipe_ctx->plane_state->clip_rect.height); + + DC_LOG_SURFACE( + "Pipe %d: width, height, x, y\n" + "viewport:%d, %d, %d, %d\n" + "recout: %d, %d, %d, %d\n", + pipe_ctx->pipe_idx, + pipe_ctx->plane_res.scl_data.viewport.width, + pipe_ctx->plane_res.scl_data.viewport.height, + pipe_ctx->plane_res.scl_data.viewport.x, + pipe_ctx->plane_res.scl_data.viewport.y, + pipe_ctx->plane_res.scl_data.recout.width, + pipe_ctx->plane_res.scl_data.recout.height, + pipe_ctx->plane_res.scl_data.recout.x, + pipe_ctx->plane_res.scl_data.recout.y); +} + +static void dce60_apply_ctx_for_surface( + struct dc *dc, + const struct dc_stream_state *stream, + int num_planes, + struct dc_state *context) +{ + int i; + + if (num_planes == 0) + return; + + if (dc->fbc_compressor) + dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream != stream) + continue; + + /* Need to allocate mem before program front end for Fiji */ + pipe_ctx->plane_res.mi->funcs->allocate_mem_input( + pipe_ctx->plane_res.mi, + pipe_ctx->stream->timing.h_total, + pipe_ctx->stream->timing.v_total, + pipe_ctx->stream->timing.pix_clk_100hz / 10, + context->stream_count); + + dce60_program_front_end_for_pipe(dc, pipe_ctx); + + dc->hwss.update_plane_addr(dc, pipe_ctx); + + dce60_program_surface_visibility(dc, pipe_ctx); + + } + + if (dc->fbc_compressor) + dce60_enable_fbc(dc, context); +} + void dce60_hw_sequencer_construct(struct dc *dc) { dce110_hw_sequencer_construct(dc); dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; - dc->hwss.pipe_control_lock = dce_pipe_control_lock; + dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface; + dc->hwss.pipe_control_lock = dce60_pipe_control_lock; dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; } -- GitLab From 1bd26c7db150a98ebc13e417341bc4dcf67c0b0d Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sun, 12 Jul 2020 22:54:13 +0200 Subject: [PATCH 0091/1494] drm/amd/display: dce60_hw_sequencer: add DCE6 specific .cursor_lock [Why] kernel WARNING due to use of .cursor_lock = dce_pipe_control_lock inherited by dce110 [How] DCE6 set .cursor_lock = dce60_pipe_control_lock Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c index 9d8797ac0c985..920c7ae29d530 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c @@ -424,6 +424,7 @@ void dce60_hw_sequencer_construct(struct dc *dc) dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating; dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface; + dc->hwss.cursor_lock = dce60_pipe_control_lock; dc->hwss.pipe_control_lock = dce60_pipe_control_lock; dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth; dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth; -- GitLab From 9caf2a1f4e8aeff31124c807a529375451a56899 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 10 Jul 2020 20:45:01 +0200 Subject: [PATCH 0092/1494] drm/amd/display: dce60_timing_generator: add DCE6 specific functions (v2) [Why] DCE6 has CRTC_PREFETCH_EN bit in CRTC_CONTROL register DCE6 has no CRTC_LEGACY_REQUESTOR_EN bit in CRTC_START_LINE_CONTROL register DCE6 has no CRTC_CRC_CNTL register [How] Modify dce60_timing_generator_enable_advanced_request() function Add dce60_configure_crc() function and dce60_is_tg_enabled() kept as static Use dce60_configure_crc() function in dce60_tg_funcs v2: remove unused variable (Alex) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../display/dc/dce60/dce60_timing_generator.c | 55 +++++++++++++------ .../amd/display/dc/inc/hw/clk_mgr_internal.h | 11 ++++ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c index eb9705e9d40a5..fc1af0ff0ca4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c @@ -128,20 +128,12 @@ static void dce60_timing_generator_enable_advanced_request( struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); uint32_t addr = CRTC_REG(mmCRTC_START_LINE_CONTROL); uint32_t value = dm_read_reg(tg->ctx, addr); + /* DCE6 has CRTC_PREFETCH_EN bit in CRTC_CONTROL register */ + uint32_t addr2 = CRTC_REG(mmCRTC_CONTROL); + uint32_t value2 = dm_read_reg(tg->ctx, addr2); - if (enable) { - set_reg_field_value( - value, - 0, - CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } else { - set_reg_field_value( - value, - 1, - CRTC_START_LINE_CONTROL, - CRTC_LEGACY_REQUESTOR_EN); - } + /* DCE6 does not support CRTC_LEGACY_REQUESTOR_EN bit + so here is not possible to set bit based on enable argument */ if ((timing->v_sync_width + timing->v_front_porch) <= 3) { set_reg_field_value( @@ -150,9 +142,9 @@ static void dce60_timing_generator_enable_advanced_request( CRTC_START_LINE_CONTROL, CRTC_ADVANCED_START_LINE_POSITION); set_reg_field_value( - value, + value2, 0, - CRTC_START_LINE_CONTROL, + CRTC_CONTROL, CRTC_PREFETCH_EN); } else { set_reg_field_value( @@ -161,9 +153,9 @@ static void dce60_timing_generator_enable_advanced_request( CRTC_START_LINE_CONTROL, CRTC_ADVANCED_START_LINE_POSITION); set_reg_field_value( - value, + value2, 1, - CRTC_START_LINE_CONTROL, + CRTC_CONTROL, CRTC_PREFETCH_EN); } @@ -180,6 +172,33 @@ static void dce60_timing_generator_enable_advanced_request( CRTC_INTERLACE_START_LINE_EARLY); dm_write_reg(tg->ctx, addr, value); + dm_write_reg(tg->ctx, addr2, value2); +} + +static bool dce60_is_tg_enabled(struct timing_generator *tg) +{ + uint32_t addr = 0; + uint32_t value = 0; + uint32_t field = 0; + struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg); + + addr = CRTC_REG(mmCRTC_CONTROL); + value = dm_read_reg(tg->ctx, addr); + field = get_reg_field_value(value, CRTC_CONTROL, + CRTC_CURRENT_MASTER_EN_STATE); + return field == 1; +} + +bool dce60_configure_crc(struct timing_generator *tg, + const struct crc_params *params) +{ + /* Cannot configure crc on a CRTC that is disabled */ + if (!dce60_is_tg_enabled(tg)) + return false; + + /* DCE6 has no CRTC_CRC_CNTL register, nothing to do */ + + return true; } static const struct timing_generator_funcs dce60_tg_funcs = { @@ -217,7 +236,7 @@ static const struct timing_generator_funcs dce60_tg_funcs = { /* DCE6.0 overrides */ .enable_advanced_request = dce60_timing_generator_enable_advanced_request, - .configure_crc = dce110_configure_crc, + .configure_crc = dce60_configure_crc, .get_crc = dce110_get_crc, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index 4e6e18bbef5d2..ca9eedb643f29 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -88,6 +88,11 @@ enum dentist_divider_range { .DPREFCLK_CNTL = mmDPREFCLK_CNTL, \ .DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL +#if defined(CONFIG_DRM_AMD_DC_SI) +#define CLK_COMMON_REG_LIST_DCE60_BASE() \ + SR(DENTIST_DISPCLK_CNTL) +#endif + #define CLK_COMMON_REG_LIST_DCN_BASE() \ SR(DENTIST_DISPCLK_CNTL) @@ -114,6 +119,12 @@ enum dentist_divider_range { CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh) +#if defined(CONFIG_DRM_AMD_DC_SI) +#define CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \ + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ + CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) +#endif + #define CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh) \ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\ CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh) -- GitLab From 75b4766bad05c4db6e9e568af95712321f57d02e Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Tue, 7 Jul 2020 17:24:56 +0200 Subject: [PATCH 0093/1494] drm/amd/display: dc/dce60: use DCE6 headers (v6) [Why] With all DCE6 specific macros, register, masks in place dce60_resource.c may use them and become independent from DCE8 headers [How] (v1) Changelog: - use DCE6 headers for registers and masks, remove the DC8 headers - remove 7th Display Controller/Encoder register instances (DCE6 has only 6) - use DCE6 specific watermark programming registers (DPG_PIPE_ARBITRATION_CONTROL3) - use DCE6 specific input pixel processing registers shift/mask - use DCE6 specific transform registers shift/mask - use DCE6 specific link encoder registers shift/mask - use DCE6 specific output pixel processing registers shift/mask - use DCE6 specific audio registers shift/mask - use DCE6 specific dmcu registers shift/mask - use DCE6 specific hwseq registers shift/mask - use DCE6 specific mem input registers shift/mask (v2) Changelog: - use DCE6 ad hoc dce60_mem_input_construct() function - use DCE6 ad hoc dce60_transform_construct() function (v3) Changelog: - use DCE6 ad hoc dce60_ipp_construct() function (v4) Changelog: - use DCE6 ad hoc dce60_link_encoder_construct() function (v5) Changelog: - use DCE6 ad hoc dce60_opp_construct() function (v6) Changelog: - use DCE6 ad hoc dce60_audio_create() function Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dce60/dce60_resource.c | 89 +++++++++---------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c index 534db1c4eaa62..5a5a9cb77acbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c @@ -25,8 +25,8 @@ #include <linux/slab.h> -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" +#include "dce/dce_6_0_d.h" +#include "dce/dce_6_0_sh_mask.h" #include "dm_services.h" @@ -73,7 +73,6 @@ #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE -#define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE #endif @@ -91,7 +90,6 @@ #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE - #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE #endif @@ -113,38 +111,38 @@ static const struct dce110_timing_generator_offsets dce60_tg_offsets[] = { { .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmGRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), }, { .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), }, { .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), }, { .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), }, { .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), }, { .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL), .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL), - .dmif = (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL - - mmDPG_WATERMARK_MASK_CONTROL), + .dmif = (mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL3 + - mmDPG_PIPE_ARBITRATION_CONTROL3), } }; @@ -171,16 +169,16 @@ static const struct dce_ipp_registers ipp_regs[] = { }; static const struct dce_ipp_shift ipp_shift = { - IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) + IPP_DCE60_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT) }; static const struct dce_ipp_mask ipp_mask = { - IPP_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) + IPP_DCE60_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; #define transform_regs(id)\ [id] = {\ - XFM_COMMON_REG_LIST_DCE80(id)\ + XFM_COMMON_REG_LIST_DCE60(id)\ } static const struct dce_transform_registers xfm_regs[] = { @@ -193,11 +191,11 @@ static const struct dce_transform_registers xfm_regs[] = { }; static const struct dce_transform_shift xfm_shift = { - XFM_COMMON_MASK_SH_LIST_DCE80(__SHIFT) + XFM_COMMON_MASK_SH_LIST_DCE60(__SHIFT) }; static const struct dce_transform_mask xfm_mask = { - XFM_COMMON_MASK_SH_LIST_DCE80(_MASK) + XFM_COMMON_MASK_SH_LIST_DCE60(_MASK) }; #define aux_regs(id)\ @@ -230,7 +228,7 @@ static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = { #define link_regs(id)\ [id] = {\ - LE_DCE80_REG_LIST(id)\ + LE_DCE60_REG_LIST(id)\ } static const struct dce110_link_enc_registers link_enc_regs[] = { @@ -239,8 +237,7 @@ static const struct dce110_link_enc_registers link_enc_regs[] = { link_regs(2), link_regs(3), link_regs(4), - link_regs(5), - link_regs(6), + link_regs(5) }; #define stream_enc_regs(id)\ @@ -255,8 +252,7 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = { stream_enc_regs(2), stream_enc_regs(3), stream_enc_regs(4), - stream_enc_regs(5), - stream_enc_regs(6) + stream_enc_regs(5) }; static const struct dce_stream_encoder_shift se_shift = { @@ -281,7 +277,7 @@ static const struct dce_panel_cntl_mask panel_cntl_mask = { #define opp_regs(id)\ [id] = {\ - OPP_DCE_80_REG_LIST(id),\ + OPP_DCE_60_REG_LIST(id),\ } static const struct dce_opp_registers opp_regs[] = { @@ -294,11 +290,11 @@ static const struct dce_opp_registers opp_regs[] = { }; static const struct dce_opp_shift opp_shift = { - OPP_COMMON_MASK_SH_LIST_DCE_80(__SHIFT) + OPP_COMMON_MASK_SH_LIST_DCE_60(__SHIFT) }; static const struct dce_opp_mask opp_mask = { - OPP_COMMON_MASK_SH_LIST_DCE_80(_MASK) + OPP_COMMON_MASK_SH_LIST_DCE_60(_MASK) }; static const struct dce110_aux_registers_shift aux_shift = { @@ -336,15 +332,14 @@ static const struct dce_audio_registers audio_regs[] = { audio_regs(3), audio_regs(4), audio_regs(5), - audio_regs(6), }; static const struct dce_audio_shift audio_shift = { - AUD_COMMON_MASK_SH_LIST(__SHIFT) + AUD_DCE60_MASK_SH_LIST(__SHIFT) }; static const struct dce_audio_mask audio_mask = { - AUD_COMMON_MASK_SH_LIST(_MASK) + AUD_DCE60_MASK_SH_LIST(_MASK) }; #define clk_src_regs(id)\ @@ -419,15 +414,15 @@ static const struct dc_plane_cap plane_cap = { }; static const struct dce_dmcu_registers dmcu_regs = { - DMCU_DCE80_REG_LIST() + DMCU_DCE60_REG_LIST() }; static const struct dce_dmcu_shift dmcu_shift = { - DMCU_MASK_SH_LIST_DCE80(__SHIFT) + DMCU_MASK_SH_LIST_DCE60(__SHIFT) }; static const struct dce_dmcu_mask dmcu_mask = { - DMCU_MASK_SH_LIST_DCE80(_MASK) + DMCU_MASK_SH_LIST_DCE60(_MASK) }; static const struct dce_abm_registers abm_regs = { ABM_DCE110_COMMON_REG_LIST() @@ -497,7 +492,7 @@ static void read_dce_straps( static struct audio *create_audio( struct dc_context *ctx, unsigned int inst) { - return dce_audio_create(ctx, inst, + return dce60_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); } @@ -526,7 +521,7 @@ static struct output_pixel_processor *dce60_opp_create( if (!opp) return NULL; - dce110_opp_construct(opp, + dce60_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); return &opp->base; } @@ -618,15 +613,15 @@ static struct stream_encoder *dce60_stream_encoder_create( .reg_name[id] = mm ## block ## id ## _ ## reg_name static const struct dce_hwseq_registers hwseq_reg = { - HWSEQ_DCE8_REG_LIST() + HWSEQ_DCE6_REG_LIST() }; static const struct dce_hwseq_shift hwseq_shift = { - HWSEQ_DCE8_MASK_SH_LIST(__SHIFT) + HWSEQ_DCE6_MASK_SH_LIST(__SHIFT) }; static const struct dce_hwseq_mask hwseq_mask = { - HWSEQ_DCE8_MASK_SH_LIST(_MASK) + HWSEQ_DCE6_MASK_SH_LIST(_MASK) }; static struct dce_hwseq *dce60_hwseq_create( @@ -651,7 +646,7 @@ static const struct resource_create_funcs res_create_funcs = { }; #define mi_inst_regs(id) { \ - MI_DCE8_REG_LIST(id), \ + MI_DCE6_REG_LIST(id), \ .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \ } static const struct dce_mem_input_registers mi_regs[] = { @@ -664,12 +659,12 @@ static const struct dce_mem_input_registers mi_regs[] = { }; static const struct dce_mem_input_shift mi_shifts = { - MI_DCE8_MASK_SH_LIST(__SHIFT), + MI_DCE6_MASK_SH_LIST(__SHIFT), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT }; static const struct dce_mem_input_mask mi_masks = { - MI_DCE8_MASK_SH_LIST(_MASK), + MI_DCE6_MASK_SH_LIST(_MASK), .ENABLE = MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK }; @@ -685,7 +680,7 @@ static struct mem_input *dce60_mem_input_create( return NULL; } - dce_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); + dce60_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks); dce_mi->wa.single_head_rdreq_dmif_limit = 2; return &dce_mi->base; } @@ -706,7 +701,7 @@ static struct transform *dce60_transform_create( if (!transform) return NULL; - dce_transform_construct(transform, ctx, inst, + dce60_transform_construct(transform, ctx, inst, &xfm_regs[inst], &xfm_shift, &xfm_mask); transform->prescaler_on = false; return &transform->base; @@ -732,7 +727,7 @@ struct link_encoder *dce60_link_encoder_create( link_regs_id = map_transmitter_id_to_phy_instance(enc_init_data->transmitter); - dce110_link_encoder_construct(enc110, + dce60_link_encoder_construct(enc110, enc_init_data, &link_enc_feature, &link_enc_regs[link_regs_id], @@ -798,7 +793,7 @@ static struct input_pixel_processor *dce60_ipp_create( return NULL; } - dce_ipp_construct(ipp, ctx, inst, + dce60_ipp_construct(ipp, ctx, inst, &ipp_regs[inst], &ipp_shift, &ipp_mask); return &ipp->base; } -- GitLab From f784112f0126a8d9cd4d92878dc76796b5eba11e Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Thu, 16 Jul 2020 20:54:28 +0200 Subject: [PATCH 0094/1494] drm/amd/display: create plane rotation property for Bonaire and later [Why] DCE6 chipsets do not support HW rotation [How] rotation property is created for Bonaire and later Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 149da893b7142..5109ee032b726 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6009,8 +6009,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; - drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, - supported_rotations); + if (dm->adev->asic_type >= CHIP_BONAIRE) + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + supported_rotations); drm_plane_helper_add(plane, &dm_plane_helper_funcs); -- GitLab From 31ed1b5dff46fc5c9347338b7e65973f34e9713f Mon Sep 17 00:00:00 2001 From: Paul Menzel <pmenzel@molgen.mpg.de> Date: Fri, 3 Jul 2020 16:29:37 +0200 Subject: [PATCH 0095/1494] kernel/params.c: Align last argument with a tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The second and third arguments are aligned with tabs, so do the same for the fourth. Cc: linux-kernel@vger.kernel.org Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://lore.kernel.org/patchwork/patch/1267600/ --- kernel/params.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/params.c b/kernel/params.c index 8e56f8b12d8f7..111eee82b9990 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -233,14 +233,14 @@ char *parse_args(const char *doing, EXPORT_SYMBOL(param_ops_##name) -STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); -STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); -STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); -STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); -STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); -STANDARD_PARAM_DEF(long, long, "%li", kstrtol); -STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); -STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); +STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); +STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); +STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); +STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); +STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); +STANDARD_PARAM_DEF(long, long, "%li", kstrtol); +STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); +STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); int param_set_charp(const char *val, const struct kernel_param *kp) { -- GitLab From 7d8365771ffb0edc336f2cd45e96ef8214a83dca Mon Sep 17 00:00:00 2001 From: Paul Menzel <pmenzel@molgen.mpg.de> Date: Fri, 3 Jul 2020 16:29:38 +0200 Subject: [PATCH 0096/1494] moduleparams: Add hexint type parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For bitmasks printing values in hex is more convenient. Prefix with `0x` to make it clear, that it’s a hex value, and pad it out. Using the helper for `amdgpu.ppfeaturemask`, it will look like below. Before: $ more /sys/module/amdgpu/parameters/ppfeaturemask 4294950911 After: $ more /sys/module/amdgpu/parameters/ppfeaturemask 0xffffbfff Cc: linux-kernel@vger.kernel.org Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/374726/ --- include/linux/moduleparam.h | 7 ++++++- kernel/params.c | 17 +++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 3ef917ff09647..cff7261e98bbe 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -118,7 +118,7 @@ struct kparam_array * you can create your own by defining those variables. * * Standard types are: - * byte, short, ushort, int, uint, long, ulong + * byte, hexint, short, ushort, int, uint, long, ulong * charp: a character pointer * bool: a bool, values 0/1, y/n, Y/N. * invbool: the above, only sense-reversed (N = true). @@ -448,6 +448,11 @@ extern int param_set_ullong(const char *val, const struct kernel_param *kp); extern int param_get_ullong(char *buffer, const struct kernel_param *kp); #define param_check_ullong(name, p) __param_check(name, p, unsigned long long) +extern const struct kernel_param_ops param_ops_hexint; +extern int param_set_hexint(const char *val, const struct kernel_param *kp); +extern int param_get_hexint(char *buffer, const struct kernel_param *kp); +#define param_check_hexint(name, p) param_check_uint(name, p) + extern const struct kernel_param_ops param_ops_charp; extern int param_set_charp(const char *val, const struct kernel_param *kp); extern int param_get_charp(char *buffer, const struct kernel_param *kp); diff --git a/kernel/params.c b/kernel/params.c index 111eee82b9990..3835fb82c64bd 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -233,14 +233,15 @@ char *parse_args(const char *doing, EXPORT_SYMBOL(param_ops_##name) -STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); -STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); -STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); -STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); -STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); -STANDARD_PARAM_DEF(long, long, "%li", kstrtol); -STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); -STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); +STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8); +STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16); +STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16); +STANDARD_PARAM_DEF(int, int, "%i", kstrtoint); +STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint); +STANDARD_PARAM_DEF(long, long, "%li", kstrtol); +STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul); +STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull); +STANDARD_PARAM_DEF(hexint, unsigned int, "%#08x", kstrtouint); int param_set_charp(const char *val, const struct kernel_param *kp) { -- GitLab From 7427a7a0b3b8f66ea45472a9a37b79689ed8c3b3 Mon Sep 17 00:00:00 2001 From: Paul Menzel <pmenzel@molgen.mpg.de> Date: Fri, 3 Jul 2020 16:29:39 +0200 Subject: [PATCH 0097/1494] drm/amdgpu: Change type of module param `ppfeaturemask` to hexint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The newly added hexint helper is more convenient for bitmasks. Before: $ more /sys/module/amdgpu/parameters/ppfeaturemask 4294950911 After: $ more /sys/module/amdgpu/parameters/ppfeaturemask 0xffffbfff Cc: amd-gfx@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Paul Menzel <pmenzel@molgen.mpg.de> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/374724/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 126e74758a342..5c4263335cbad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -391,12 +391,12 @@ MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); /** - * DOC: ppfeaturemask (uint) + * DOC: ppfeaturemask (hexint) * Override power features enabled. See enum PP_FEATURE_MASK in drivers/gpu/drm/amd/include/amd_shared.h. * The default is the current set of stable power features. */ MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); -module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, uint, 0444); +module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, hexint, 0444); /** * DOC: forcelongtraining (uint) -- GitLab From d59bc6324208e427d141826d26408b193d522244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 10:58:12 +0200 Subject: [PATCH 0098/1494] drm/ttm: fix pipelined gutting for evictions v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can't pipeline that during eviction because the memory needs to be available immediately. v2: fix how we cleanup the BOs resources Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Tested-by: Alex Sierra <alex.sierra@amd.com> Link: https://patchwork.freedesktop.org/patch/379039/ --- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 0768a054a9166..469aa93ea3175 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -652,8 +652,12 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, placement.num_busy_placement = 0; bdev->driver->evict_flags(bo, &placement); - if (!placement.num_placement && !placement.num_busy_placement) - return ttm_bo_pipeline_gutting(bo); + if (!placement.num_placement && !placement.num_busy_placement) { + ttm_bo_wait(bo, false, false); + + ttm_bo_cleanup_memtype_use(bo); + return 0; + } evict_mem = bo->mem; evict_mem.mm_node = NULL; -- GitLab From 64200c468fb0a3ab88033f6b90ea4a576ae6a1e0 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Fri, 5 Oct 2018 00:00:17 +0200 Subject: [PATCH 0099/1494] drm/amdgpu: enable DC support for SI parts (v2) [Why] amdgpu_device.c requires changes for SI chipsets support si.c require changes for Display Manager IP block enabling [How] amdgpu_device.c: add SI families in amdgpu_device_asic_has_dc_support() si.c: changes in si_set_ip_blocks() for Display Manager IP blocks enablement (v1) NOTE: As per Kaveri and older amdgpu.dc=1 kernel cmdline is required (v2) fix for bc011f9350 ("drm/amdgpu: Change SI/CI gfx/sdma/smu init sequence") remove CHIP_HAINAN support since it does not have physical DCE6 module Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/si.c | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 62ecac97fbd2d..638c2cc426c15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2775,6 +2775,12 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) { switch (asic_type) { #if defined(CONFIG_DRM_AMD_DC) +#if defined(CONFIG_DRM_AMD_DC_SI) + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + case CHIP_OLAND: +#endif case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 1b449291f0687..5a112c7a35ca5 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -52,6 +52,8 @@ #include "bif/bif_3_0_d.h" #include "bif/bif_3_0_sh_mask.h" +#include "amdgpu_dm.h" + static const u32 tahiti_golden_registers[] = { mmAZALIA_SCLK_CONTROL, 0x00000030, 0x00000011, @@ -2546,6 +2548,10 @@ int si_set_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &si_smu_ip_block); if (adev->enable_virtual_display) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_device_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_device_ip_block_add(adev, &dce_v6_0_ip_block); amdgpu_device_ip_block_add(adev, &uvd_v3_1_ip_block); @@ -2560,6 +2566,10 @@ int si_set_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &si_smu_ip_block); if (adev->enable_virtual_display) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); +#if defined(CONFIG_DRM_AMD_DC) && defined(CONFIG_DRM_AMD_DC_SI) + else if (amdgpu_device_has_dc_support(adev)) + amdgpu_device_ip_block_add(adev, &dm_ip_block); +#endif else amdgpu_device_ip_block_add(adev, &dce_v6_4_ip_block); amdgpu_device_ip_block_add(adev, &uvd_v3_1_ip_block); -- GitLab From 5963cdde1acf6b81c62bf6d3bdae723139bf8138 Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Sun, 14 Oct 2018 20:51:29 +0200 Subject: [PATCH 0100/1494] drm/amd/display: enable SI support in the Kconfig (v2) [Why] All DCE6 specific code changes are guarded by CONFIG_DRM_AMD_DC_SI Kconfig option [How] (v1) CONFIG_DRM_AMD_DC_SI configuration option is added, default setting is disabled (v2) Hainan is not supported, description updated accordingly Tested with HD7750 (Cape Verde) and HD7950 (Tahiti) Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 34ae4f3a32f4c..77569097a480a 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -31,6 +31,14 @@ config DRM_AMD_DC_HDCP help Choose this option if you want to support HDCP authentication. +config DRM_AMD_DC_SI + bool "AMD DC support for Southern Islands ASICs" + default n + help + Choose this option to enable new AMD DC support for SI asics + by default. This includes Tahiti, Pitcairn, Cape Verde, Oland. + Hainan is not supported by AMD DC and it has no physical DCE6. + config DEBUG_KERNEL_DC bool "Enable kgdb break in DC" depends on DRM_AMD_DC -- GitLab From 6cd3c6798aac0d1a53d1426e1cfa0432cce51486 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 27 Jul 2020 10:35:07 -0400 Subject: [PATCH 0101/1494] drm/amdgpu/si: initial support for GPU reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from radeon. Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/si.c | 92 ++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 5a112c7a35ca5..e330884edd196 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1217,10 +1217,98 @@ static bool si_read_bios_from_rom(struct amdgpu_device *adev, return true; } -//xxx: not implemented +static void si_set_clk_bypass_mode(struct amdgpu_device *adev) +{ + u32 tmp, i; + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_BYPASS_EN; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL_2); + tmp |= SPLL_CTLREQ_CHG; + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(SPLL_STATUS) & SPLL_CHG_STATUS) + break; + udelay(1); + } + + tmp = RREG32(CG_SPLL_FUNC_CNTL_2); + tmp &= ~(SPLL_CTLREQ_CHG | SCLK_MUX_UPDATE); + WREG32(CG_SPLL_FUNC_CNTL_2, tmp); + + tmp = RREG32(MPLL_CNTL_MODE); + tmp &= ~MPLL_MCLK_SEL; + WREG32(MPLL_CNTL_MODE, tmp); +} + +static void si_spll_powerdown(struct amdgpu_device *adev) +{ + u32 tmp; + + tmp = RREG32(SPLL_CNTL_MODE); + tmp |= SPLL_SW_DIR_CONTROL; + WREG32(SPLL_CNTL_MODE, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_RESET; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(CG_SPLL_FUNC_CNTL); + tmp |= SPLL_SLEEP; + WREG32(CG_SPLL_FUNC_CNTL, tmp); + + tmp = RREG32(SPLL_CNTL_MODE); + tmp &= ~SPLL_SW_DIR_CONTROL; + WREG32(SPLL_CNTL_MODE, tmp); +} + +static int si_gpu_pci_config_reset(struct amdgpu_device *adev) +{ + u32 i; + int r = -EINVAL; + + dev_info(adev->dev, "GPU pci config reset\n"); + + /* set mclk/sclk to bypass */ + si_set_clk_bypass_mode(adev); + /* powerdown spll */ + si_spll_powerdown(adev); + /* disable BM */ + pci_clear_master(adev->pdev); + /* reset */ + amdgpu_device_pci_config_reset(adev); + + udelay(100); + + /* wait for asic to come out of reset */ + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(mmCONFIG_MEMSIZE) != 0xffffffff) { + /* enable BM */ + pci_set_master(adev->pdev); + adev->has_hw_reset = true; + r = 0; + break; + } + udelay(1); + } + + return r; +} + static int si_asic_reset(struct amdgpu_device *adev) { - return 0; + int r; + + amdgpu_atombios_scratch_regs_engine_hung(adev, true); + + r = si_gpu_pci_config_reset(adev); + + amdgpu_atombios_scratch_regs_engine_hung(adev, false); + + return r; } static bool si_asic_supports_baco(struct amdgpu_device *adev) -- GitLab From fcf863ec07688a5242b75b032bad3f0e3581d68d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:33 +0300 Subject: [PATCH 0102/1494] drm: mxsfb: Remove fbdev leftovers Commit 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()") replaced fbdev handling with drm_fbdev_generic_setup() but left inclusion of the drm/drm_fb_cma_helper.h header. Remove it. Fixes: 8e93f1028d74 ("drm/mxsfb: Use drm_fbdev_generic_setup()") Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-2-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 508764fccd27d..79cd2511a86b3 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -24,7 +24,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -- GitLab From c42001e357f7de11e882f54461be27757a7fe51a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:34 +0300 Subject: [PATCH 0103/1494] drm: mxsfb: Use drm_panel_bridge Replace the manual connector implementation based on drm_panel with the drm_panel_bridge helper. This simplifies the mxsfb driver by removing connector-related code, and standardizing all pipeline control operations on bridges. A hack is needed to get hold of the connector, as that's our only source of bus flags and formats for now. As soon as the bridge API provides us with that information this can be fixed. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-3-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/Kconfig | 1 + drivers/gpu/drm/mxsfb/Makefile | 2 +- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 105 ++++++++++++++---------------- drivers/gpu/drm/mxsfb/mxsfb_drv.h | 5 +- drivers/gpu/drm/mxsfb/mxsfb_out.c | 99 ---------------------------- 5 files changed, 55 insertions(+), 157 deletions(-) delete mode 100644 drivers/gpu/drm/mxsfb/mxsfb_out.c diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 0dca8f27169e9..e43b326e91474 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -13,6 +13,7 @@ config DRM_MXSFB select DRM_KMS_FB_HELPER select DRM_KMS_CMA_HELPER select DRM_PANEL + select DRM_PANEL_BRIDGE help Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB LCD controller. diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile index ff6e358088fa5..811584e54ad16 100644 --- a/drivers/gpu/drm/mxsfb/Makefile +++ b/drivers/gpu/drm/mxsfb/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o +mxsfb-y := mxsfb_drv.o mxsfb_crtc.o obj-$(CONFIG_DRM_MXSFB) += mxsfb.o diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 79cd2511a86b3..689f50b1ef687 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -29,7 +29,6 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_irq.h> #include <drm/drm_of.h> -#include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> @@ -105,29 +104,11 @@ static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct drm_connector *connector; struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); struct drm_device *drm = pipe->plane.dev; - if (!mxsfb->connector) { - list_for_each_entry(connector, - &drm->mode_config.connector_list, - head) - if (connector->encoder == &mxsfb->pipe.encoder) { - mxsfb->connector = connector; - break; - } - } - - if (!mxsfb->connector) { - dev_warn(drm->dev, "No connector attached, using default\n"); - mxsfb->connector = &mxsfb->panel_connector; - } - pm_runtime_get_sync(drm->dev); - drm_panel_prepare(mxsfb->panel); mxsfb_crtc_enable(mxsfb); - drm_panel_enable(mxsfb->panel); } static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe) @@ -137,9 +118,7 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe) struct drm_crtc *crtc = &pipe->crtc; struct drm_pending_vblank_event *event; - drm_panel_disable(mxsfb->panel); mxsfb_crtc_disable(mxsfb); - drm_panel_unprepare(mxsfb->panel); pm_runtime_put_sync(drm->dev); spin_lock_irq(&drm->event_lock); @@ -149,9 +128,6 @@ static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe) drm_crtc_send_vblank_event(crtc, event); } spin_unlock_irq(&drm->event_lock); - - if (mxsfb->connector != &mxsfb->panel_connector) - mxsfb->connector = NULL; } static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe, @@ -195,6 +171,49 @@ static struct drm_simple_display_pipe_funcs mxsfb_funcs = { .disable_vblank = mxsfb_pipe_disable_vblank, }; +static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb) +{ + struct drm_device *drm = mxsfb->drm; + struct drm_connector_list_iter iter; + struct drm_panel *panel; + struct drm_bridge *bridge; + int ret; + + ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &panel, + &bridge); + if (ret) + return ret; + + if (panel) { + bridge = devm_drm_panel_bridge_add_typed(drm->dev, panel, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(bridge)) + return PTR_ERR(bridge); + } + + if (!bridge) + return -ENODEV; + + ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge); + if (ret) { + DRM_DEV_ERROR(drm->dev, + "failed to attach bridge: %d\n", ret); + return ret; + } + + mxsfb->bridge = bridge; + + /* + * Get hold of the connector. This is a bit of a hack, until the bridge + * API gives us bus flags and formats. + */ + drm_connector_list_iter_begin(drm, &iter); + mxsfb->connector = drm_connector_list_iter_next(&iter); + drm_connector_list_iter_end(&iter); + + return 0; +} + static int mxsfb_load(struct drm_device *drm) { struct platform_device *pdev = to_platform_device(drm->dev); @@ -206,6 +225,7 @@ static int mxsfb_load(struct drm_device *drm) if (!mxsfb) return -ENOMEM; + mxsfb->drm = drm; drm->dev_private = mxsfb; mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; @@ -241,41 +261,18 @@ static int mxsfb_load(struct drm_device *drm) /* Modeset init */ drm_mode_config_init(drm); - ret = mxsfb_create_output(drm); - if (ret < 0) { - dev_err(drm->dev, "Failed to create outputs\n"); - goto err_vblank; - } - ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs, mxsfb_formats, ARRAY_SIZE(mxsfb_formats), - mxsfb_modifiers, mxsfb->connector); + mxsfb_modifiers, NULL); if (ret < 0) { dev_err(drm->dev, "Cannot setup simple display pipe\n"); goto err_vblank; } - /* - * Attach panel only if there is one. - * If there is no panel attach, it must be a bridge. In this case, we - * need a reference to its connector for a proper initialization. - * We will do this check in pipe->enable(), since the connector won't - * be attached to an encoder until then. - */ - - if (mxsfb->panel) { - ret = drm_panel_attach(mxsfb->panel, mxsfb->connector); - if (ret) { - dev_err(drm->dev, "Cannot connect panel: %d\n", ret); - goto err_vblank; - } - } else if (mxsfb->bridge) { - ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, - mxsfb->bridge); - if (ret) { - dev_err(drm->dev, "Cannot connect bridge: %d\n", ret); - goto err_vblank; - } + ret = mxsfb_attach_bridge(mxsfb); + if (ret) { + dev_err(drm->dev, "Cannot connect bridge: %d\n", ret); + goto err_vblank; } drm->mode_config.min_width = MXSFB_MIN_XRES; @@ -293,7 +290,7 @@ static int mxsfb_load(struct drm_device *drm) if (ret < 0) { dev_err(drm->dev, "Failed to install IRQ handler\n"); - goto err_irq; + goto err_vblank; } drm_kms_helper_poll_init(drm); @@ -304,8 +301,6 @@ static int mxsfb_load(struct drm_device *drm) return 0; -err_irq: - drm_panel_detach(mxsfb->panel); err_vblank: pm_runtime_disable(drm->dev); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index 0b65b5194a9cc..0e3e5a63bbf9f 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -8,6 +8,8 @@ #ifndef __MXSFB_DRV_H__ #define __MXSFB_DRV_H__ +struct drm_device; + struct mxsfb_devdata { unsigned int transfer_count; unsigned int cur_buf; @@ -26,10 +28,9 @@ struct mxsfb_drm_private { struct clk *clk_axi; struct clk *clk_disp_axi; + struct drm_device *drm; struct drm_simple_display_pipe pipe; - struct drm_connector panel_connector; struct drm_connector *connector; - struct drm_panel *panel; struct drm_bridge *bridge; }; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c deleted file mode 100644 index 9eca1605d11d6..0000000000000 --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2016 Marek Vasut <marex@denx.de> - */ - -#include <linux/of_graph.h> - -#include <drm/drm_atomic.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> - -#include "mxsfb_drv.h" - -static struct mxsfb_drm_private * -drm_connector_to_mxsfb_drm_private(struct drm_connector *connector) -{ - return container_of(connector, struct mxsfb_drm_private, - panel_connector); -} - -static int mxsfb_panel_get_modes(struct drm_connector *connector) -{ - struct mxsfb_drm_private *mxsfb = - drm_connector_to_mxsfb_drm_private(connector); - - if (mxsfb->panel) - return drm_panel_get_modes(mxsfb->panel, connector); - - return 0; -} - -static const struct -drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = { - .get_modes = mxsfb_panel_get_modes, -}; - -static enum drm_connector_status -mxsfb_panel_connector_detect(struct drm_connector *connector, bool force) -{ - struct mxsfb_drm_private *mxsfb = - drm_connector_to_mxsfb_drm_private(connector); - - if (mxsfb->panel) - return connector_status_connected; - - return connector_status_disconnected; -} - -static void mxsfb_panel_connector_destroy(struct drm_connector *connector) -{ - struct mxsfb_drm_private *mxsfb = - drm_connector_to_mxsfb_drm_private(connector); - - if (mxsfb->panel) - drm_panel_detach(mxsfb->panel); - - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static const struct drm_connector_funcs mxsfb_panel_connector_funcs = { - .detect = mxsfb_panel_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = mxsfb_panel_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, -}; - -int mxsfb_create_output(struct drm_device *drm) -{ - struct mxsfb_drm_private *mxsfb = drm->dev_private; - int ret; - - ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, - &mxsfb->panel, &mxsfb->bridge); - if (ret) - return ret; - - if (mxsfb->panel) { - mxsfb->connector = &mxsfb->panel_connector; - mxsfb->connector->dpms = DRM_MODE_DPMS_OFF; - mxsfb->connector->polled = 0; - drm_connector_helper_add(mxsfb->connector, - &mxsfb_panel_connector_helper_funcs); - ret = drm_connector_init(drm, mxsfb->connector, - &mxsfb_panel_connector_funcs, - DRM_MODE_CONNECTOR_Unknown); - } - - return ret; -} -- GitLab From 8c6619ff22113666b112cace7e4e8d872e09dff3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:35 +0300 Subject: [PATCH 0104/1494] drm: mxsfb: Use BIT() macro to define register bitfields Using BIT() is preferred over manual shifts as it's more readable, handles the 1 << 31 case properly, and avoids other mistakes as shown by the DEBUG0_HSYNC and DEBUG0_VSYNC bits (that are currently unused). Use it. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-4-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_regs.h | 56 +++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 932d7ea08fd5c..713d8f8301353 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h @@ -28,51 +28,51 @@ #define LCDC_V4_DEBUG0 0x1d0 #define LCDC_V3_DEBUG0 0x1f0 -#define CTRL_SFTRST (1 << 31) -#define CTRL_CLKGATE (1 << 30) -#define CTRL_BYPASS_COUNT (1 << 19) -#define CTRL_VSYNC_MODE (1 << 18) -#define CTRL_DOTCLK_MODE (1 << 17) -#define CTRL_DATA_SELECT (1 << 16) +#define CTRL_SFTRST BIT(31) +#define CTRL_CLKGATE BIT(30) +#define CTRL_BYPASS_COUNT BIT(19) +#define CTRL_VSYNC_MODE BIT(18) +#define CTRL_DOTCLK_MODE BIT(17) +#define CTRL_DATA_SELECT BIT(16) #define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10) #define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3) #define CTRL_BUS_WIDTH_MASK (0x3 << 10) #define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8) #define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3) -#define CTRL_MASTER (1 << 5) -#define CTRL_DF16 (1 << 3) -#define CTRL_DF18 (1 << 2) -#define CTRL_DF24 (1 << 1) -#define CTRL_RUN (1 << 0) +#define CTRL_MASTER BIT(5) +#define CTRL_DF16 BIT(3) +#define CTRL_DF18 BIT(2) +#define CTRL_DF24 BIT(1) +#define CTRL_RUN BIT(0) -#define CTRL1_FIFO_CLEAR (1 << 21) +#define CTRL1_FIFO_CLEAR BIT(21) #define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16) #define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf) -#define CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) -#define CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) +#define CTRL1_CUR_FRAME_DONE_IRQ_EN BIT(13) +#define CTRL1_CUR_FRAME_DONE_IRQ BIT(9) #define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) #define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) #define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff) #define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff) -#define VDCTRL0_ENABLE_PRESENT (1 << 28) -#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27) -#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26) -#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25) -#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24) -#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) -#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) -#define VDCTRL0_HALF_LINE (1 << 19) -#define VDCTRL0_HALF_LINE_MODE (1 << 18) +#define VDCTRL0_ENABLE_PRESENT BIT(28) +#define VDCTRL0_VSYNC_ACT_HIGH BIT(27) +#define VDCTRL0_HSYNC_ACT_HIGH BIT(26) +#define VDCTRL0_DOTCLK_ACT_FALLING BIT(25) +#define VDCTRL0_ENABLE_ACT_HIGH BIT(24) +#define VDCTRL0_VSYNC_PERIOD_UNIT BIT(21) +#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT BIT(20) +#define VDCTRL0_HALF_LINE BIT(19) +#define VDCTRL0_HALF_LINE_MODE BIT(18) #define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) #define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) #define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff) #define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff) -#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) -#define VDCTRL3_VSYNC_ONLY (1 << 28) +#define VDCTRL3_MUX_SYNC_SIGNALS BIT(29) +#define VDCTRL3_VSYNC_ONLY BIT(28) #define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16) #define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff) #define SET_VERT_WAIT_CNT(x) ((x) & 0xffff) @@ -80,11 +80,11 @@ #define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */ #define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */ -#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18) +#define VDCTRL4_SYNC_SIGNALS_ON BIT(18) #define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff) -#define DEBUG0_HSYNC (1 < 26) -#define DEBUG0_VSYNC (1 < 25) +#define DEBUG0_HSYNC BIT(26) +#define DEBUG0_VSYNC BIT(25) #define MXSFB_MIN_XRES 120 #define MXSFB_MIN_YRES 120 -- GitLab From 92000371c8294136accc2997cba89dff8c0bc9f5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:36 +0300 Subject: [PATCH 0105/1494] drm: mxsfb: Remove unused macros from mxsfb_regs.h mxsfb_regs.h defines macros related to register bits. Some of them are not used and don't clearly map to any particular register, so their purpose isn't known. Remove them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-5-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_regs.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 713d8f8301353..78e6cb754712b 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h @@ -91,17 +91,9 @@ #define MXSFB_MAX_XRES 0xffff #define MXSFB_MAX_YRES 0xffff -#define RED 0 -#define GREEN 1 -#define BLUE 2 -#define TRANSP 3 - #define STMLCDIF_8BIT 1 /* pixel data bus to the display is of 8 bit width */ #define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */ #define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */ #define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */ -#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6) -#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negative edge sampling */ - #endif /* __MXSFB_REGS_H__ */ -- GitLab From 8a460068494a536e3d544dc4778d3c9d4081c504 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:37 +0300 Subject: [PATCH 0106/1494] drm: mxsfb: Clarify format and bus width configuration Replace the convoluted way to set the format and bus width through difficult to read macros with more explicit ones. Also remove the outdated comment related to the limitations on bus width setting as it doesn't apply anymore (the bus width can be specified through the display_info bus format). Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-6-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++++------------ drivers/gpu/drm/mxsfb/mxsfb_regs.h | 17 ++++++++--------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index b69ace8bf526f..8b6339316929f 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -52,13 +52,6 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER; - /* - * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to - * match the selected mode here. This differs from the original - * MXSFB driver, which had the option to configure the bus width - * to arbitrary value. This limitation should not pose an issue. - */ - /* CTRL1 contains IRQ config and status bits, preserve those. */ ctrl1 = readl(mxsfb->base + LCDC_CTRL1); ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ; @@ -66,12 +59,12 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) switch (format) { case DRM_FORMAT_RGB565: dev_dbg(drm->dev, "Setting up RGB565 mode\n"); - ctrl |= CTRL_SET_WORD_LENGTH(0); + ctrl |= CTRL_WORD_LENGTH_16; ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf); break; case DRM_FORMAT_XRGB8888: dev_dbg(drm->dev, "Setting up XRGB8888 mode\n"); - ctrl |= CTRL_SET_WORD_LENGTH(3); + ctrl |= CTRL_WORD_LENGTH_24; /* Do not use packed pixels = one pixel per word instead. */ ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7); break; @@ -104,13 +97,13 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb) reg &= ~CTRL_BUS_WIDTH_MASK; switch (bus_format) { case MEDIA_BUS_FMT_RGB565_1X16: - reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT); + reg |= CTRL_BUS_WIDTH_16; break; case MEDIA_BUS_FMT_RGB666_1X18: - reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT); + reg |= CTRL_BUS_WIDTH_18; break; case MEDIA_BUS_FMT_RGB888_1X24: - reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT); + reg |= CTRL_BUS_WIDTH_24; break; default: dev_err(drm->dev, "Unknown media bus format %d\n", bus_format); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 78e6cb754712b..8ebb52bb1b461 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h @@ -34,11 +34,15 @@ #define CTRL_VSYNC_MODE BIT(18) #define CTRL_DOTCLK_MODE BIT(17) #define CTRL_DATA_SELECT BIT(16) -#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10) -#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3) +#define CTRL_BUS_WIDTH_16 (0 << 10) +#define CTRL_BUS_WIDTH_8 (1 << 10) +#define CTRL_BUS_WIDTH_18 (2 << 10) +#define CTRL_BUS_WIDTH_24 (3 << 10) #define CTRL_BUS_WIDTH_MASK (0x3 << 10) -#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8) -#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3) +#define CTRL_WORD_LENGTH_16 (0 << 8) +#define CTRL_WORD_LENGTH_8 (1 << 8) +#define CTRL_WORD_LENGTH_18 (2 << 8) +#define CTRL_WORD_LENGTH_24 (3 << 8) #define CTRL_MASTER BIT(5) #define CTRL_DF16 BIT(3) #define CTRL_DF18 BIT(2) @@ -91,9 +95,4 @@ #define MXSFB_MAX_XRES 0xffff #define MXSFB_MAX_YRES 0xffff -#define STMLCDIF_8BIT 1 /* pixel data bus to the display is of 8 bit width */ -#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */ -#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */ -#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */ - #endif /* __MXSFB_REGS_H__ */ -- GitLab From f14fec8481ce64e9c544770d8977e8c8efab4a11 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:38 +0300 Subject: [PATCH 0107/1494] drm: mxsfb: Pass mxsfb_drm_private pointer to mxsfb_reset_block() The mxsfb_reset_block() function isn't special, pass it the mxsfb_drm_private pointer instead of a pointer to the base address. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-7-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 8b6339316929f..be60c4021e2fb 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -166,21 +166,21 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT); } -static int mxsfb_reset_block(void __iomem *reset_addr) +static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb) { int ret; - ret = clear_poll_bit(reset_addr, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST); if (ret) return ret; - writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); + writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR); - ret = clear_poll_bit(reset_addr, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST); if (ret) return ret; - return clear_poll_bit(reset_addr, MODULE_CLKGATE); + return clear_poll_bit(mxsfb->base, MODULE_CLKGATE); } static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) @@ -213,7 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) */ /* Mandatory eLCDIF reset as per the Reference Manual */ - err = mxsfb_reset_block(mxsfb->base); + err = mxsfb_reset_block(mxsfb); if (err) return; -- GitLab From 7865cd5aae2267b8b1efd1019279b9a6e1a11941 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:39 +0300 Subject: [PATCH 0108/1494] drm: mxsfb: Use LCDC_CTRL register name explicitly The LCDC_CTRL register is located at address 0x0000. Some of the accesses to the register simply use the mxsfb->base address. Reference the LCDC_CTRL register explicitly instead to clarify the code. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-8-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index be60c4021e2fb..722bd9b4f5f9a 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -170,17 +170,17 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb) { int ret; - ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST); if (ret) return ret; - writel(MODULE_CLKGATE, mxsfb->base + MXS_CLR_ADDR); + writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR); - ret = clear_poll_bit(mxsfb->base, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST); if (ret) return ret; - return clear_poll_bit(mxsfb->base, MODULE_CLKGATE); + return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE); } static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) -- GitLab From eb28c5cee2a8c44f80b0a35b8bc8ba2924fcb87d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:40 +0300 Subject: [PATCH 0109/1494] drm: mxsfb: Remove register definitions from mxsfb_crtc.c mxsfb_crtc.c defines several macros related to register addresses and bit, which duplicates macros from mxsfb_regs.h. Use the macros from mxsfb_regs.h instead and remove them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-9-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 722bd9b4f5f9a..aef72adabf417 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -29,10 +29,6 @@ #include "mxsfb_drv.h" #include "mxsfb_regs.h" -#define MXS_SET_ADDR 0x4 -#define MXS_CLR_ADDR 0x8 -#define MODULE_CLKGATE BIT(30) -#define MODULE_SFTRST BIT(31) /* 1 second delay should be plenty of time for block reset */ #define RESET_TIMEOUT 1000000 @@ -162,7 +158,7 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) { u32 reg; - writel(mask, addr + MXS_CLR_ADDR); + writel(mask, addr + REG_CLR); return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT); } @@ -170,17 +166,17 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb) { int ret; - ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST); if (ret) return ret; - writel(MODULE_CLKGATE, mxsfb->base + LCDC_CTRL + MXS_CLR_ADDR); + writel(CTRL_CLKGATE, mxsfb->base + LCDC_CTRL + REG_CLR); - ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_SFTRST); + ret = clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_SFTRST); if (ret) return ret; - return clear_poll_bit(mxsfb->base + LCDC_CTRL, MODULE_CLKGATE); + return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE); } static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) -- GitLab From f16a008921aa13b7012b9f8cf48c44130e6e8a35 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:41 +0300 Subject: [PATCH 0110/1494] drm: mxsfb: Remove unneeded includes A fair number of includes are not needed. Drop them, and add a couple of required includes that were included indirectly. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-10-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 +++--------- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 5 ----- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index aef72adabf417..c4f1575b42100 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -10,19 +10,13 @@ #include <linux/clk.h> #include <linux/iopoll.h> -#include <linux/of_graph.h> -#include <linux/platform_data/simplefb.h> +#include <linux/spinlock.h> -#include <video/videomode.h> - -#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> -#include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 689f50b1ef687..0ee9e5cd492bc 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -9,15 +9,10 @@ */ #include <linux/clk.h> -#include <linux/component.h> #include <linux/dma-mapping.h> -#include <linux/list.h> #include <linux/module.h> #include <linux/of_device.h> -#include <linux/of_graph.h> -#include <linux/of_reserved_mem.h> #include <linux/pm_runtime.h> -#include <linux/dma-resv.h> #include <linux/spinlock.h> #include <drm/drm_atomic.h> -- GitLab From 40a726b82e266693f198f0d8c89de6723b203ebc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:42 +0300 Subject: [PATCH 0111/1494] drm: mxsfb: Rename mxsfb_crtc.c to mxsfb_kms.c The mxsfb_crtc.c file doesn't handle just the CRTC, but also the other KMS objects. Rename it accordingly. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-11-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/Makefile | 2 +- drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename drivers/gpu/drm/mxsfb/{mxsfb_crtc.c => mxsfb_kms.c} (100%) diff --git a/drivers/gpu/drm/mxsfb/Makefile b/drivers/gpu/drm/mxsfb/Makefile index 811584e54ad16..26d153896d720 100644 --- a/drivers/gpu/drm/mxsfb/Makefile +++ b/drivers/gpu/drm/mxsfb/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -mxsfb-y := mxsfb_drv.o mxsfb_crtc.o +mxsfb-y := mxsfb_drv.o mxsfb_kms.o obj-$(CONFIG_DRM_MXSFB) += mxsfb.o diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c similarity index 100% rename from drivers/gpu/drm/mxsfb/mxsfb_crtc.c rename to drivers/gpu/drm/mxsfb/mxsfb_kms.c -- GitLab From ae1ed0093281939b80664a687689f12436c0e874 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:43 +0300 Subject: [PATCH 0112/1494] drm: mxsfb: Stop using DRM simple display pipeline helper The DRM simple display pipeline helper only supports a single plane. In order to prepare for support of the alpha plane on i.MX6SX and i.MX7, move away from the helper. No new feature is added. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-12-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 114 ++---------------- drivers/gpu/drm/mxsfb/mxsfb_drv.h | 23 ++-- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 190 +++++++++++++++++++++++++++--- 3 files changed, 203 insertions(+), 124 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 0ee9e5cd492bc..08b2b2735bc64 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -10,22 +10,23 @@ #include <linux/clk.h> #include <linux/dma-mapping.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <linux/spinlock.h> -#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc.h> +#include <drm/drm_bridge.h> +#include <drm/drm_connector.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_irq.h> +#include <drm/drm_mode_config.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vblank.h> #include "mxsfb_drv.h" @@ -57,22 +58,6 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { }, }; -static const uint32_t mxsfb_formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565 -}; - -static const uint64_t mxsfb_modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID -}; - -static struct mxsfb_drm_private * -drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe) -{ - return container_of(pipe, struct mxsfb_drm_private, pipe); -} - void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb) { if (mxsfb->clk_axi) @@ -95,77 +80,6 @@ static const struct drm_mode_config_helper_funcs mxsfb_mode_config_helpers = { .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, }; -static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe, - struct drm_crtc_state *crtc_state, - struct drm_plane_state *plane_state) -{ - struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); - struct drm_device *drm = pipe->plane.dev; - - pm_runtime_get_sync(drm->dev); - mxsfb_crtc_enable(mxsfb); -} - -static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe) -{ - struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); - struct drm_device *drm = pipe->plane.dev; - struct drm_crtc *crtc = &pipe->crtc; - struct drm_pending_vblank_event *event; - - mxsfb_crtc_disable(mxsfb); - pm_runtime_put_sync(drm->dev); - - spin_lock_irq(&drm->event_lock); - event = crtc->state->event; - if (event) { - crtc->state->event = NULL; - drm_crtc_send_vblank_event(crtc, event); - } - spin_unlock_irq(&drm->event_lock); -} - -static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state) -{ - struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); - - mxsfb_plane_atomic_update(mxsfb, plane_state); -} - -static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe) -{ - struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); - - /* Clear and enable VBLANK IRQ */ - mxsfb_enable_axi_clk(mxsfb); - writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); - writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); - mxsfb_disable_axi_clk(mxsfb); - - return 0; -} - -static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe) -{ - struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); - - /* Disable and clear VBLANK IRQ */ - mxsfb_enable_axi_clk(mxsfb); - writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); - writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); - mxsfb_disable_axi_clk(mxsfb); -} - -static struct drm_simple_display_pipe_funcs mxsfb_funcs = { - .enable = mxsfb_pipe_enable, - .disable = mxsfb_pipe_disable, - .update = mxsfb_pipe_update, - .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, - .enable_vblank = mxsfb_pipe_enable_vblank, - .disable_vblank = mxsfb_pipe_disable_vblank, -}; - static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb) { struct drm_device *drm = mxsfb->drm; @@ -189,7 +103,7 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb) if (!bridge) return -ENODEV; - ret = drm_simple_display_pipe_attach_bridge(&mxsfb->pipe, bridge); + ret = drm_bridge_attach(&mxsfb->encoder, bridge, NULL, 0); if (ret) { DRM_DEV_ERROR(drm->dev, "failed to attach bridge: %d\n", ret); @@ -256,11 +170,9 @@ static int mxsfb_load(struct drm_device *drm) /* Modeset init */ drm_mode_config_init(drm); - ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs, - mxsfb_formats, ARRAY_SIZE(mxsfb_formats), - mxsfb_modifiers, NULL); + ret = mxsfb_kms_init(mxsfb); if (ret < 0) { - dev_err(drm->dev, "Cannot setup simple display pipe\n"); + dev_err(drm->dev, "Failed to initialize KMS pipeline\n"); goto err_vblank; } @@ -316,11 +228,11 @@ static void mxsfb_unload(struct drm_device *drm) pm_runtime_disable(drm->dev); } -static void mxsfb_irq_preinstall(struct drm_device *drm) +static void mxsfb_irq_disable(struct drm_device *drm) { struct mxsfb_drm_private *mxsfb = drm->dev_private; - mxsfb_pipe_disable_vblank(&mxsfb->pipe); + mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc); } static irqreturn_t mxsfb_irq_handler(int irq, void *data) @@ -334,7 +246,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data) reg = readl(mxsfb->base + LCDC_CTRL1); if (reg & CTRL1_CUR_FRAME_DONE_IRQ) - drm_crtc_handle_vblank(&mxsfb->pipe.crtc); + drm_crtc_handle_vblank(&mxsfb->crtc); writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); @@ -348,8 +260,8 @@ DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver mxsfb_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .irq_handler = mxsfb_irq_handler, - .irq_preinstall = mxsfb_irq_preinstall, - .irq_uninstall = mxsfb_irq_preinstall, + .irq_preinstall = mxsfb_irq_disable, + .irq_uninstall = mxsfb_irq_disable, DRM_GEM_CMA_DRIVER_OPS, .fops = &fops, .name = "mxsfb-drm", diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index 0e3e5a63bbf9f..edd766ad254f6 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -8,7 +8,12 @@ #ifndef __MXSFB_DRV_H__ #define __MXSFB_DRV_H__ -struct drm_device; +#include <drm/drm_crtc.h> +#include <drm/drm_device.h> +#include <drm/drm_encoder.h> +#include <drm/drm_plane.h> + +struct clk; struct mxsfb_devdata { unsigned int transfer_count; @@ -29,20 +34,22 @@ struct mxsfb_drm_private { struct clk *clk_disp_axi; struct drm_device *drm; - struct drm_simple_display_pipe pipe; + struct drm_plane plane; + struct drm_crtc crtc; + struct drm_encoder encoder; struct drm_connector *connector; struct drm_bridge *bridge; }; -int mxsfb_setup_crtc(struct drm_device *dev); -int mxsfb_create_output(struct drm_device *dev); +static inline struct mxsfb_drm_private * +to_mxsfb_drm_private(struct drm_device *drm) +{ + return drm->dev_private; +} void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb); void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb); -void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb); -void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb); -void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, - struct drm_plane_state *state); +int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb); #endif /* __MXSFB_DRV_H__ */ diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index c4f1575b42100..2346ad56daea9 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -9,15 +9,21 @@ */ #include <linux/clk.h> +#include <linux/io.h> #include <linux/iopoll.h> +#include <linux/pm_runtime.h> #include <linux/spinlock.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_plane.h> +#include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> #include "mxsfb_drv.h" @@ -26,6 +32,10 @@ /* 1 second delay should be plenty of time for block reset */ #define RESET_TIMEOUT 1000000 +/* ----------------------------------------------------------------------------- + * CRTC + */ + static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) { return (val & mxsfb->devdata->hs_wdth_mask) << @@ -35,9 +45,8 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) { - struct drm_crtc *crtc = &mxsfb->pipe.crtc; - struct drm_device *drm = crtc->dev; - const u32 format = crtc->primary->state->fb->format->format; + struct drm_device *drm = mxsfb->drm; + const u32 format = mxsfb->crtc.primary->state->fb->format->format; u32 ctrl, ctrl1; ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER; @@ -71,8 +80,7 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb) { - struct drm_crtc *crtc = &mxsfb->pipe.crtc; - struct drm_device *drm = crtc->dev; + struct drm_device *drm = mxsfb->drm; u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; u32 reg; @@ -175,7 +183,7 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb) static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) { - struct drm_framebuffer *fb = mxsfb->pipe.plane.state->fb; + struct drm_framebuffer *fb = mxsfb->plane.state->fb; struct drm_gem_cma_object *gem; if (!fb) @@ -190,8 +198,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) { - struct drm_device *drm = mxsfb->pipe.crtc.dev; - struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; + struct drm_device *drm = mxsfb->crtc.dev; + struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode; u32 bus_flags = mxsfb->connector->display_info.bus_flags; u32 vdctrl0, vsync_pulse_len, hsync_pulse_len; int err; @@ -273,10 +281,29 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) mxsfb->base + LCDC_VDCTRL4); } -void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) +static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) { + bool has_primary = state->plane_mask & + drm_plane_mask(crtc->primary); + + /* The primary plane has to be enabled when the CRTC is active. */ + if (state->active && !has_primary) + return -EINVAL; + + /* TODO: Is this needed ? */ + return drm_atomic_add_affected_planes(state->state, crtc); +} + +static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); + struct drm_device *drm = mxsfb->drm; dma_addr_t paddr; + pm_runtime_get_sync(drm->dev); + mxsfb_enable_axi_clk(mxsfb); mxsfb_crtc_mode_set_nofb(mxsfb); @@ -290,17 +317,100 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb) mxsfb_enable_controller(mxsfb); } -void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb) +static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) { + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); + struct drm_device *drm = mxsfb->drm; + struct drm_pending_vblank_event *event; + mxsfb_disable_controller(mxsfb); mxsfb_disable_axi_clk(mxsfb); + + pm_runtime_put_sync(drm->dev); + + spin_lock_irq(&drm->event_lock); + event = crtc->state->event; + if (event) { + crtc->state->event = NULL; + drm_crtc_send_vblank_event(crtc, event); + } + spin_unlock_irq(&drm->event_lock); +} + +static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); + + /* Clear and enable VBLANK IRQ */ + mxsfb_enable_axi_clk(mxsfb); + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); + mxsfb_disable_axi_clk(mxsfb); + + return 0; +} + +static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); + + /* Disable and clear VBLANK IRQ */ + mxsfb_enable_axi_clk(mxsfb); + writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); + writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); + mxsfb_disable_axi_clk(mxsfb); +} + +static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = { + .atomic_check = mxsfb_crtc_atomic_check, + .atomic_enable = mxsfb_crtc_atomic_enable, + .atomic_disable = mxsfb_crtc_atomic_disable, +}; + +static const struct drm_crtc_funcs mxsfb_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = mxsfb_crtc_enable_vblank, + .disable_vblank = mxsfb_crtc_disable_vblank, +}; + +/* ----------------------------------------------------------------------------- + * Encoder + */ + +static const struct drm_encoder_funcs mxsfb_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +/* ----------------------------------------------------------------------------- + * Planes + */ + +static int mxsfb_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *plane_state) +{ + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_new_crtc_state(plane_state->state, + &mxsfb->crtc); + + return drm_atomic_helper_check_plane_state(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); } -void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, - struct drm_plane_state *state) +static void mxsfb_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_pstate) { - struct drm_simple_display_pipe *pipe = &mxsfb->pipe; - struct drm_crtc *crtc = &pipe->crtc; + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); + struct drm_crtc *crtc = &mxsfb->crtc; struct drm_pending_vblank_event *event; dma_addr_t paddr; @@ -324,3 +434,53 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb, mxsfb_disable_axi_clk(mxsfb); } } + +static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = { + .atomic_check = mxsfb_plane_atomic_check, + .atomic_update = mxsfb_plane_atomic_update, +}; + +static const struct drm_plane_funcs mxsfb_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_plane_cleanup, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const uint32_t mxsfb_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565 +}; + +static const uint64_t mxsfb_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb) +{ + struct drm_encoder *encoder = &mxsfb->encoder; + struct drm_plane *plane = &mxsfb->plane; + struct drm_crtc *crtc = &mxsfb->crtc; + int ret; + + drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs); + ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs, + mxsfb_formats, ARRAY_SIZE(mxsfb_formats), + mxsfb_modifiers, DRM_PLANE_TYPE_PRIMARY, + NULL); + if (ret) + return ret; + + drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs); + ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL, + &mxsfb_crtc_funcs, NULL); + if (ret) + return ret; + + encoder->possible_crtcs = drm_crtc_mask(crtc); + return drm_encoder_init(mxsfb->drm, encoder, &mxsfb_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); +} -- GitLab From 1e5d7963bb770d055c2a90f6ef7b57c9f4ba0fa0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:44 +0300 Subject: [PATCH 0113/1494] drm: mxsfb: Move vblank event arm to CRTC .atomic_flush() The vblank event is armed in the plane .atomic_update(). This works fine as we have a single plane, and was the only option when the driver was using the drm_simple_kms_helper helper, but will break as soon as multiple planes are supported. Move it to CRTC .atomic_flush(). Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-13-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 35 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 2346ad56daea9..770546e67a8dc 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -295,6 +295,25 @@ static int mxsfb_crtc_atomic_check(struct drm_crtc *crtc, return drm_atomic_add_affected_planes(state->state, crtc); } +static void mxsfb_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct drm_pending_vblank_event *event; + + event = crtc->state->event; + crtc->state->event = NULL; + + if (!event) + return; + + spin_lock_irq(&crtc->dev->event_lock); + if (drm_crtc_vblank_get(crtc) == 0) + drm_crtc_arm_vblank_event(crtc, event); + else + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); +} + static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -364,6 +383,7 @@ static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc) static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = { .atomic_check = mxsfb_crtc_atomic_check, + .atomic_flush = mxsfb_crtc_atomic_flush, .atomic_enable = mxsfb_crtc_atomic_enable, .atomic_disable = mxsfb_crtc_atomic_disable, }; @@ -410,23 +430,8 @@ static void mxsfb_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_pstate) { struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); - struct drm_crtc *crtc = &mxsfb->crtc; - struct drm_pending_vblank_event *event; dma_addr_t paddr; - spin_lock_irq(&crtc->dev->event_lock); - event = crtc->state->event; - if (event) { - crtc->state->event = NULL; - - if (drm_crtc_vblank_get(crtc) == 0) { - drm_crtc_arm_vblank_event(crtc, event); - } else { - drm_crtc_send_vblank_event(crtc, event); - } - } - spin_unlock_irq(&crtc->dev->event_lock); - paddr = mxsfb_get_fb_paddr(mxsfb); if (paddr) { mxsfb_enable_axi_clk(mxsfb); -- GitLab From 07b7fd77b48c56a0d99c06053bad39b426e28201 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:45 +0300 Subject: [PATCH 0114/1494] drm: mxsfb: Don't touch AXI clock in IRQ context The driver attempts agressive power management by enabling and disabling the AXI clock around register accesses. This results in attempts to enable and disable the clock in the IRQ handler, which is a no-go as preparing or unpreparing the clock may sleep. On the other hand, the driver enables the AXI clock when enabling the CRTC and keeps it enabled until the CRTC is disabled. This is correct, and renders the power management attempt pointless, as interrupts are not supposed to occur when the CRTC is off. The same reasoning can be applied to the CRTC .enable_vblank() and .disable_vblank() that are not supposed to be called when the CRTC off and thus don't require manual handling of the AXI clock. Furthermore, vblank handling is never enabled, which results in the vblank enable and disable handlers never being called. To fix this, remove the manual clock handling in the IRQ, the CRTC .enable_vblank() and .disable_vblank() handlers and the plane .atomic_update() handler. We however need to handle the clock manually in mxsfb_irq_disable() as is calls .disable_vblank() manually and is used both at probe and remove time. The clock disabling is also moved to the last step of the mxsfb_crtc_atomic_disable() function, to prepare for enabling vblank handling. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-14-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 6 ++---- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 15 ++++----------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 08b2b2735bc64..cac50fb4fc0fe 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -232,7 +232,9 @@ static void mxsfb_irq_disable(struct drm_device *drm) { struct mxsfb_drm_private *mxsfb = drm->dev_private; + mxsfb_enable_axi_clk(mxsfb); mxsfb->crtc.funcs->disable_vblank(&mxsfb->crtc); + mxsfb_disable_axi_clk(mxsfb); } static irqreturn_t mxsfb_irq_handler(int irq, void *data) @@ -241,8 +243,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data) struct mxsfb_drm_private *mxsfb = drm->dev_private; u32 reg; - mxsfb_enable_axi_clk(mxsfb); - reg = readl(mxsfb->base + LCDC_CTRL1); if (reg & CTRL1_CUR_FRAME_DONE_IRQ) @@ -250,8 +250,6 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data) writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); - mxsfb_disable_axi_clk(mxsfb); - return IRQ_HANDLED; } diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 770546e67a8dc..3e118848a0830 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -344,9 +344,6 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_pending_vblank_event *event; mxsfb_disable_controller(mxsfb); - mxsfb_disable_axi_clk(mxsfb); - - pm_runtime_put_sync(drm->dev); spin_lock_irq(&drm->event_lock); event = crtc->state->event; @@ -355,6 +352,9 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_send_vblank_event(crtc, event); } spin_unlock_irq(&drm->event_lock); + + mxsfb_disable_axi_clk(mxsfb); + pm_runtime_put_sync(drm->dev); } static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc) @@ -362,10 +362,8 @@ static int mxsfb_crtc_enable_vblank(struct drm_crtc *crtc) struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); /* Clear and enable VBLANK IRQ */ - mxsfb_enable_axi_clk(mxsfb); writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET); - mxsfb_disable_axi_clk(mxsfb); return 0; } @@ -375,10 +373,8 @@ static void mxsfb_crtc_disable_vblank(struct drm_crtc *crtc) struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev); /* Disable and clear VBLANK IRQ */ - mxsfb_enable_axi_clk(mxsfb); writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR); writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR); - mxsfb_disable_axi_clk(mxsfb); } static const struct drm_crtc_helper_funcs mxsfb_crtc_helper_funcs = { @@ -433,11 +429,8 @@ static void mxsfb_plane_atomic_update(struct drm_plane *plane, dma_addr_t paddr; paddr = mxsfb_get_fb_paddr(mxsfb); - if (paddr) { - mxsfb_enable_axi_clk(mxsfb); + if (paddr) writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); - mxsfb_disable_axi_clk(mxsfb); - } } static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = { -- GitLab From b9f5937680a8f1c14aea481358af3504c8b94c3f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:46 +0300 Subject: [PATCH 0115/1494] drm: mxsfb: Enable vblank handling Enable vblank handling when the CRTC is turned on and disable it when it is turned off. This requires moving vblank init after the KMS pipeline initialisation, otherwise drm_vblank_init() gets called with 0 CRTCs. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-15-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 15 +++++++++------ drivers/gpu/drm/mxsfb/mxsfb_kms.c | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index cac50fb4fc0fe..85756d5907e37 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -161,12 +161,6 @@ static int mxsfb_load(struct drm_device *drm) pm_runtime_enable(drm->dev); - ret = drm_vblank_init(drm, drm->mode_config.num_crtc); - if (ret < 0) { - dev_err(drm->dev, "Failed to initialise vblank\n"); - goto err_vblank; - } - /* Modeset init */ drm_mode_config_init(drm); @@ -176,6 +170,15 @@ static int mxsfb_load(struct drm_device *drm) goto err_vblank; } + ret = drm_vblank_init(drm, drm->mode_config.num_crtc); + if (ret < 0) { + dev_err(drm->dev, "Failed to initialise vblank\n"); + goto err_vblank; + } + + /* Start with vertical blanking interrupt reporting disabled. */ + drm_crtc_vblank_off(&mxsfb->crtc); + ret = mxsfb_attach_bridge(mxsfb); if (ret) { dev_err(drm->dev, "Cannot connect bridge: %d\n", ret); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 3e118848a0830..70fd372952e10 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -322,8 +322,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, dma_addr_t paddr; pm_runtime_get_sync(drm->dev); - mxsfb_enable_axi_clk(mxsfb); + + drm_crtc_vblank_on(crtc); + mxsfb_crtc_mode_set_nofb(mxsfb); /* Write cur_buf as well to avoid an initial corrupt frame */ @@ -353,6 +355,8 @@ static void mxsfb_crtc_atomic_disable(struct drm_crtc *crtc, } spin_unlock_irq(&drm->event_lock); + drm_crtc_vblank_off(crtc); + mxsfb_disable_axi_clk(mxsfb); pm_runtime_put_sync(drm->dev); } -- GitLab From f4098b07efb8a38a2f0bc10fce7828eee995f474 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:47 +0300 Subject: [PATCH 0116/1494] drm: mxsfb: Remove mxsfb_devdata unused fields The debug0 and ipversion fields of the mxsfb_devdata structure are unused. Remove them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-16-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 4 ---- drivers/gpu/drm/mxsfb/mxsfb_drv.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 85756d5907e37..ff55519355747 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -42,19 +42,15 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { .transfer_count = LCDC_V3_TRANSFER_COUNT, .cur_buf = LCDC_V3_CUR_BUF, .next_buf = LCDC_V3_NEXT_BUF, - .debug0 = LCDC_V3_DEBUG0, .hs_wdth_mask = 0xff, .hs_wdth_shift = 24, - .ipversion = 3, }, [MXSFB_V4] = { .transfer_count = LCDC_V4_TRANSFER_COUNT, .cur_buf = LCDC_V4_CUR_BUF, .next_buf = LCDC_V4_NEXT_BUF, - .debug0 = LCDC_V4_DEBUG0, .hs_wdth_mask = 0x3fff, .hs_wdth_shift = 18, - .ipversion = 4, }, }; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index edd766ad254f6..607a6a5e6be37 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -19,10 +19,8 @@ struct mxsfb_devdata { unsigned int transfer_count; unsigned int cur_buf; unsigned int next_buf; - unsigned int debug0; unsigned int hs_wdth_mask; unsigned int hs_wdth_shift; - unsigned int ipversion; }; struct mxsfb_drm_private { -- GitLab From b13aeb9e212dbeb051d093201085a4935d348463 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:48 +0300 Subject: [PATCH 0117/1494] drm: mxsfb: Add i.MX7 and i.MX8M to the list of supported SoCs in Kconfig Extend the Kconfig option description by listing the i.MX7 and i.MX8M SoCs, as they are supported by the same driver. Replace the list of SoCs in the short description with just "(e)LCDIF LCD controller" to avoid expanding it further in the future as support for more SoCs is added. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-17-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/Kconfig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index e43b326e91474..0143d539f8f82 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -5,7 +5,7 @@ config DRM_MXS Choose this option to select drivers for MXS FB devices config DRM_MXSFB - tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller" + tristate "i.MX (e)LCDIF LCD controller" depends on DRM && OF depends on COMMON_CLK select DRM_MXS @@ -15,7 +15,8 @@ config DRM_MXSFB select DRM_PANEL select DRM_PANEL_BRIDGE help - Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB - LCD controller. + Choose this option if you have an LCDIF or eLCDIF LCD controller. + Those devices are found in various i.MX SoC (including i.MX23, + i.MX28, i.MX6SX, i.MX7 and i.MX8M). If M is selected the module will be called mxsfb. -- GitLab From f6d94e715817d3847ea0152020ee9f921b4327b6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:49 +0300 Subject: [PATCH 0118/1494] drm: mxsfb: Update internal IP version number for i.MX6SX The LCDIF present in the i.MX6SX has extra features compared to the i.MX28. It has however lost its IP version register, so no official version number is known. Bump the version to MXSFB_V6 following the i.MX version, in preparation for support for the additional features. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-18-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index ff55519355747..9fe0a37e007d0 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -35,6 +35,11 @@ enum mxsfb_devtype { MXSFB_V3, MXSFB_V4, + /* + * Starting at i.MX6 the hardware version register is gone, use the + * i.MX family number as the version. + */ + MXSFB_V6, }; static const struct mxsfb_devdata mxsfb_devdata[] = { @@ -52,6 +57,13 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { .hs_wdth_mask = 0x3fff, .hs_wdth_shift = 18, }, + [MXSFB_V6] = { + .transfer_count = LCDC_V4_TRANSFER_COUNT, + .cur_buf = LCDC_V4_CUR_BUF, + .next_buf = LCDC_V4_NEXT_BUF, + .hs_wdth_mask = 0x3fff, + .hs_wdth_shift = 18, + }, }; void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb) @@ -271,7 +283,7 @@ static struct drm_driver mxsfb_driver = { static const struct platform_device_id mxsfb_devtype[] = { { .name = "imx23-fb", .driver_data = MXSFB_V3, }, { .name = "imx28-fb", .driver_data = MXSFB_V4, }, - { .name = "imx6sx-fb", .driver_data = MXSFB_V4, }, + { .name = "imx6sx-fb", .driver_data = MXSFB_V6, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, mxsfb_devtype); -- GitLab From c6ddee8220bf8ac019589d5ff8ffc4707bcc1c82 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:50 +0300 Subject: [PATCH 0119/1494] drm: mxsfb: Drop non-OF support The mxsfb driver is only used by OF platforms. Drop non-OF support. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-19-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 9fe0a37e007d0..bb80e12d91207 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -131,7 +131,8 @@ static int mxsfb_attach_bridge(struct mxsfb_drm_private *mxsfb) return 0; } -static int mxsfb_load(struct drm_device *drm) +static int mxsfb_load(struct drm_device *drm, + const struct mxsfb_devdata *devdata) { struct platform_device *pdev = to_platform_device(drm->dev); struct mxsfb_drm_private *mxsfb; @@ -144,7 +145,7 @@ static int mxsfb_load(struct drm_device *drm) mxsfb->drm = drm; drm->dev_private = mxsfb; - mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; + mxsfb->devdata = devdata; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mxsfb->base = devm_ioremap_resource(drm->dev, res); @@ -280,18 +281,10 @@ static struct drm_driver mxsfb_driver = { .minor = 0, }; -static const struct platform_device_id mxsfb_devtype[] = { - { .name = "imx23-fb", .driver_data = MXSFB_V3, }, - { .name = "imx28-fb", .driver_data = MXSFB_V4, }, - { .name = "imx6sx-fb", .driver_data = MXSFB_V6, }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(platform, mxsfb_devtype); - static const struct of_device_id mxsfb_dt_ids[] = { - { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], }, - { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], }, - { .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], }, + { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devdata[MXSFB_V3], }, + { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devdata[MXSFB_V4], }, + { .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devdata[MXSFB_V6], }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mxsfb_dt_ids); @@ -306,14 +299,11 @@ static int mxsfb_probe(struct platform_device *pdev) if (!pdev->dev.of_node) return -ENODEV; - if (of_id) - pdev->id_entry = of_id->data; - drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev); if (IS_ERR(drm)) return PTR_ERR(drm); - ret = mxsfb_load(drm); + ret = mxsfb_load(drm, of_id->data); if (ret) goto err_free; @@ -367,7 +357,6 @@ static const struct dev_pm_ops mxsfb_pm_ops = { static struct platform_driver mxsfb_platform_driver = { .probe = mxsfb_probe, .remove = mxsfb_remove, - .id_table = mxsfb_devtype, .driver = { .name = "mxsfb", .of_match_table = mxsfb_dt_ids, -- GitLab From d9ef0d31503254c672afe890641b86870a7ff7cb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:51 +0300 Subject: [PATCH 0120/1494] drm: mxsfb: Turn mxsfb_set_pixel_fmt() into a void function The mxsfb_set_pixel_fmt() function returns an error when the selected pixel format is unsupported. This can never happen, as such errors are caught by the DRM core. Remove the error check. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-20-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 70fd372952e10..ee9ca541caea3 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -43,7 +43,7 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) } /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */ -static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) +static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) { struct drm_device *drm = mxsfb->drm; const u32 format = mxsfb->crtc.primary->state->fb->format->format; @@ -67,15 +67,10 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) /* Do not use packed pixels = one pixel per word instead. */ ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7); break; - default: - dev_err(drm->dev, "Unhandled pixel format %08x\n", format); - return -EINVAL; } writel(ctrl1, mxsfb->base + LCDC_CTRL1); writel(ctrl, mxsfb->base + LCDC_CTRL); - - return 0; } static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb) @@ -218,9 +213,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) /* Clear the FIFOs */ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); - err = mxsfb_set_pixel_fmt(mxsfb); - if (err) - return; + mxsfb_set_pixel_fmt(mxsfb); clk_set_rate(mxsfb->clk, m->crtc_clock * 1000); -- GitLab From 51b777f2b11ea2eed4b6c5faf3884b4aeba0b82a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:52 +0300 Subject: [PATCH 0121/1494] drm: mxsfb: Merge mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() The mxsfb_set_pixel_fmt() and mxsfb_set_bus_fmt() functions both deal with format configuration, are always called in a row from mxsfb_crtc_mode_set_nofb(), and set fields from the LCDC_CTRL register. This requires a read-modify-update cycle in mxsfb_set_bus_fmt(). Make this more efficient by merging them together. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-21-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 47 +++++++++++++------------------ 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index ee9ca541caea3..505aa7e242391 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -42,13 +42,23 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val) mxsfb->devdata->hs_wdth_shift; } -/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */ -static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) +/* + * Setup the MXSFB registers for decoding the pixels out of the framebuffer and + * outputting them on the bus. + */ +static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb) { struct drm_device *drm = mxsfb->drm; const u32 format = mxsfb->crtc.primary->state->fb->format->format; + u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; u32 ctrl, ctrl1; + if (mxsfb->connector->display_info.num_bus_formats) + bus_format = mxsfb->connector->display_info.bus_formats[0]; + + DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n", + bus_format); + ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER; /* CTRL1 contains IRQ config and status bits, preserve those. */ @@ -69,40 +79,23 @@ static void mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb) break; } - writel(ctrl1, mxsfb->base + LCDC_CTRL1); - writel(ctrl, mxsfb->base + LCDC_CTRL); -} - -static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb) -{ - struct drm_device *drm = mxsfb->drm; - u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; - u32 reg; - - reg = readl(mxsfb->base + LCDC_CTRL); - - if (mxsfb->connector->display_info.num_bus_formats) - bus_format = mxsfb->connector->display_info.bus_formats[0]; - - DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n", - bus_format); - - reg &= ~CTRL_BUS_WIDTH_MASK; switch (bus_format) { case MEDIA_BUS_FMT_RGB565_1X16: - reg |= CTRL_BUS_WIDTH_16; + ctrl |= CTRL_BUS_WIDTH_16; break; case MEDIA_BUS_FMT_RGB666_1X18: - reg |= CTRL_BUS_WIDTH_18; + ctrl |= CTRL_BUS_WIDTH_18; break; case MEDIA_BUS_FMT_RGB888_1X24: - reg |= CTRL_BUS_WIDTH_24; + ctrl |= CTRL_BUS_WIDTH_24; break; default: dev_err(drm->dev, "Unknown media bus format %d\n", bus_format); break; } - writel(reg, mxsfb->base + LCDC_CTRL); + + writel(ctrl1, mxsfb->base + LCDC_CTRL1); + writel(ctrl, mxsfb->base + LCDC_CTRL); } static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb) @@ -213,7 +206,7 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) /* Clear the FIFOs */ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); - mxsfb_set_pixel_fmt(mxsfb); + mxsfb_set_formats(mxsfb); clk_set_rate(mxsfb->clk, m->crtc_clock * 1000); @@ -255,8 +248,6 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0); - mxsfb_set_bus_fmt(mxsfb); - /* Frame length in lines. */ writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1); -- GitLab From b963ad95a06a5480367dd25a807e5bc0dd83842e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:53 +0300 Subject: [PATCH 0122/1494] drm: mxsfb: Remove unnecessary spaces after tab This is a cosmetic change only, no code change is included. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-22-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index 607a6a5e6be37..f883b56caed34 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -16,11 +16,11 @@ struct clk; struct mxsfb_devdata { - unsigned int transfer_count; - unsigned int cur_buf; - unsigned int next_buf; - unsigned int hs_wdth_mask; - unsigned int hs_wdth_shift; + unsigned int transfer_count; + unsigned int cur_buf; + unsigned int next_buf; + unsigned int hs_wdth_mask; + unsigned int hs_wdth_shift; }; struct mxsfb_drm_private { -- GitLab From 63aa581c3019301e998b148c1eb63a108aca365f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 27 Jul 2020 05:06:54 +0300 Subject: [PATCH 0123/1494] drm: mxsfb: Support the alpha plane The LCDIF in the i.MX6SX and i.MX7 have a second plane called the alpha plane. Support it. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200727020654.8231-23-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 3 + drivers/gpu/drm/mxsfb/mxsfb_drv.h | 6 +- drivers/gpu/drm/mxsfb/mxsfb_kms.c | 129 +++++++++++++++++++++++++---- drivers/gpu/drm/mxsfb/mxsfb_regs.h | 22 +++++ 4 files changed, 144 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index bb80e12d91207..8c549c3931afa 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -49,6 +49,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { .next_buf = LCDC_V3_NEXT_BUF, .hs_wdth_mask = 0xff, .hs_wdth_shift = 24, + .has_overlay = false, }, [MXSFB_V4] = { .transfer_count = LCDC_V4_TRANSFER_COUNT, @@ -56,6 +57,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { .next_buf = LCDC_V4_NEXT_BUF, .hs_wdth_mask = 0x3fff, .hs_wdth_shift = 18, + .has_overlay = false, }, [MXSFB_V6] = { .transfer_count = LCDC_V4_TRANSFER_COUNT, @@ -63,6 +65,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = { .next_buf = LCDC_V4_NEXT_BUF, .hs_wdth_mask = 0x3fff, .hs_wdth_shift = 18, + .has_overlay = true, }, }; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h b/drivers/gpu/drm/mxsfb/mxsfb_drv.h index f883b56caed34..399d23e91ed10 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h @@ -21,6 +21,7 @@ struct mxsfb_devdata { unsigned int next_buf; unsigned int hs_wdth_mask; unsigned int hs_wdth_shift; + bool has_overlay; }; struct mxsfb_drm_private { @@ -32,7 +33,10 @@ struct mxsfb_drm_private { struct clk *clk_disp_axi; struct drm_device *drm; - struct drm_plane plane; + struct { + struct drm_plane primary; + struct drm_plane overlay; + } planes; struct drm_crtc crtc; struct drm_encoder encoder; struct drm_connector *connector; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_kms.c b/drivers/gpu/drm/mxsfb/mxsfb_kms.c index 505aa7e242391..b721b8b262ce9 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_kms.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_kms.c @@ -169,9 +169,9 @@ static int mxsfb_reset_block(struct mxsfb_drm_private *mxsfb) return clear_poll_bit(mxsfb->base + LCDC_CTRL, CTRL_CLKGATE); } -static dma_addr_t mxsfb_get_fb_paddr(struct mxsfb_drm_private *mxsfb) +static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane) { - struct drm_framebuffer *fb = mxsfb->plane.state->fb; + struct drm_framebuffer *fb = plane->state->fb; struct drm_gem_cma_object *gem; if (!fb) @@ -206,6 +206,9 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb) /* Clear the FIFOs */ writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); + if (mxsfb->devdata->has_overlay) + writel(0, mxsfb->base + LCDC_AS_CTRL); + mxsfb_set_formats(mxsfb); clk_set_rate(mxsfb->clk, m->crtc_clock * 1000); @@ -313,7 +316,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc, mxsfb_crtc_mode_set_nofb(mxsfb); /* Write cur_buf as well to avoid an initial corrupt frame */ - paddr = mxsfb_get_fb_paddr(mxsfb); + paddr = mxsfb_get_fb_paddr(crtc->primary); if (paddr) { writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf); writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); @@ -410,20 +413,85 @@ static int mxsfb_plane_atomic_check(struct drm_plane *plane, false, true); } -static void mxsfb_plane_atomic_update(struct drm_plane *plane, - struct drm_plane_state *old_pstate) +static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_pstate) { struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); dma_addr_t paddr; - paddr = mxsfb_get_fb_paddr(mxsfb); + paddr = mxsfb_get_fb_paddr(plane); if (paddr) writel(paddr, mxsfb->base + mxsfb->devdata->next_buf); } -static const struct drm_plane_helper_funcs mxsfb_plane_helper_funcs = { +static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_pstate) +{ + struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev); + struct drm_plane_state *state = plane->state; + dma_addr_t paddr; + u32 ctrl; + + paddr = mxsfb_get_fb_paddr(plane); + if (!paddr) { + writel(0, mxsfb->base + LCDC_AS_CTRL); + return; + } + + /* + * HACK: The hardware seems to output 64 bytes of data of unknown + * origin, and then to proceed with the framebuffer. Until the reason + * is understood, live with the 16 initial invalid pixels on the first + * line and start 64 bytes within the framebuffer. + */ + paddr += 64; + + writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF); + + /* + * If the plane was previously disabled, write LCDC_AS_BUF as well to + * provide the first buffer. + */ + if (!old_pstate->fb) + writel(paddr, mxsfb->base + LCDC_AS_BUF); + + ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255); + + switch (state->fb->format->format) { + case DRM_FORMAT_XRGB4444: + ctrl |= AS_CTRL_FORMAT_RGB444 | AS_CTRL_ALPHA_CTRL_OVERRIDE; + break; + case DRM_FORMAT_ARGB4444: + ctrl |= AS_CTRL_FORMAT_ARGB4444 | AS_CTRL_ALPHA_CTRL_EMBEDDED; + break; + case DRM_FORMAT_XRGB1555: + ctrl |= AS_CTRL_FORMAT_RGB555 | AS_CTRL_ALPHA_CTRL_OVERRIDE; + break; + case DRM_FORMAT_ARGB1555: + ctrl |= AS_CTRL_FORMAT_ARGB1555 | AS_CTRL_ALPHA_CTRL_EMBEDDED; + break; + case DRM_FORMAT_RGB565: + ctrl |= AS_CTRL_FORMAT_RGB565 | AS_CTRL_ALPHA_CTRL_OVERRIDE; + break; + case DRM_FORMAT_XRGB8888: + ctrl |= AS_CTRL_FORMAT_RGB888 | AS_CTRL_ALPHA_CTRL_OVERRIDE; + break; + case DRM_FORMAT_ARGB8888: + ctrl |= AS_CTRL_FORMAT_ARGB8888 | AS_CTRL_ALPHA_CTRL_EMBEDDED; + break; + } + + writel(ctrl, mxsfb->base + LCDC_AS_CTRL); +} + +static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = { + .atomic_check = mxsfb_plane_atomic_check, + .atomic_update = mxsfb_plane_primary_atomic_update, +}; + +static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = { .atomic_check = mxsfb_plane_atomic_check, - .atomic_update = mxsfb_plane_atomic_update, + .atomic_update = mxsfb_plane_overlay_atomic_update, }; static const struct drm_plane_funcs mxsfb_plane_funcs = { @@ -435,9 +503,19 @@ static const struct drm_plane_funcs mxsfb_plane_funcs = { .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, }; -static const uint32_t mxsfb_formats[] = { +static const uint32_t mxsfb_primary_plane_formats[] = { + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, +}; + +static const uint32_t mxsfb_overlay_plane_formats[] = { + DRM_FORMAT_XRGB4444, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565 + DRM_FORMAT_ARGB8888, }; static const uint64_t mxsfb_modifiers[] = { @@ -445,23 +523,44 @@ static const uint64_t mxsfb_modifiers[] = { DRM_FORMAT_MOD_INVALID }; +/* ----------------------------------------------------------------------------- + * Initialization + */ + int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb) { struct drm_encoder *encoder = &mxsfb->encoder; - struct drm_plane *plane = &mxsfb->plane; struct drm_crtc *crtc = &mxsfb->crtc; int ret; - drm_plane_helper_add(plane, &mxsfb_plane_helper_funcs); - ret = drm_universal_plane_init(mxsfb->drm, plane, 0, &mxsfb_plane_funcs, - mxsfb_formats, ARRAY_SIZE(mxsfb_formats), + drm_plane_helper_add(&mxsfb->planes.primary, + &mxsfb_plane_primary_helper_funcs); + ret = drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1, + &mxsfb_plane_funcs, + mxsfb_primary_plane_formats, + ARRAY_SIZE(mxsfb_primary_plane_formats), mxsfb_modifiers, DRM_PLANE_TYPE_PRIMARY, NULL); if (ret) return ret; + if (mxsfb->devdata->has_overlay) { + drm_plane_helper_add(&mxsfb->planes.overlay, + &mxsfb_plane_overlay_helper_funcs); + ret = drm_universal_plane_init(mxsfb->drm, + &mxsfb->planes.overlay, 1, + &mxsfb_plane_funcs, + mxsfb_overlay_plane_formats, + ARRAY_SIZE(mxsfb_overlay_plane_formats), + mxsfb_modifiers, DRM_PLANE_TYPE_OVERLAY, + NULL); + if (ret) + return ret; + } + drm_crtc_helper_add(crtc, &mxsfb_crtc_helper_funcs); - ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, plane, NULL, + ret = drm_crtc_init_with_planes(mxsfb->drm, crtc, + &mxsfb->planes.primary, NULL, &mxsfb_crtc_funcs, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 8ebb52bb1b461..55d28a27f9124 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h @@ -27,6 +27,11 @@ #define LCDC_VDCTRL4 0xb0 #define LCDC_V4_DEBUG0 0x1d0 #define LCDC_V3_DEBUG0 0x1f0 +#define LCDC_AS_CTRL 0x210 +#define LCDC_AS_BUF 0x220 +#define LCDC_AS_NEXT_BUF 0x230 +#define LCDC_AS_CLRKEYLOW 0x240 +#define LCDC_AS_CLRKEYHIGH 0x250 #define CTRL_SFTRST BIT(31) #define CTRL_CLKGATE BIT(30) @@ -90,6 +95,23 @@ #define DEBUG0_HSYNC BIT(26) #define DEBUG0_VSYNC BIT(25) +#define AS_CTRL_PS_DISABLE BIT(23) +#define AS_CTRL_ALPHA_INVERT BIT(20) +#define AS_CTRL_ALPHA(a) (((a) & 0xff) << 8) +#define AS_CTRL_FORMAT_RGB565 (0xe << 4) +#define AS_CTRL_FORMAT_RGB444 (0xd << 4) +#define AS_CTRL_FORMAT_RGB555 (0xc << 4) +#define AS_CTRL_FORMAT_ARGB4444 (0x9 << 4) +#define AS_CTRL_FORMAT_ARGB1555 (0x8 << 4) +#define AS_CTRL_FORMAT_RGB888 (0x4 << 4) +#define AS_CTRL_FORMAT_ARGB8888 (0x0 << 4) +#define AS_CTRL_ENABLE_COLORKEY BIT(3) +#define AS_CTRL_ALPHA_CTRL_ROP (3 << 1) +#define AS_CTRL_ALPHA_CTRL_MULTIPLY (2 << 1) +#define AS_CTRL_ALPHA_CTRL_OVERRIDE (1 << 1) +#define AS_CTRL_ALPHA_CTRL_EMBEDDED (0 << 1) +#define AS_CTRL_AS_ENABLE BIT(0) + #define MXSFB_MIN_XRES 120 #define MXSFB_MIN_YRES 120 #define MXSFB_MAX_XRES 0xffff -- GitLab From a26a4790a82a4675323102235a7bcbd479817b02 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 14:12:44 +0200 Subject: [PATCH 0124/1494] dt-bindings: Add vendor prefix for Powertip The Powertip Tech. Corp. is an LCD panel manufacturer. Signed-off-by: Marek Vasut <marex@denx.de> To: dri-devel@lists.freedesktop.org Cc: Eric Anholt <eric@anholt.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728121246.23304-1-marex@denx.de --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index caf7dbed564ca..da56a82b56231 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -824,6 +824,8 @@ patternProperties: description: Poslab Technology Co., Ltd. "^pov,.*": description: Point of View International B.V. + "^powertip,.*": + description: Powertip Tech. Corp. "^powervr,.*": description: PowerVR (deprecated, use img) "^primux,.*": -- GitLab From 051e95ee7ec10050154e4c8f48be4d99ac83f8fc Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 14:12:45 +0200 Subject: [PATCH 0125/1494] dt-bindings: Add DT bindings for Powertip PH800480T013 Add DT bindings for Powertip PH800480T013 800x480 parallel LCD, this one is used in the Raspberry Pi 7" touchscreen display unit. Signed-off-by: Marek Vasut <marex@denx.de> To: dri-devel@lists.freedesktop.org Cc: Eric Anholt <eric@anholt.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728121246.23304-2-marex@denx.de --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 6deeeed59e59f..5a0af2b80abae 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -219,6 +219,8 @@ properties: - osddisplays,osd070t1718-19ts # One Stop Displays OSD101T2045-53TS 10.1" 1920x1200 panel - osddisplays,osd101t2045-53ts + # POWERTIP PH800480T013-IDF2 7.0" WVGA TFT LCD panel + - powertip,ph800480t013-idf02 # QiaoDian XianShi Corporation 4"3 TFT LCD panel - qiaodian,qd43003c0-40 # Rocktech Displays Ltd. RK101II01D-CT 10.1" TFT 1280x800 -- GitLab From d69de69f2be105b2474c05a5ca4827aac3e80ad3 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 14:12:46 +0200 Subject: [PATCH 0126/1494] drm/panel: simple: Add Powertip PH800480T013 panel Add support for Powertip PH800480T013 800x480 parallel LCD, this one is used in the Raspberry Pi 7" touchscreen display unit. Signed-off-by: Marek Vasut <marex@denx.de> To: dri-devel@lists.freedesktop.org Cc: Eric Anholt <eric@anholt.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728121246.23304-3-marex@denx.de --- drivers/gpu/drm/panel/panel-simple.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 5cba33394083a..221859652d82b 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3028,6 +3028,31 @@ static const struct panel_desc pda_91_00156_a0 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct drm_display_mode powertip_ph800480t013_idf02_mode = { + .clock = 24750, + .hdisplay = 800, + .hsync_start = 800 + 54, + .hsync_end = 800 + 54 + 2, + .htotal = 800 + 54 + 2 + 44, + .vdisplay = 480, + .vsync_start = 480 + 49, + .vsync_end = 480 + 49 + 2, + .vtotal = 480 + 49 + 2 + 22, +}; + +static const struct panel_desc powertip_ph800480t013_idf02 = { + .modes = &powertip_ph800480t013_idf02_mode, + .num_modes = 1, + .size = { + .width = 152, + .height = 91, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | + DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .connector_type = DRM_MODE_CONNECTOR_DPI, +}; static const struct drm_display_mode qd43003c0_40_mode = { .clock = 9000, @@ -4040,6 +4065,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "pda,91-00156-a0", .data = &pda_91_00156_a0, + }, { + .compatible = "powertip,ph800480t013-idf02", + .data = &powertip_ph800480t013_idf02, }, { .compatible = "qiaodian,qd43003c0-40", .data = &qd43003c0_40, -- GitLab From c114e72313045108d6ddc1847b4ffff4e50ab444 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 28 Jul 2020 17:16:40 +0200 Subject: [PATCH 0127/1494] drm/ingenic: Handle errors of drm_atomic_get_plane_state drm_atomic_get_plane_state() can return errors, so we need to handle these. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728151641.26124-2-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index ada990a7f911a..64eabab3ef691 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -215,10 +215,17 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, if (priv->soc_info->has_osd) { f1_state = drm_atomic_get_plane_state(state->state, &priv->f1); + if (IS_ERR(f1_state)) + return PTR_ERR(f1_state); + f0_state = drm_atomic_get_plane_state(state->state, &priv->f0); + if (IS_ERR(f0_state)) + return PTR_ERR(f0_state); if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && priv->ipu_plane) { ipu_state = drm_atomic_get_plane_state(state->state, priv->ipu_plane); + if (IS_ERR(ipu_state)) + return PTR_ERR(ipu_state); /* IPU and F1 planes cannot be enabled at the same time. */ if (f1_state->fb && ipu_state->fb) { -- GitLab From 639abb72f189a9df1033cbe5eaf1c0508021f699 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 28 Jul 2020 17:16:41 +0200 Subject: [PATCH 0128/1494] drm/ingenic: Validate mode in a .mode_valid callback Validate modes in the drm_crtc_helper_funcs.mode_valid() callback, which is designed for this purpose, instead of doing it in drm_crtc_helper_funcs.atomic_check(). Signed-off-by: Paul Cercueil <paul@crapouillou.net> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728151641.26124-3-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 34 +++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 64eabab3ef691..5dab9c3d0a520 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -199,21 +199,8 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, { struct ingenic_drm *priv = drm_crtc_get_priv(crtc); struct drm_plane_state *f1_state, *f0_state, *ipu_state = NULL; - long rate; - - if (!drm_atomic_crtc_needs_modeset(state)) - return 0; - - if (state->mode.hdisplay > priv->soc_info->max_width || - state->mode.vdisplay > priv->soc_info->max_height) - return -EINVAL; - rate = clk_round_rate(priv->pix_clk, - state->adjusted_mode.clock * 1000); - if (rate < 0) - return rate; - - if (priv->soc_info->has_osd) { + if (drm_atomic_crtc_needs_modeset(state) && priv->soc_info->has_osd) { f1_state = drm_atomic_get_plane_state(state->state, &priv->f1); if (IS_ERR(f1_state)) return PTR_ERR(f1_state); @@ -242,6 +229,24 @@ static int ingenic_drm_crtc_atomic_check(struct drm_crtc *crtc, return 0; } +static enum drm_mode_status +ingenic_drm_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) +{ + struct ingenic_drm *priv = drm_crtc_get_priv(crtc); + long rate; + + if (mode->hdisplay > priv->soc_info->max_width) + return MODE_BAD_HVALUE; + if (mode->vdisplay > priv->soc_info->max_height) + return MODE_BAD_VVALUE; + + rate = clk_round_rate(priv->pix_clk, mode->clock * 1000); + if (rate < 0) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + static void ingenic_drm_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *oldstate) { @@ -655,6 +660,7 @@ static const struct drm_crtc_helper_funcs ingenic_drm_crtc_helper_funcs = { .atomic_begin = ingenic_drm_crtc_atomic_begin, .atomic_flush = ingenic_drm_crtc_atomic_flush, .atomic_check = ingenic_drm_crtc_atomic_check, + .mode_valid = ingenic_drm_crtc_mode_valid, }; static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = { -- GitLab From 85b3bfa266e8421afab5e75b8306003e97990a4a Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Tue, 28 Jul 2020 20:55:07 +0800 Subject: [PATCH 0129/1494] drm/hisilicon: Fixed the warning: Assignment of 0/1 to bool variable fixed the following warning: hibmc_drm_drv.c:296:1-18:WARNING: Assignment of 0/1 to bool variable. hibmc_drm_drv.c:301:2-19: WARNING: Assignment of 0/1 to bool variable. v2: using the pci_dev.msi_enabled instead of priv->msi_enabled. v3: just call pci_enable_msi() and pci_disable_msi(), it's no need to set dev->pdev->msi_enabled again. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-By: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1595940907-17874-1-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 5 +---- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 249c298e0987e..b8d839a1c4598 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -254,9 +254,8 @@ static int hibmc_unload(struct drm_device *dev) if (dev->irq_enabled) drm_irq_uninstall(dev); - if (priv->msi_enabled) - pci_disable_msi(dev->pdev); + pci_disable_msi(dev->pdev); hibmc_kms_fini(priv); hibmc_mm_fini(priv); dev->dev_private = NULL; @@ -294,12 +293,10 @@ static int hibmc_load(struct drm_device *dev) goto err; } - priv->msi_enabled = 0; ret = pci_enable_msi(dev->pdev); if (ret) { DRM_WARN("enabling MSI failed: %d\n", ret); } else { - priv->msi_enabled = 1; ret = drm_irq_install(dev, dev->pdev->irq); if (ret) DRM_WARN("install irq failed: %d\n", ret); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 609768748de65..a6837637af2a4 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -25,7 +25,6 @@ struct hibmc_drm_private { void __iomem *fb_map; unsigned long fb_base; unsigned long fb_size; - bool msi_enabled; /* drm */ struct drm_device *dev; -- GitLab From cfb9b89f116a076ff333d4d0dc4aa862079481ba Mon Sep 17 00:00:00 2001 From: Pekka Paalanen <pekka.paalanen@collabora.com> Date: Tue, 7 Jul 2020 14:38:05 +0300 Subject: [PATCH 0130/1494] drm/doc: device hot-unplug for userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set up the expectations on how hot-unplugging a DRM device should look like to userspace. Written by Daniel Vetter's request and largely based on his comments in IRC and from https://lists.freedesktop.org/archives/dri-devel/2020-May/265484.html . A related Wayland protocol change proposal is at https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/35 Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Noralf Trønnes <noralf@tronnes.org> Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Sean Paul <sean@poorly.run> Cc: Simon Ser <contact@emersion.fr> Cc: Ben Skeggs <skeggsb@gmail.com> Cc: Karol Herbst <kherbst@redhat.com> Acked-by: Simon Ser <contact@emersion.fr> Signed-off-by: Emil Velikov <emil.velikov@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200707113805.30936-1-ppaalanen@gmail.com --- Documentation/gpu/drm-uapi.rst | 114 ++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 56fec6ed1ad86..9ce51e4f98f45 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -1,3 +1,5 @@ +.. Copyright 2020 DisplayLink (UK) Ltd. + =================== Userland interfaces =================== @@ -162,6 +164,116 @@ other hand, a driver requires shared state between clients which is visible to user-space and accessible beyond open-file boundaries, they cannot support render nodes. +Device Hot-Unplug +================= + +.. note:: + The following is the plan. Implementation is not there yet + (2020 May). + +Graphics devices (display and/or render) may be connected via USB (e.g. +display adapters or docking stations) or Thunderbolt (e.g. eGPU). An end +user is able to hot-unplug this kind of devices while they are being +used, and expects that the very least the machine does not crash. Any +damage from hot-unplugging a DRM device needs to be limited as much as +possible and userspace must be given the chance to handle it if it wants +to. Ideally, unplugging a DRM device still lets a desktop continue to +run, but that is going to need explicit support throughout the whole +graphics stack: from kernel and userspace drivers, through display +servers, via window system protocols, and in applications and libraries. + +Other scenarios that should lead to the same are: unrecoverable GPU +crash, PCI device disappearing off the bus, or forced unbind of a driver +from the physical device. + +In other words, from userspace perspective everything needs to keep on +working more or less, until userspace stops using the disappeared DRM +device and closes it completely. Userspace will learn of the device +disappearance from the device removed uevent, ioctls returning ENODEV +(or driver-specific ioctls returning driver-specific things), or open() +returning ENXIO. + +Only after userspace has closed all relevant DRM device and dmabuf file +descriptors and removed all mmaps, the DRM driver can tear down its +instance for the device that no longer exists. If the same physical +device somehow comes back in the mean time, it shall be a new DRM +device. + +Similar to PIDs, chardev minor numbers are not recycled immediately. A +new DRM device always picks the next free minor number compared to the +previous one allocated, and wraps around when minor numbers are +exhausted. + +The goal raises at least the following requirements for the kernel and +drivers. + +Requirements for KMS UAPI +------------------------- + +- KMS connectors must change their status to disconnected. + +- Legacy modesets and pageflips, and atomic commits, both real and + TEST_ONLY, and any other ioctls either fail with ENODEV or fake + success. + +- Pending non-blocking KMS operations deliver the DRM events userspace + is expecting. This applies also to ioctls that faked success. + +- open() on a device node whose underlying device has disappeared will + fail with ENXIO. + +- Attempting to create a DRM lease on a disappeared DRM device will + fail with ENODEV. Existing DRM leases remain and work as listed + above. + +Requirements for Render and Cross-Device UAPI +--------------------------------------------- + +- All GPU jobs that can no longer run must have their fences + force-signalled to avoid inflicting hangs on userspace. + The associated error code is ENODEV. + +- Some userspace APIs already define what should happen when the device + disappears (OpenGL, GL ES: `GL_KHR_robustness`_; `Vulkan`_: + VK_ERROR_DEVICE_LOST; etc.). DRM drivers are free to implement this + behaviour the way they see best, e.g. returning failures in + driver-specific ioctls and handling those in userspace drivers, or + rely on uevents, and so on. + +- dmabuf which point to memory that has disappeared will either fail to + import with ENODEV or continue to be successfully imported if it would + have succeeded before the disappearance. See also about memory maps + below for already imported dmabufs. + +- Attempting to import a dmabuf to a disappeared device will either fail + with ENODEV or succeed if it would have succeeded without the + disappearance. + +- open() on a device node whose underlying device has disappeared will + fail with ENXIO. + +.. _GL_KHR_robustness: https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_robustness.txt +.. _Vulkan: https://www.khronos.org/vulkan/ + +Requirements for Memory Maps +---------------------------- + +Memory maps have further requirements that apply to both existing maps +and maps created after the device has disappeared. If the underlying +memory disappears, the map is created or modified such that reads and +writes will still complete successfully but the result is undefined. +This applies to both userspace mmap()'d memory and memory pointed to by +dmabuf which might be mapped to other devices (cross-device dmabuf +imports). + +Raising SIGBUS is not an option, because userspace cannot realistically +handle it. Signal handlers are global, which makes them extremely +difficult to use correctly from libraries like those that Mesa produces. +Signal handlers are not composable, you can't have different handlers +for GPU1 and GPU2 from different vendors, and a third handler for +mmapped regular files. Threads cause additional pain with signal +handling as well. + .. _drm_driver_ioctl: IOCTL Support on Device Nodes @@ -199,7 +311,7 @@ EPERM/EACCES: difference between EACCES and EPERM. ENODEV: - The device is not (yet) present or fully initialized. + The device is not present anymore or is not yet fully initialized. EOPNOTSUPP: Feature (like PRIME, modesetting, GEM) is not supported by the driver. -- GitLab From 3debcdf066e51fa771e128a18655f2712b1f82e9 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Thu, 30 Jul 2020 16:48:28 +0200 Subject: [PATCH 0131/1494] drm/ingenic: ipu: Only restart manually on older SoCs On older SoCs, it is necessary to restart manually the IPU when a frame is done processing. Doing so on newer SoCs (JZ4760/70) kinds of work too, until the input or output resolutions or the framerate are too high. Make it work properly on newer SoCs by letting the LCD controller trigger the IPU frame restart signal. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200730144830.10479-2-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 7a0a8bd865d33..7eae56fa92ea2 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -35,6 +35,7 @@ struct soc_info { const u32 *formats; size_t num_formats; bool has_bicubic; + bool manual_restart; void (*set_coefs)(struct ingenic_ipu *ipu, unsigned int reg, unsigned int sharpness, bool downscale, @@ -645,7 +646,8 @@ static irqreturn_t ingenic_ipu_irq_handler(int irq, void *arg) unsigned int dummy; /* dummy read allows CPU to reconfigure IPU */ - regmap_read(ipu->map, JZ_REG_IPU_STATUS, &dummy); + if (ipu->soc_info->manual_restart) + regmap_read(ipu->map, JZ_REG_IPU_STATUS, &dummy); /* ACK interrupt */ regmap_write(ipu->map, JZ_REG_IPU_STATUS, 0); @@ -656,7 +658,8 @@ static irqreturn_t ingenic_ipu_irq_handler(int irq, void *arg) regmap_write(ipu->map, JZ_REG_IPU_V_ADDR, ipu->addr_v); /* Run IPU for the new frame */ - regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RUN); + if (ipu->soc_info->manual_restart) + regmap_set_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_RUN); drm_crtc_handle_vblank(crtc); @@ -806,6 +809,7 @@ static const struct soc_info jz4725b_soc_info = { .formats = jz4725b_ipu_formats, .num_formats = ARRAY_SIZE(jz4725b_ipu_formats), .has_bicubic = false, + .manual_restart = true, .set_coefs = jz4725b_set_coefs, }; @@ -831,6 +835,7 @@ static const struct soc_info jz4760_soc_info = { .formats = jz4760_ipu_formats, .num_formats = ARRAY_SIZE(jz4760_ipu_formats), .has_bicubic = true, + .manual_restart = false, .set_coefs = jz4760_set_coefs, }; -- GitLab From c0fd208ee3bc1020fd24cf986aec604374440ce4 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Thu, 30 Jul 2020 16:48:29 +0200 Subject: [PATCH 0132/1494] drm/ingenic: ipu: Remove YUV422 from supported formats on JZ4725B When configuring the IPU for packed YUV 4:2:2, depending on the scaling ratios given by the source and destination resolutions, it is possible to crash the IPU block, to the point where a software reset of the IP does not fix it. This can happen anytime, in the first few frames, or after dozens of minutes. The same crash also happens when the IPU is fully controlled by the LCD controller (in that case no HW register is written at any moment after startup), which points towards a hardware bug. Thanksfully multiplanar YUV is not affected. Until this bug is fixed or worked around, address this issue by removing support for YUV 4:2:2 on the IPU of the JZ4725B. v2: Update commit message (remove the "crash beyond repair" bit) Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200730144830.10479-3-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 7eae56fa92ea2..7dd2a6ae49946 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -795,10 +795,16 @@ static int ingenic_ipu_remove(struct platform_device *pdev) } static const u32 jz4725b_ipu_formats[] = { + /* + * While officially supported, packed YUV 4:2:2 formats can cause + * random hardware crashes on JZ4725B under certain circumstances. + * It seems to happen with some specific resize ratios. + * Until a proper workaround or fix is found, disable these formats. DRM_FORMAT_YUYV, DRM_FORMAT_YVYU, DRM_FORMAT_UYVY, DRM_FORMAT_VYUY, + */ DRM_FORMAT_YUV411, DRM_FORMAT_YUV420, DRM_FORMAT_YUV422, -- GitLab From 38ee474fc63f79f66df1bed06c8c952e8258ea90 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Thu, 30 Jul 2020 16:48:30 +0200 Subject: [PATCH 0133/1494] drm/ingenic: ipu: Only enable clock when needed Instead of keeping the IPU clock enabled constantly, enable and disable it on demand, when the IPU plane is used. That way, we won't use any extra power when the IPU is not used. v2: Explain the reason of this patch Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200730144830.10479-4-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-ipu.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 7dd2a6ae49946..fc8c6e970ee31 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -49,6 +49,7 @@ struct ingenic_ipu { struct regmap *map; struct clk *clk; const struct soc_info *soc_info; + bool clk_enabled; unsigned int num_w, num_h, denom_w, denom_h; @@ -288,12 +289,23 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, const struct drm_format_info *finfo; u32 ctrl, stride = 0, coef_index = 0, format = 0; bool needs_modeset, upscaling_w, upscaling_h; + int err; if (!state || !state->fb) return; finfo = drm_format_info(state->fb->format->format); + if (!ipu->clk_enabled) { + err = clk_enable(ipu->clk); + if (err) { + dev_err(ipu->dev, "Unable to enable clock: %d\n", err); + return; + } + + ipu->clk_enabled = true; + } + /* Reset all the registers if needed */ needs_modeset = drm_atomic_crtc_needs_modeset(state->crtc->state); if (needs_modeset) { @@ -578,6 +590,11 @@ static void ingenic_ipu_plane_atomic_disable(struct drm_plane *plane, regmap_clear_bits(ipu->map, JZ_REG_IPU_CTRL, JZ_IPU_CTRL_CHIP_EN); ingenic_drm_plane_disable(ipu->master, plane); + + if (ipu->clk_enabled) { + clk_disable(ipu->clk); + ipu->clk_enabled = false; + } } static const struct drm_plane_helper_funcs ingenic_ipu_plane_helper_funcs = { @@ -761,9 +778,9 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d) drm_object_attach_property(&plane->base, ipu->sharpness_prop, ipu->sharpness); - err = clk_prepare_enable(ipu->clk); + err = clk_prepare(ipu->clk); if (err) { - dev_err(dev, "Unable to enable clock\n"); + dev_err(dev, "Unable to prepare clock\n"); return err; } @@ -775,7 +792,7 @@ static void ingenic_ipu_unbind(struct device *dev, { struct ingenic_ipu *ipu = dev_get_drvdata(dev); - clk_disable_unprepare(ipu->clk); + clk_unprepare(ipu->clk); } static const struct component_ops ingenic_ipu_ops = { -- GitLab From 473e2d16777030ca9b3a0178b179efdb2548b415 Mon Sep 17 00:00:00 2001 From: Stylon Wang <stylon.wang@amd.com> Date: Tue, 30 Jun 2020 17:55:29 +0800 Subject: [PATCH 0134/1494] drm/amd/display: Fix dmesg warning from setting abm level [Why] Setting abm level does not correctly update CRTC state. As a result no surface update is added to dc stream state and triggers warning. [How] Correctly update CRTC state when setting abm level property. CC: Stable <stable@vger.kernel.org> Signed-off-by: Stylon Wang <stylon.wang@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5109ee032b726..9b4808529a539 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8656,6 +8656,29 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; + /* Check connector changes */ + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + + /* Skip connectors that are disabled or part of modeset already. */ + if (!old_con_state->crtc && !new_con_state->crtc) + continue; + + if (!new_con_state->crtc) + continue; + + new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc); + if (IS_ERR(new_crtc_state)) { + ret = PTR_ERR(new_crtc_state); + goto fail; + } + + if (dm_old_con_state->abm_level != + dm_new_con_state->abm_level) + new_crtc_state->connectors_changed = true; + } + #if defined(CONFIG_DRM_AMD_DC_DCN) if (adev->asic_type >= CHIP_NAVI10) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { -- GitLab From 9b6ca29e093660241002c91e2c8abf771c726921 Mon Sep 17 00:00:00 2001 From: Jun Lei <jun.lei@amd.com> Date: Thu, 25 Jun 2020 13:24:12 -0400 Subject: [PATCH 0135/1494] drm/amd/display: Disable idle optimizations before programming DCN [Why] Programming DCN is explicitly forbidden during idle optimzations allowed state. Existing implemenation relies on OS/DM, which is not robust. Instead DC should sequence this. Note that DC will not re-enter idle optimized state on its own, it is only responsible for catching out of sequence calls. It is still DM responsibility to sequence appropriate for optimized power, but this change removes the requirement for DM to cover the .1% case. [How] - elevate updates during idle optimized state to full updates - disable idle power optimizations prior to programming Signed-off-by: Jun Lei <jun.lei@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ef0b5941bc500..92eb1ca1634fc 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1250,6 +1250,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c int i, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + dc_allow_idle_optimizations(dc, false); +#endif for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; @@ -1838,6 +1841,11 @@ static enum surface_update_type check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (dc->idle_optimizations_allowed) + overall_type = UPDATE_TYPE_FULL; + +#endif if (stream_status == NULL || stream_status->plane_count != surface_count) overall_type = UPDATE_TYPE_FULL; @@ -2306,8 +2314,14 @@ static void commit_planes_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FULL && dc->optimize_seamless_boot_streams == 0) { - dc->hwss.prepare_bandwidth(dc, context); + if (update_type == UPDATE_TYPE_FULL) { +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + dc_allow_idle_optimizations(dc, false); + +#endif + if (dc->optimize_seamless_boot_streams == 0) + dc->hwss.prepare_bandwidth(dc, context); + context_clock_trace(dc, context); } -- GitLab From cc0f379dd2bb34ee247222ff822b52319a755652 Mon Sep 17 00:00:00 2001 From: Reza Amini <Reza.Amini@amd.com> Date: Wed, 15 Jul 2020 11:33:23 -0400 Subject: [PATCH 0136/1494] drm/amd/display: Allow asic specific FSFT timing optimization [Why] Each asic can optimize best based on its capabilities [How] Optimizing timing for a new pixel clock Signed-off-by: Reza Amini <Reza.Amini@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_stream.c | 18 ++++++------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 4 +-- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 27 +++++++++++++++++++ .../drm/amd/display/dc/dcn20/dcn20_hwseq.h | 5 ++++ .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 3 +++ .../gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 3 +++ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 ++++ .../amd/display/modules/freesync/freesync.c | 5 +++- 8 files changed, 57 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10d69ada88e3d..0257a900fe2bb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -246,20 +246,18 @@ struct dc_stream_status *dc_stream_get_status( #ifndef TRIM_FSFT /** - * dc_optimize_timing() - dc to optimize timing + * dc_optimize_timing_for_fsft() - dc to optimize timing */ -bool dc_optimize_timing( - struct dc_crtc_timing *timing, +bool dc_optimize_timing_for_fsft( + struct dc_stream_state *pStream, unsigned int max_input_rate_in_khz) { - //optimization is expected to assing a value to these: - //timing->pix_clk_100hz - //timing->v_front_porch - //timing->v_total - //timing->fast_transport_output_rate_100hz; - timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz; + struct dc *dc; - return true; + dc = pStream->ctx->dc; + + return (dc->hwss.optimize_timing_for_fsft && + dc->hwss.optimize_timing_for_fsft(dc, &pStream->timing, max_input_rate_in_khz)); } #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index e4e85a1594624..633442bc7ef26 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -424,8 +424,8 @@ struct dc_stream_status *dc_stream_get_status( struct dc_stream_state *dc_stream); #ifndef TRIM_FSFT -bool dc_optimize_timing( - struct dc_crtc_timing *timing, +bool dc_optimize_timing_for_fsft( + struct dc_stream_state *pStream, unsigned int max_input_rate_in_khz); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 7725a406c16ee..66180b4332f1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2498,3 +2498,30 @@ void dcn20_fpga_init_hw(struct dc *dc) tg->funcs->tg_init(tg); } } +#ifndef TRIM_FSFT +bool dcn20_optimize_timing_for_fsft(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz) +{ + unsigned int old_v_front_porch; + unsigned int old_v_total; + unsigned int max_input_rate_in_100hz; + unsigned long long new_v_total; + + max_input_rate_in_100hz = max_input_rate_in_khz * 10; + if (max_input_rate_in_100hz < timing->pix_clk_100hz) + return false; + + old_v_total = timing->v_total; + old_v_front_porch = timing->v_front_porch; + + timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz; + timing->pix_clk_100hz = max_input_rate_in_100hz; + + new_v_total = div_u64((unsigned long long)old_v_total * max_input_rate_in_100hz, timing->pix_clk_100hz); + + timing->v_total = new_v_total; + timing->v_front_porch = old_v_front_porch + (timing->v_total - old_v_total); + return true; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 63ce763f148ec..83220e34c1a92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -132,5 +132,10 @@ int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); +#ifndef TRIM_FSFT +bool dcn20_optimize_timing_for_fsft(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz); +#endif #endif /* __DC_HWSS_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 2380392b916ed..3dde6f26de474 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -88,6 +88,9 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, +#ifndef TRIM_FSFT + .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, +#endif }; static const struct hwseq_private_funcs dcn20_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 177d0dc8927a6..b187f71afa652 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -92,6 +92,9 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, +#ifndef TRIM_FSFT + .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, +#endif }; static const struct hwseq_private_funcs dcn21_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 720ce5e458d80..3c986717dcd56 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -116,6 +116,11 @@ struct hw_sequencer_funcs { void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_params *events); +#ifndef TRIM_FSFT + bool (*optimize_timing_for_fsft)(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz); +#endif /* Stream Related */ void (*enable_stream)(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7a2500fbf3f29..81820f3d6b3b4 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -829,10 +829,13 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, switch (packet_type) { case PACKET_TYPE_FS_V3: #ifndef TRIM_FSFT + // always populate with pixel rate. build_vrr_infopacket_v3( stream->signal, vrr, stream->timing.flags.FAST_TRANSPORT, - stream->timing.fast_transport_output_rate_100hz, + (stream->timing.flags.FAST_TRANSPORT) ? + stream->timing.fast_transport_output_rate_100hz : + stream->timing.pix_clk_100hz, app_tf, infopacket); #else build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket); -- GitLab From 097e6d98c98fc79625e44c03c56924a6bb2569ef Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Tue, 14 Jul 2020 13:42:05 -0400 Subject: [PATCH 0137/1494] drm/amd/display: DSC Clock enable debugfs write entry [Why] Need a mechanism to force enable DSC on any connector [How] Debugfs entry overwrites newly added connector's dsc preffered settings structure and sets dsc_clock_en flag on it. During the attomic commit, depending if connector is SST or MST, we will enable DSC manually by overwriting stream's DSC flag. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 ++ .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 89 +++++++++++++++++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 ++- 4 files changed, 107 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9b4808529a539..eaec386b31c99 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4659,7 +4659,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, dc_link_get_link_cap(aconnector->dc_link)); #if defined(CONFIG_DRM_AMD_DC_DCN) - if (dsc_caps.is_dsc_supported) + if (dsc_caps.is_dsc_supported) { if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], &dsc_caps, aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, @@ -4667,6 +4667,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, &stream->timing, &stream->timing.dsc_cfg)) stream->timing.flags.DSC = 1; + if (aconnector->dsc_settings.dsc_clock_en) + stream->timing.flags.DSC = 1; + } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index dd1559c743c2c..56f50a309eba2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -342,6 +342,10 @@ struct amdgpu_display_manager { struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; }; +struct dsc_preferred_settings { + bool dsc_clock_en; +}; + struct amdgpu_dm_connector { struct drm_connector base; @@ -389,6 +393,7 @@ struct amdgpu_dm_connector { uint32_t debugfs_dpcd_size; #endif bool force_yuv420_output; + struct dsc_preferred_settings dsc_settings; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index e5a6d91159498..5322bc13af3c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -980,6 +980,21 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +/* function: read DSC status on the connector + * + * The read function: dp_dsc_clock_en_read + * returns current status of DSC clock on the connector. + * The return is a boolean flag: 1 or 0. + * + * Access it with the following command (you need to specify + * connector like DP-1): + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + * Expected output: + * 1 - means that DSC is currently enabled + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1037,6 +1052,79 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, return result; } +/* function: write force DSC on the connector + * + * The write function: dp_dsc_clock_en_write + * enables to force DSC on the connector. + * User can write to either force enable DSC + * on the next modeset or set it to driver default + * + * Writing DSC settings is done with the following command: + * - To force enable DSC (you need to specify + * connector like DP-1): + * + * echo 0x1 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + * - To return to default state set the flag to zero and + * let driver deal with DSC automatically + * (you need to specify connector like DP-1): + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + */ +static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_clock_en = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1446,6 +1534,7 @@ DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability); static const struct file_operations dp_dsc_clock_en_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_clock_en_read, + .write = dp_dsc_clock_en_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e85b58f0f4166..bb03aa6081234 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -450,6 +450,7 @@ struct dsc_mst_fairness_params { struct dc_dsc_bw_range bw_range; bool compression_possible; struct drm_dp_mst_port *port; + bool clock_overwrite; }; struct dsc_mst_fairness_vars { @@ -615,7 +616,9 @@ static void try_disable_dsc(struct drm_atomic_state *state, int remaining_to_try = 0; for (i = 0; i < count; i++) { - if (vars[i].dsc_enabled && vars[i].bpp_x16 == params[i].bw_range.max_target_bpp_x16) { + if (vars[i].dsc_enabled + && vars[i].bpp_x16 == params[i].bw_range.max_target_bpp_x16 + && !params[i].clock_overwrite) { kbps_increase[i] = params[i].bw_range.stream_kbps - params[i].bw_range.max_kbps; tried[i] = false; remaining_to_try += 1; @@ -676,6 +679,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, struct dsc_mst_fairness_vars vars[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; int count = 0; + bool debugfs_overwrite = false; memset(params, 0, sizeof(params)); @@ -694,6 +698,9 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].sink = stream->sink; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; params[count].port = aconnector->port; + params[count].clock_overwrite = aconnector->dsc_settings.dsc_clock_en; + if (params[count].clock_overwrite) + debugfs_overwrite = true; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( @@ -719,7 +726,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, dm_mst_get_pbn_divider(dc_link)) < 0) return false; } - if (!drm_dp_mst_atomic_check(state)) { + if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) { set_dsc_configs_from_fairness_vars(params, vars, count); return true; } -- GitLab From 68d90e066df1e14641749cc1821ff36452b64368 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Sat, 18 Jul 2020 15:25:22 -0400 Subject: [PATCH 0138/1494] drm/amd/display: [FW Promotion] Release 0.0.26 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index e013875b89ed4..8b27cf0f1d513 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xe6d590b09 +#define DMUB_FW_VERSION_GIT_HASH 0x636e7b294 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 25 +#define DMUB_FW_VERSION_REVISION 26 #define DMUB_FW_VERSION_UCODE ((DMUB_FW_VERSION_MAJOR << 24) | (DMUB_FW_VERSION_MINOR << 16) | DMUB_FW_VERSION_REVISION) #endif -- GitLab From 31f34d19f87ee9fa475bc8556e298ea1ec3e7e1d Mon Sep 17 00:00:00 2001 From: hersen wu <hersenxs.wu@amd.com> Date: Sun, 19 Jul 2020 17:21:59 -0400 Subject: [PATCH 0139/1494] drm/amd/display: dchubbub p-state warning during surface planes switch [Why] ramp_up_dispclk_with_dpp is to change dispclk, dppclk and dprefclk according to bandwidth requirement. call stack: rv1_update_clocks --> update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, prepare_bandwidth will be called first to allow enough clock, watermark for change, after end of dcn hw change, optimize_bandwidth is executed to lower clock to save power for new dcn hw settings. below is sequence of commit_planes_for_stream: step 1: prepare_bandwidth - raise clock to have enough bandwidth step 2: lock_doublebuffer_enable step 3: pipe_control_lock(true) - make dchubp register change will not take effect right way step 4: apply_ctx_for_surface - program dchubp step 5: pipe_control_lock(false) - dchubp register change take effect step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream for full_date, optimize clock to save power at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be changed for new dchubp configuration. but real dcn hub dchubps are still running with old configuration until end of step 5. this need clocks settings at step 1 should not less than that before step 1. this is checked by two conditions: 1. if (should_set_clock(safe_to_lower , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz the second condition is based on new dchubp configuration. dppclk for new dchubp may be different from dppclk before step 1. for example, before step 1, dchubps are as below: pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) for dppclk for pipe0 need dppclk = dispclk new dchubp pipe split configuration: pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) dppclk only needs dppclk = dispclk /2. dispclk, dppclk are not lock by otg master lock. they take effect after step 1. during this transition, dispclk are the same, but dppclk is changed to half of previous clock for old dchubp configuration between step 1 and step 6. This may cause p-state warning intermittently. [How] for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we need make sure dppclk are not changed to less between step 1 and 6. for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, new display clock is raised, but we do not know ratio of new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, new_clocks->dispclk_khz /2 does not guarantee equal or higher than old dppclk. we could ignore power saving different between dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. as long as safe_to_lower = false, set dpclk = dispclk to simplify condition check. CC: Stable <stable@vger.kernel.org> Signed-off-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../display/dc/clk_mgr/dcn10/rv1_clk_mgr.c | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c index 3fab9296918ab..e133edc587d31 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c @@ -85,12 +85,77 @@ static int rv1_determine_dppclk_threshold(struct clk_mgr_internal *clk_mgr, stru return disp_clk_threshold; } -static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc *dc, struct dc_clocks *new_clocks) +static void ramp_up_dispclk_with_dpp( + struct clk_mgr_internal *clk_mgr, + struct dc *dc, + struct dc_clocks *new_clocks, + bool safe_to_lower) { int i; int dispclk_to_dpp_threshold = rv1_determine_dppclk_threshold(clk_mgr, new_clocks); bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; + /* this function is to change dispclk, dppclk and dprefclk according to + * bandwidth requirement. Its call stack is rv1_update_clocks --> + * update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth + * --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, + * prepare_bandwidth will be called first to allow enough clock, + * watermark for change, after end of dcn hw change, optimize_bandwidth + * is executed to lower clock to save power for new dcn hw settings. + * + * below is sequence of commit_planes_for_stream: + * + * step 1: prepare_bandwidth - raise clock to have enough bandwidth + * step 2: lock_doublebuffer_enable + * step 3: pipe_control_lock(true) - make dchubp register change will + * not take effect right way + * step 4: apply_ctx_for_surface - program dchubp + * step 5: pipe_control_lock(false) - dchubp register change take effect + * step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream + * for full_date, optimize clock to save power + * + * at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be + * changed for new dchubp configuration. but real dcn hub dchubps are + * still running with old configuration until end of step 5. this need + * clocks settings at step 1 should not less than that before step 1. + * this is checked by two conditions: 1. if (should_set_clock(safe_to_lower + * , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || + * new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) + * 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz + * + * the second condition is based on new dchubp configuration. dppclk + * for new dchubp may be different from dppclk before step 1. + * for example, before step 1, dchubps are as below: + * pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) + * pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) + * for dppclk for pipe0 need dppclk = dispclk + * + * new dchubp pipe split configuration: + * pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) + * pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) + * dppclk only needs dppclk = dispclk /2. + * + * dispclk, dppclk are not lock by otg master lock. they take effect + * after step 1. during this transition, dispclk are the same, but + * dppclk is changed to half of previous clock for old dchubp + * configuration between step 1 and step 6. This may cause p-state + * warning intermittently. + * + * for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we + * need make sure dppclk are not changed to less between step 1 and 6. + * for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, + * new display clock is raised, but we do not know ratio of + * new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, + * new_clocks->dispclk_khz /2 does not guarantee equal or higher than + * old dppclk. we could ignore power saving different between + * dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. + * as long as safe_to_lower = false, set dpclk = dispclk to simplify + * condition check. + * todo: review this change for other asic. + **/ + if (!safe_to_lower) + request_dpp_div = false; + /* set disp clk to dpp clk threshold */ clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold); @@ -209,7 +274,7 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, /* program dispclk on = as a w/a for sleep resume clock ramping issues */ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) { - ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks); + ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks, safe_to_lower); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; send_request_to_lower = true; } -- GitLab From 42a614800b0647af3c4944f2ac04eb1613b30161 Mon Sep 17 00:00:00 2001 From: Wyatt Wood <wyatt.wood@amd.com> Date: Wed, 17 Jun 2020 11:29:27 -0400 Subject: [PATCH 0140/1494] drm/amd/display: Use hw lock mgr [Why] Feature requires synchronization of dig, pipe, and cursor locking between driver and fw. [How] Set flag to force psr to use hw lock mgr. Signed-off-by: Wyatt Wood <wyatt.wood@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 82e67bd81f2df..5167d6b8a48de 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -233,8 +233,8 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR ? true : false; + copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; - copy_settings_data->debug.bitfields.use_hw_lock_mgr = 0; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); -- GitLab From 27e84dd7b4490fad29118d5bddfc0018f38a1c66 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Wed, 17 Jun 2020 14:39:50 -0400 Subject: [PATCH 0141/1494] drm/amd/display: DSC Slice width debugfs write entry [Why] We need to be able to specify slice width for DSC on aconnector [How] Getting slice width parameter from debugfs entry, if it is a valid the value is set in connector's dsc preffered settings structure. Which then overwrites dsc_cfg structure's parameters if DSC is decided to be enabled. Works for both SST and MST. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 93 +++++++++++++++++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++ 4 files changed, 104 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index eaec386b31c99..09da24e8806f8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4667,8 +4667,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, &stream->timing, &stream->timing.dsc_cfg)) stream->timing.flags.DSC = 1; + /* Overwrite the stream flag if DSC is enabled through debugfs */ if (aconnector->dsc_settings.dsc_clock_en) stream->timing.flags.DSC = 1; + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) + stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable, + aconnector->dsc_settings.dsc_slice_width); } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 56f50a309eba2..a06ad133a23a8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -344,6 +344,7 @@ struct amdgpu_display_manager { struct dsc_preferred_settings { bool dsc_clock_en; + uint32_t dsc_slice_width; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 5322bc13af3c9..550138012123e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1125,6 +1125,22 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, return size; } +/* function: read DSC slice width parameter on the connector + * + * The read function: dp_dsc_slice_width_read + * returns dsc slice width used in the current configuration + * The return is an integer: 0 or other positive number + * + * Access the status with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + * 0 - means that DSC is disabled + * + * Any other number more than zero represents the + * slice width currently used by DSC in pixels + * + */ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1182,6 +1198,82 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, return result; } +/* function: write DSC slice width parameter + * + * The write function: dp_dsc_slice_width_write + * overwrites automatically generated DSC configuration + * of slice width. + * + * The user has to write the slice width divisible by the + * picture width. + * + * Also the user has to write width in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite slice width: (example sets to 1920 pixels) + * + * echo 0x780 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + * - To stop overwriting and let driver find the optimal size, + * set the width to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + */ +static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_slice_width = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1541,6 +1633,7 @@ static const struct file_operations dp_dsc_clock_en_debugfs_fops = { static const struct file_operations dp_dsc_slice_width_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_slice_width_read, + .write = dp_dsc_slice_width_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index bb03aa6081234..b8a900e963d3f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -451,6 +451,7 @@ struct dsc_mst_fairness_params { bool compression_possible; struct drm_dp_mst_port *port; bool clock_overwrite; + uint32_t slice_width_overwrite; }; struct dsc_mst_fairness_vars { @@ -485,6 +486,10 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p ¶ms[i].timing->dsc_cfg)) { params[i].timing->flags.DSC = 1; params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + if (params[i].slice_width_overwrite) + params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( + params[i].timing->h_addressable, + params[i].slice_width_overwrite); } else { params[i].timing->flags.DSC = 0; } @@ -701,6 +706,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].clock_overwrite = aconnector->dsc_settings.dsc_clock_en; if (params[count].clock_overwrite) debugfs_overwrite = true; + params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- GitLab From 746565c25abf9e0bc603aaf520cb33bed7510842 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 20 Jul 2020 11:07:46 -0400 Subject: [PATCH 0142/1494] drm/amd/display: 3.2.96 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f50ef4255020a..ae0e27c67ef9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.95" +#define DC_VER "3.2.96" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From d9b91b1ea26b0e528c44c12f9b5637ba41b9006c Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Wed, 22 Jul 2020 15:40:06 -0400 Subject: [PATCH 0143/1494] drm/amd/display: Fix DP Compliance tests 4.3.2.1 and 4.3.2.2 [Why] Test expects that we also read HPD_IRQ_VECTOR when checking for symbol loss as well lane status. [How] Read bytes 0x200-0x205 instead of just 0x202-0x205 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 1a3dbed3becbd..d7d2dcd49c062 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1138,23 +1138,22 @@ static enum link_training_result check_link_loss_status( const struct link_training_settings *link_training_setting) { enum link_training_result status = LINK_TRAINING_SUCCESS; - unsigned int lane01_status_address = DP_LANE0_1_STATUS; union lane_status lane_status; - uint8_t dpcd_buf[4] = {0}; + uint8_t dpcd_buf[6] = {0}; uint32_t lane; core_link_read_dpcd( - link, - lane01_status_address, - (uint8_t *)(dpcd_buf), - sizeof(dpcd_buf)); + link, + DP_SINK_COUNT, + (uint8_t *)(dpcd_buf), + sizeof(dpcd_buf)); /*parse lane status*/ for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { /* * check lanes status */ - lane_status.raw = get_nibble_at_index(&dpcd_buf[0], lane); + lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane); if (!lane_status.bits.CHANNEL_EQ_DONE_0 || !lane_status.bits.CR_DONE_0 || -- GitLab From 35dab589de1309c485935ede35870adf155bba6e Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Mon, 27 Jul 2020 16:19:45 +0800 Subject: [PATCH 0144/1494] drm/amdgpu: skip crit temperature values on APU (v2) It doesn't expose PPTable descriptor on APU platform. So max/min temperature values cannot be got from APU platform. v2: Stoney needs to skip crit temperature as well. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 581b2d6bea3b2..f44157daf3ec3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -3467,6 +3467,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) return 0; + /* Skip crit temp on APU */ + if ((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ) && + (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) + return 0; + /* Skip limit attributes if DPM is not enabled */ if (!adev->pm.dpm_enabled && (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || -- GitLab From 01eee24fceb9a64b2dc3b3ccb7b7c6852aa7a403 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Tue, 28 Jul 2020 14:22:54 +0800 Subject: [PATCH 0145/1494] drm/amdgpu: enable umc 8.7 functions in gmc v10 add support for umc 8.7 initialization add umc 8.7 source to makefile Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 50 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 403ec3db29df5..0ba396e9d7e40 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -85,7 +85,7 @@ amdgpu-y += \ # add UMC block amdgpu-y += \ - umc_v6_1.o umc_v6_0.o + umc_v6_1.o umc_v6_0.o umc_v8_7.o # add IH block amdgpu-y += \ diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 1a78073c2f053..35d21f330b0ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -25,6 +25,7 @@ #include "amdgpu.h" #include "amdgpu_atomfirmware.h" #include "gmc_v10_0.h" +#include "umc_v8_7.h" #include "hdp/hdp_5_0_0_offset.h" #include "hdp/hdp_5_0_0_sh_mask.h" @@ -55,6 +56,14 @@ static const struct soc15_reg_golden golden_settings_navi10_hdp[] = }; #endif +static int gmc_v10_0_ecc_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + static int gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, @@ -131,10 +140,20 @@ static const struct amdgpu_irq_src_funcs gmc_v10_0_irq_funcs = { .process = gmc_v10_0_process_interrupt, }; -static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev) +static const struct amdgpu_irq_src_funcs gmc_v10_0_ecc_funcs = { + .set = gmc_v10_0_ecc_interrupt_state, + .process = amdgpu_umc_process_ecc_irq, +}; + + static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev) { adev->gmc.vm_fault.num_types = 1; adev->gmc.vm_fault.funcs = &gmc_v10_0_irq_funcs; + + if (!amdgpu_sriov_vf(adev)) { + adev->gmc.ecc_irq.num_types = 1; + adev->gmc.ecc_irq.funcs = &gmc_v10_0_ecc_funcs; + } } /** @@ -569,12 +588,29 @@ static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev) adev->gmc.gmc_funcs = &gmc_v10_0_gmc_funcs; } +static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + adev->umc.max_ras_err_cnt_per_query = UMC_V8_7_TOTAL_CHANNEL_NUM; + adev->umc.channel_inst_num = UMC_V8_7_CHANNEL_INSTANCE_NUM; + adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM; + adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA; + adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0]; + adev->umc.funcs = &umc_v8_7_funcs; + break; + default: + break; + } +} + static int gmc_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; gmc_v10_0_set_gmc_funcs(adev); gmc_v10_0_set_irq_funcs(adev); + gmc_v10_0_set_umc_funcs(adev); adev->gmc.shared_aperture_start = 0x2000000000000000ULL; adev->gmc.shared_aperture_end = @@ -790,6 +826,14 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; + if (!amdgpu_sriov_vf(adev)) { + /* interrupt sent to DF. */ + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0, + &adev->gmc.ecc_irq); + if (r) + return r; + } + /* * Set the internal MC address mask This is the max address of the GPU's * internal address space. @@ -950,6 +994,9 @@ static int gmc_v10_0_hw_init(void *handle) if (r) return r; + if (adev->umc.funcs && adev->umc.funcs->init_registers) + adev->umc.funcs->init_registers(adev); + return 0; } @@ -981,6 +1028,7 @@ static int gmc_v10_0_hw_fini(void *handle) return 0; } + amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); gmc_v10_0_gart_disable(adev); -- GitLab From da82cbd8328ff7574d5f42c09562572890338309 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Tue, 28 Jul 2020 19:14:22 +0800 Subject: [PATCH 0146/1494] drm/amd/powerplay: update driver if version for navy_flounder It's in accordance with pmfw 65.5.0 for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 9504f9954fd3f..6a42331aba8aa 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -31,7 +31,7 @@ #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x34 -#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x2 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 /* MP Apertures */ #define MP0_Public 0x03800000 -- GitLab From defa489636a67bb64ecd3bd9ae9ddedb163adccf Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 29 Jul 2020 11:58:21 +0800 Subject: [PATCH 0147/1494] drm/amdgpu: update GC golden setting for navy_flounder Update GC golden setting for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index db9f1e89a0f83..ca16f01956d3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3127,7 +3127,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA0_CLK_CTRL, 0xff7f0fff, 0x30000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA1_CLK_CTRL, 0xff7f0fff, 0x7e000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCPF_GCR_CNTL, 0x0007ffff, 0x0000c000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500), @@ -3158,7 +3158,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER7_SELECT, 0xf0f001ff, 0x00000000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER8_SELECT, 0xf0f001ff, 0x00000000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER9_SELECT, 0xf0f001ff, 0x00000000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xffffffff, 0x010b0000), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff) }; -- GitLab From 7619517598ad5ba04beb855cde6558e72c73dbb5 Mon Sep 17 00:00:00 2001 From: Mazin Rezk <mnrzk@protonmail.com> Date: Mon, 27 Jul 2020 05:40:46 +0000 Subject: [PATCH 0148/1494] drm/amd/display: Clear dm_state for fast updates This patch fixes a race condition that causes a use-after-free during amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits are requested and the second one finishes before the first. Essentially, this bug occurs when the following sequence of events happens: 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is deferred to the workqueue. 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is deferred to the workqueue. 3. Commit #2 starts before commit #1, dm_state #1 is used in the commit_tail and commit #2 completes, freeing dm_state #1. 4. Commit #1 starts after commit #2 completes, uses the freed dm_state 1 and dereferences a freelist pointer while setting the context. Since this bug has only been spotted with fast commits, this patch fixes the bug by clearing the dm_state instead of using the old dc_state for fast updates. In addition, since dm_state is only used for its dc_state and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, removing the dm_state should not have any consequences in fast updates. This use-after-free bug has existed for a while now, but only caused a noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate freelist pointer to middle of object") moving the freelist pointer from dm_state->base (which was unused) to dm_state->context (which is dereferenced). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates") Reported-by: Duncan <1i5t5.duncan@cox.net> Signed-off-by: Mazin Rezk <mnrzk@protonmail.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 09da24e8806f8..4b32862879130 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8901,20 +8901,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, * the same resource. If we have a new DC context as part of * the DM atomic state from validation we need to free it and * retain the existing one instead. + * + * Furthermore, since the DM atomic state only contains the DC + * context and can safely be annulled, we can free the state + * and clear the associated private object now to free + * some memory and avoid a possible use-after-free later. */ - struct dm_atomic_state *new_dm_state, *old_dm_state; - new_dm_state = dm_atomic_get_new_state(state); - old_dm_state = dm_atomic_get_old_state(state); + for (i = 0; i < state->num_private_objs; i++) { + struct drm_private_obj *obj = state->private_objs[i].ptr; - if (new_dm_state && old_dm_state) { - if (new_dm_state->context) - dc_release_state(new_dm_state->context); + if (obj->funcs == adev->dm.atomic_obj.funcs) { + int j = state->num_private_objs-1; - new_dm_state->context = old_dm_state->context; + dm_atomic_destroy_state(obj, + state->private_objs[i].state); + + /* If i is not at the end of the array then the + * last element needs to be moved to where i was + * before the array can safely be truncated. + */ + if (i != j) + state->private_objs[i] = + state->private_objs[j]; - if (old_dm_state->context) - dc_retain_state(old_dm_state->context); + state->private_objs[j].ptr = NULL; + state->private_objs[j].state = NULL; + state->private_objs[j].old_state = NULL; + state->private_objs[j].new_state = NULL; + + state->num_private_objs = j; + break; + } } } -- GitLab From 8e326285924cd13d9d94edc209440ef5b6f85085 Mon Sep 17 00:00:00 2001 From: Peilin Ye <yepeilin.cs@gmail.com> Date: Tue, 28 Jul 2020 15:29:24 -0400 Subject: [PATCH 0149/1494] drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compiler leaves a 4-byte hole near the end of `dev_info`, causing amdgpu_info_ioctl() to copy uninitialized kernel stack memory to userspace when `size` is greater than 356. In 2015 we tried to fix this issue by doing `= {};` on `dev_info`, which unfortunately does not initialize that 4-byte hole. Fix it by using memset() instead. Cc: stable@vger.kernel.org Fixes: c193fa91b918 ("drm/amdgpu: information leak in amdgpu_info_ioctl()") Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") Suggested-by: Dan Carpenter <dan.carpenter@oracle.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Peilin Ye <yepeilin.cs@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index b9c1fce6da793..e99ad031efd41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -707,9 +707,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return n ? -EFAULT : 0; } case AMDGPU_INFO_DEV_INFO: { - struct drm_amdgpu_info_device dev_info = {}; + struct drm_amdgpu_info_device dev_info; uint64_t vm_size; + memset(&dev_info, 0, sizeof(dev_info)); dev_info.device_id = dev->pdev->device; dev_info.chip_rev = adev->rev_id; dev_info.external_rev = adev->external_rev_id; -- GitLab From 317469f695c27e290b8001a0df0fdbb95f27bfa9 Mon Sep 17 00:00:00 2001 From: Li Heng <liheng40@huawei.com> Date: Wed, 29 Jul 2020 16:34:01 +0800 Subject: [PATCH 0150/1494] drm/amd/powerplay: Remove unneeded cast from memory allocation Remove casting the values returned by memory allocation function. Coccinelle emits WARNING: ./drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c:893:37-46: WARNING: casting value returned by memory allocation function to (PPTable_t *) is useless. Signed-off-by: Li Heng <liheng40@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c index 7a7f15d0c53af..f56a3cbdfa3b3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c @@ -890,7 +890,7 @@ static int init_powerplay_table_information( power_saving_clock_count); } - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; -- GitLab From 178b0013f074da545492662ec76dc2be363ca85c Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Mon, 27 Jul 2020 23:30:18 +0200 Subject: [PATCH 0151/1494] drm/amdgpu/dc: Stop dma_resv_lock inversion in commit_tail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to grab dma_resv_lock while in commit_tail before we've done all the code that leads to the eventual signalling of the vblank event (which can be a dma_fence) is deadlock-y. Don't do that. Here the solution is easy because just grabbing locks to read something races anyway. We don't need to bother, READ_ONCE is equivalent. And avoids the locking issue. v2: Also take into account tmz_surface boolean, plus just delete the old code. Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Cc: linux-rdma@vger.kernel.org Cc: amd-gfx@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Christian König <christian.koenig@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4b32862879130..342663fcd44d7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7081,20 +7081,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("Waiting for fences timed out!"); /* - * TODO This might fail and hence better not used, wait - * explicitly on fences instead - * and in general should be called for - * blocking commit to as per framework helpers + * We cannot reserve buffers here, which means the normal flag + * access functions don't work. Paper over this with READ_ONCE, + * but maybe the flags are invariant enough that not even that + * would be needed. */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) - DRM_ERROR("failed to reserve buffer before flip\n"); - - amdgpu_bo_get_tiling_flags(abo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(abo); - - amdgpu_bo_unreserve(abo); + tiling_flags = READ_ONCE(abo->tiling_flags); + tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; fill_dc_plane_info_and_addr( dm->adev, new_plane_state, tiling_flags, -- GitLab From 392cf6a739271a70311b6a3c4f60900039721a68 Mon Sep 17 00:00:00 2001 From: Liu ChengZhe <ChengZhe.Liu@amd.com> Date: Fri, 24 Jul 2020 17:22:15 +0800 Subject: [PATCH 0152/1494] drm/amdgpu: fix PSP autoload twice in FLR Assigning false to block->status.hw overwrites PSP's previous hardware status, which causes the PSP to Resume operation after hardware init. Remove this assignment and let the PSP execute Resume operation when it is told to. v2: Remove the braces. v3: Modify the description. Signed-off-by: Liu ChengZhe <ChengZhe.Liu@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 638c2cc426c15..40caa7437ce24 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2574,6 +2574,9 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; + for (i = 0; i < adev->num_ip_blocks; i++) + adev->ip_blocks[i].status.hw = false; + for (i = 0; i < ARRAY_SIZE(ip_order); i++) { int j; struct amdgpu_ip_block *block; @@ -2581,7 +2584,6 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) for (j = 0; j < adev->num_ip_blocks; j++) { block = &adev->ip_blocks[j]; - block->status.hw = false; if (block->version->type != ip_order[i] || !block->status.valid) continue; -- GitLab From f61772cd132e09bd9e0b52627d8a82631e860a10 Mon Sep 17 00:00:00 2001 From: Liu ChengZhe <ChengZhe.Liu@amd.com> Date: Fri, 24 Jul 2020 15:55:33 +0800 Subject: [PATCH 0153/1494] drm amdgpu: Skip tmr load for SRIOV 1. For Navi12, CHIP_SIENNA_CICHLID, skip tmr load operation; 2. Check pointer before release firmware. v2: use CHIP_SIENNA_CICHLID instead v3: remove local "bool ret"; fix grammer issue v4: use my name instead of "root" v5: fix grammer issue and indent issue Signed-off-by: Liu ChengZhe <ChengZhe.Liu@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 35 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index a053b7af06802..c68369731b20a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -193,12 +193,18 @@ static int psp_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; psp_memory_training_fini(&adev->psp); - release_firmware(adev->psp.sos_fw); - adev->psp.sos_fw = NULL; - release_firmware(adev->psp.asd_fw); - adev->psp.asd_fw = NULL; - release_firmware(adev->psp.ta_fw); - adev->psp.ta_fw = NULL; + if (adev->psp.sos_fw) { + release_firmware(adev->psp.sos_fw); + adev->psp.sos_fw = NULL; + } + if (adev->psp.asd_fw) { + release_firmware(adev->psp.asd_fw); + adev->psp.asd_fw = NULL; + } + if (adev->psp.ta_fw) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + } if (adev->asic_type == CHIP_NAVI10) psp_sysfs_fini(adev); @@ -409,11 +415,28 @@ static int psp_clear_vf_fw(struct psp_context *psp) return ret; } +static bool psp_skip_tmr(struct psp_context *psp) +{ + switch (psp->adev->asic_type) { + case CHIP_NAVI12: + case CHIP_SIENNA_CICHLID: + return true; + default: + return false; + } +} + static int psp_tmr_load(struct psp_context *psp) { int ret; struct psp_gfx_cmd_resp *cmd; + /* For Navi12 and CHIP_SIENNA_CICHLID SRIOV, do not set up TMR. + * Already set up by host driver. + */ + if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) + return 0; + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); if (!cmd) return -ENOMEM; -- GitLab From 74b3595913cc22efe77dbdf2f00bf33b9243f566 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Thu, 30 Jul 2020 18:09:47 +0800 Subject: [PATCH 0154/1494] drm/amdgpu: enable GFXOFF for navy_flounder Enable GFXOFF for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Likun Gao <Likun.Gao@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index ca16f01956d3c..fe8ccc9be6827 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7529,6 +7529,7 @@ static int gfx_v10_0_set_powergating_state(void *handle, case CHIP_NAVI14: case CHIP_NAVI12: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: amdgpu_gfx_off_ctrl(adev, enable); break; default: diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index a9453ec01619d..7d7de854a826e 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1029,6 +1029,7 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) case CHIP_NAVI14: case CHIP_NAVI12: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) -- GitLab From 2456c290a7889be492cb96092b62d16c11176f72 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 30 Jul 2020 11:02:30 -0400 Subject: [PATCH 0155/1494] Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers" This regressed some working configurations so revert it. Will fix this properly for 5.9 and backport then. This reverts commit 38e0c89a19fd13f28d2b4721035160a3e66e270b. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f44157daf3ec3..576e3ac983657 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -872,7 +872,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, tmp_str++; while (isspace(*++tmp_str)); - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; @@ -1165,7 +1166,8 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) memcpy(buf_cpy, buf, bytes); buf_cpy[bytes] = '\0'; tmp = buf_cpy; - while ((sub_str = strsep(&tmp, delimiter)) != NULL) { + while (tmp[0]) { + sub_str = strsep(&tmp, delimiter); if (strlen(sub_str)) { ret = kstrtol(sub_str, 0, &level); if (ret) @@ -1858,7 +1860,8 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, i++; memcpy(buf_cpy, buf, count-i); tmp_str = buf_cpy; - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; -- GitLab From 418d2ad1ac521acc46f74f6bcbc8c1158d077346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 20 Jul 2020 14:41:31 +0200 Subject: [PATCH 0156/1494] drm/ttm: initialize the system domain with defaults v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of repeating that in each driver. v2: keep the caching limitation for VMWGFX for now. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/382078/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 --- drivers/gpu/drm/drm_gem_vram_helper.c | 3 --- drivers/gpu/drm/nouveau/nouveau_bo.c | 3 --- drivers/gpu/drm/qxl/qxl_ttm.c | 3 --- drivers/gpu/drm/radeon/radeon_ttm.c | 3 --- drivers/gpu/drm/ttm/ttm_bo.c | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 1 - 7 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 0dd5e802091d8..e57c49a91b73c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -84,9 +84,6 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: /* System memory */ - man->flags = 0; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_TT: /* GTT memory */ diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 3296ed3df3580..be177afdeb9ab 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1009,9 +1009,6 @@ static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, { switch (type) { case TTM_PL_SYSTEM: - man->flags = 0; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: man->func = &ttm_bo_manager_func; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 4ccf937df0d0d..53af25020bb2a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -655,9 +655,6 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: - man->flags = 0; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: man->flags = TTM_MEMTYPE_FLAG_FIXED; diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 1d8e07b8b19e8..e9b8c921c1f0d 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -54,9 +54,6 @@ static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: /* System memory */ - man->flags = 0; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: case TTM_PL_PRIV: diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b474781a0920d..b4cb753615779 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -76,9 +76,6 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, switch (type) { case TTM_PL_SYSTEM: /* System memory */ - man->flags = 0; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_TT: man->func = &ttm_bo_manager_func; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 469aa93ea3175..b5608a0087a92 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1673,6 +1673,8 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, * Initialize the system memory buffer type. * Other types need to be driver / IOCTL initialized. */ + bdev->man[TTM_PL_SYSTEM].available_caching = TTM_PL_MASK_CACHING; + bdev->man[TTM_PL_SYSTEM].default_caching = TTM_PL_FLAG_CACHED; ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); if (unlikely(ret != 0)) goto out_no_sys; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 1d78187eaba6a..b2761a4b49922 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -743,7 +743,6 @@ static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_SYSTEM: /* System memory */ man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: /* "On-card" video ram */ -- GitLab From be1213a341a289afc51f89181c310e368fba0b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Tue, 21 Jul 2020 09:58:13 +0200 Subject: [PATCH 0157/1494] drm/ttm: remove TTM_MEMTYPE_FLAG_FIXED v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead use a boolean field in the memory manager structure. Also invert the meaning of the field since the use of a TT structure is the special case here. v2: cleanup zero init. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382079/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +--- drivers/gpu/drm/drm_gem_vram_helper.c | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +--- drivers/gpu/drm/qxl/qxl_ttm.c | 1 - drivers/gpu/drm/radeon/radeon_ttm.c | 3 +-- drivers/gpu/drm/ttm/ttm_bo.c | 19 ++++++++++--------- drivers/gpu/drm/ttm/ttm_bo_util.c | 12 ++++++------ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 3 ++- include/drm/ttm/ttm_bo_driver.h | 4 +--- 9 files changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e57c49a91b73c..406bcb03df485 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -87,15 +87,14 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_TT: /* GTT memory */ + man->use_tt = true; man->func = &amdgpu_gtt_mgr_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - man->flags = 0; break; case TTM_PL_VRAM: /* "On-card" video ram */ man->func = &amdgpu_vram_mgr_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; @@ -104,7 +103,6 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case AMDGPU_PL_OA: /* On-chip GDS memory*/ man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED; man->default_caching = TTM_PL_FLAG_UNCACHED; break; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index be177afdeb9ab..801a14c6e9e02 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1012,7 +1012,6 @@ static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_VRAM: man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 53af25020bb2a..a3ad66ad38175 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -657,7 +657,6 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_SYSTEM: break; case TTM_PL_VRAM: - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -685,13 +684,12 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, else man->func = &ttm_bo_manager_func; + man->use_tt = true; if (drm->agp.bridge) { - man->flags = 0; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; } else { - man->flags = 0; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; } diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index e9b8c921c1f0d..abb9fa4d80cf9 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -59,7 +59,6 @@ static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_PRIV: /* "On-card" video ram */ man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; break; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b4cb753615779..9aba18a143e71 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -81,7 +81,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - man->flags = 0; + man->use_tt = true; #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { if (!rdev->ddev->agp) { @@ -98,7 +98,6 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_VRAM: /* "On-card" video ram */ man->func = &ttm_bo_manager_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b5608a0087a92..9d316f33e6a6a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -84,7 +84,7 @@ static void ttm_mem_type_debug(struct ttm_bo_device *bdev, struct drm_printer *p drm_printf(p, " has_type: %d\n", man->has_type); drm_printf(p, " use_type: %d\n", man->use_type); - drm_printf(p, " flags: 0x%08X\n", man->flags); + drm_printf(p, " use_tt: %d\n", man->use_tt); drm_printf(p, " size: %llu\n", man->size); drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); drm_printf(p, " default_caching: 0x%08X\n", man->default_caching); @@ -159,7 +159,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, man = &bdev->man[mem->mem_type]; list_add_tail(&bo->lru, &man->lru[bo->priority]); - if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm && + if (man->use_tt && bo->ttm && !(bo->ttm->page_flags & (TTM_PAGE_FLAG_SG | TTM_PAGE_FLAG_SWAPPED))) { list_add_tail(&bo->swap, &ttm_bo_glob.swap_lru[bo->priority]); @@ -286,10 +286,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, * Create and bind a ttm if required. */ - if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) { - bool zero = !(old_man->flags & TTM_MEMTYPE_FLAG_FIXED); - - ret = ttm_tt_create(bo, zero); + if (new_man->use_tt) { + /* Zero init the new TTM structure if the old location should + * have used one as well. + */ + ret = ttm_tt_create(bo, old_man->use_tt); if (ret) goto out_err; @@ -314,8 +315,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, if (bdev->driver->move_notify) bdev->driver->move_notify(bo, evict, mem); - if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && - !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) + if (old_man->use_tt && new_man->use_tt) ret = ttm_bo_move_ttm(bo, ctx, mem); else if (bdev->driver->move) ret = bdev->driver->move(bo, evict, ctx, mem); @@ -340,7 +340,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, out_err: new_man = &bdev->man[bo->mem.mem_type]; - if (new_man->flags & TTM_MEMTYPE_FLAG_FIXED) { + if (!new_man->use_tt) { ttm_tt_destroy(bo->ttm); bo->ttm = NULL; } @@ -1673,6 +1673,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, * Initialize the system memory buffer type. * Other types need to be driver / IOCTL initialized. */ + bdev->man[TTM_PL_SYSTEM].use_tt = true; bdev->man[TTM_PL_SYSTEM].available_caching = TTM_PL_MASK_CACHING; bdev->man[TTM_PL_SYSTEM].default_caching = TTM_PL_FLAG_CACHED; ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 7fb3e0bcbab42..1f502be0b646c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -384,7 +384,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, *old_mem = *new_mem; new_mem->mm_node = NULL; - if (man->flags & TTM_MEMTYPE_FLAG_FIXED) { + if (!man->use_tt) { ttm_tt_destroy(ttm); bo->ttm = NULL; } @@ -645,7 +645,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (ret) return ret; - if (man->flags & TTM_MEMTYPE_FLAG_FIXED) { + if (!man->use_tt) { ttm_tt_destroy(bo->ttm); bo->ttm = NULL; } @@ -674,7 +674,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * bo to be unbound and destroyed. */ - if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) + if (man->use_tt) ghost_obj->ttm = NULL; else bo->ttm = NULL; @@ -730,7 +730,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, * bo to be unbound and destroyed. */ - if (!(to->flags & TTM_MEMTYPE_FLAG_FIXED)) + if (to->use_tt) ghost_obj->ttm = NULL; else bo->ttm = NULL; @@ -738,7 +738,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, dma_resv_unlock(&ghost_obj->base._resv); ttm_bo_put(ghost_obj); - } else if (from->flags & TTM_MEMTYPE_FLAG_FIXED) { + } else if (!from->use_tt) { /** * BO doesn't have a TTM we need to bind/unbind. Just remember @@ -768,7 +768,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, if (ret) return ret; - if (to->flags & TTM_MEMTYPE_FLAG_FIXED) { + if (!to->use_tt) { ttm_tt_destroy(bo->ttm); bo->ttm = NULL; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index b2761a4b49922..d00748ecaf202 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -747,7 +747,6 @@ static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, case TTM_PL_VRAM: /* "On-card" video ram */ man->func = &vmw_thp_func; - man->flags = TTM_MEMTYPE_FLAG_FIXED; man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; break; @@ -761,6 +760,8 @@ static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, man->func = &vmw_gmrid_manager_func; man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; + /* TODO: This is most likely not correct */ + man->use_tt = true; break; default: DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 9b251853afe25..adac4cd0ba232 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -45,8 +45,6 @@ #define TTM_MAX_BO_PRIORITY 4U -#define TTM_MEMTYPE_FLAG_FIXED (1 << 0) /* Fixed (on-card) PCI memory */ - struct ttm_mem_type_manager; struct ttm_mem_type_manager_func { @@ -173,7 +171,7 @@ struct ttm_mem_type_manager { bool has_type; bool use_type; - uint32_t flags; + bool use_tt; uint64_t size; uint32_t available_caching; uint32_t default_caching; -- GitLab From b0691b34f1e0a40ed565a1420e8a749cc728d422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 11:47:57 +0200 Subject: [PATCH 0158/1494] drm/radeon: stop implementing init_mem_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382080/ --- drivers/gpu/drm/radeon/radeon_ttm.c | 70 ++++++++++++++--------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 9aba18a143e71..b0b59c5537856 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -69,43 +69,43 @@ struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - struct radeon_device *rdev; + return 0; +} - rdev = radeon_get_rdev(bdev); +static int radeon_ttm_init_vram(struct radeon_device *rdev) +{ + struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_VRAM]; - switch (type) { - case TTM_PL_SYSTEM: - /* System memory */ - break; - case TTM_PL_TT: - man->func = &ttm_bo_manager_func; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - man->use_tt = true; + man->func = &ttm_bo_manager_func; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + + return ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, + rdev->mc.real_vram_size >> PAGE_SHIFT); +} + +static int radeon_ttm_init_gtt(struct radeon_device *rdev) +{ + struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_TT]; + + man->func = &ttm_bo_manager_func; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + man->use_tt = true; #if IS_ENABLED(CONFIG_AGP) - if (rdev->flags & RADEON_IS_AGP) { - if (!rdev->ddev->agp) { - DRM_ERROR("AGP is not enabled for memory type %u\n", - (unsigned)type); - return -EINVAL; - } - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; + if (rdev->flags & RADEON_IS_AGP) { + if (!rdev->ddev->agp) { + DRM_ERROR("AGP is not enabled\n"); + return -EINVAL; } -#endif - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ - man->func = &ttm_bo_manager_func; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; } - return 0; +#endif + + return ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, + rdev->mc.gtt_size >> PAGE_SHIFT); } static void radeon_evict_flags(struct ttm_buffer_object *bo, @@ -778,8 +778,8 @@ int radeon_ttm_init(struct radeon_device *rdev) return r; } rdev->mman.initialized = true; - r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, - rdev->mc.real_vram_size >> PAGE_SHIFT); + + r = radeon_ttm_init_vram(rdev); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; @@ -804,8 +804,8 @@ int radeon_ttm_init(struct radeon_device *rdev) } DRM_INFO("radeon: %uM of VRAM memory ready\n", (unsigned) (rdev->mc.real_vram_size / (1024 * 1024))); - r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, - rdev->mc.gtt_size >> PAGE_SHIFT); + + r = radeon_ttm_init_gtt(rdev); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; -- GitLab From 473633540c2f51403df1b065ccf51d8267e880a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 15:07:45 +0200 Subject: [PATCH 0159/1494] drm/amdgpu: stop implementing init_mem_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382084/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 96 +++++++++++-------------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 406bcb03df485..98a77fc4a90cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -62,55 +62,49 @@ #define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128 - -/** - * amdgpu_init_mem_type - Initialize a memory manager for a specific type of - * memory request. - * - * @bdev: The TTM BO device object (contains a reference to amdgpu_device) - * @type: The type of memory requested - * @man: The memory type manager for each domain - * - * This is called by ttm_bo_init_mm() when a buffer object is being - * initialized. - */ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - struct amdgpu_device *adev; + return 0; +} - adev = amdgpu_ttm_adev(bdev); +static int amdgpu_ttm_init_vram(struct amdgpu_device *adev) +{ - switch (type) { - case TTM_PL_SYSTEM: - /* System memory */ - break; - case TTM_PL_TT: - /* GTT memory */ - man->use_tt = true; - man->func = &amdgpu_gtt_mgr_func; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ - man->func = &amdgpu_vram_mgr_func; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - case AMDGPU_PL_GDS: - case AMDGPU_PL_GWS: - case AMDGPU_PL_OA: - /* On-chip GDS memory*/ - man->func = &ttm_bo_manager_func; - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } - return 0; + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; + + man->func = &amdgpu_vram_mgr_func; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + + return ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, + adev->gmc.real_vram_size >> PAGE_SHIFT); +} + +static int amdgpu_ttm_init_gtt(struct amdgpu_device *adev, uint64_t gtt_size) +{ + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; + + man->use_tt = true; + man->func = &amdgpu_gtt_mgr_func; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + + return ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, + gtt_size >> PAGE_SHIFT); +} + +static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, + unsigned int type, + uint64_t size) +{ + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[type]; + + man->func = &ttm_bo_manager_func; + man->available_caching = TTM_PL_FLAG_UNCACHED; + man->default_caching = TTM_PL_FLAG_UNCACHED; + + return ttm_bo_init_mm(&adev->mman.bdev, type, size); } /** @@ -1896,8 +1890,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) adev->mman.bdev.no_retry = true; /* Initialize VRAM pool with all of VRAM divided into pages */ - r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, - adev->gmc.real_vram_size >> PAGE_SHIFT); + r = amdgpu_ttm_init_vram(adev); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; @@ -1978,7 +1971,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) gtt_size = (uint64_t)amdgpu_gtt_size << 20; /* Initialize GTT memory pool */ - r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); + r = amdgpu_ttm_init_gtt(adev, gtt_size); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; @@ -1987,22 +1980,19 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) (unsigned)(gtt_size / (1024 * 1024))); /* Initialize various on-chip memory pools */ - r = ttm_bo_init_mm(&adev->mman.bdev, AMDGPU_PL_GDS, - adev->gds.gds_size); + r = amdgpu_ttm_init_on_chip(adev, AMDGPU_PL_GDS, adev->gds.gds_size); if (r) { DRM_ERROR("Failed initializing GDS heap.\n"); return r; } - r = ttm_bo_init_mm(&adev->mman.bdev, AMDGPU_PL_GWS, - adev->gds.gws_size); + r = amdgpu_ttm_init_on_chip(adev, AMDGPU_PL_GWS, adev->gds.gws_size); if (r) { DRM_ERROR("Failed initializing gws heap.\n"); return r; } - r = ttm_bo_init_mm(&adev->mman.bdev, AMDGPU_PL_OA, - adev->gds.oa_size); + r = amdgpu_ttm_init_on_chip(adev, AMDGPU_PL_OA, adev->gds.oa_size); if (r) { DRM_ERROR("Failed initializing oa heap.\n"); return r; -- GitLab From 3629ca5dfb9ab583a6307abb31793bb0afacf933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 15:19:49 +0200 Subject: [PATCH 0160/1494] drm/vmwgfx: stop implementing init_mem_type v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. v2: keep extra system domain handling Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382082/ --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 20 ++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 28 ---------------------- 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4704283878784..8e67a29471a8c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -859,11 +859,16 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) DRM_ERROR("Failed initializing TTM buffer object driver.\n"); goto out_no_bdev; } + dev_priv->bdev.man[TTM_PL_SYSTEM].available_caching = + TTM_PL_FLAG_CACHED; /* * Enable VRAM, but initially don't use it until SVGA is enabled and * unhidden. */ + dev_priv->bdev.man[TTM_PL_VRAM].func = &vmw_thp_func; + dev_priv->bdev.man[TTM_PL_VRAM].available_caching = TTM_PL_FLAG_CACHED; + dev_priv->bdev.man[TTM_PL_VRAM].default_caching = TTM_PL_FLAG_CACHED; ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, (dev_priv->vram_size >> PAGE_SHIFT)); if (unlikely(ret != 0)) { @@ -872,7 +877,17 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) } dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; + /* + * "Guest Memory Regions" is an aperture like feature with + * one slot per bo. There is an upper limit of the number of + * slots as well as the bo size. + */ dev_priv->has_gmr = true; + dev_priv->bdev.man[VMW_PL_GMR].func = &vmw_gmrid_manager_func; + dev_priv->bdev.man[VMW_PL_GMR].available_caching = TTM_PL_FLAG_CACHED; + dev_priv->bdev.man[VMW_PL_GMR].default_caching = TTM_PL_FLAG_CACHED; + /* TODO: This is most likely not correct */ + dev_priv->bdev.man[VMW_PL_GMR].use_tt = true; if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, VMW_PL_GMR) != 0) { @@ -883,6 +898,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS && !refuse_dma) { dev_priv->has_mob = true; + dev_priv->bdev.man[VMW_PL_MOB].func = &vmw_gmrid_manager_func; + dev_priv->bdev.man[VMW_PL_MOB].available_caching = TTM_PL_FLAG_CACHED; + dev_priv->bdev.man[VMW_PL_MOB].default_caching = TTM_PL_FLAG_CACHED; + /* TODO: This is most likely not correct */ + dev_priv->bdev.man[VMW_PL_MOB].use_tt = true; if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, VMW_PL_MOB) != 0) { DRM_INFO("No MOB memory available. " diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index d00748ecaf202..db4b2e2e4edb1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -739,34 +739,6 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - switch (type) { - case TTM_PL_SYSTEM: - /* System memory */ - man->available_caching = TTM_PL_FLAG_CACHED; - break; - case TTM_PL_VRAM: - /* "On-card" video ram */ - man->func = &vmw_thp_func; - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - case VMW_PL_GMR: - case VMW_PL_MOB: - /* - * "Guest Memory Regions" is an aperture like feature with - * one slot per bo. There is an upper limit of the number of - * slots as well as the bo size. - */ - man->func = &vmw_gmrid_manager_func; - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - /* TODO: This is most likely not correct */ - man->use_tt = true; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); - return -EINVAL; - } return 0; } -- GitLab From 009869fde901a4086f3590ec7c9a02de07801276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 15:39:57 +0200 Subject: [PATCH 0161/1494] drm/nouveau: stop implementing init_mem_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382081/ --- drivers/gpu/drm/nouveau/nouveau_bo.c | 48 --------------------- drivers/gpu/drm/nouveau/nouveau_ttm.c | 61 +++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a3ad66ad38175..23ef9b1aaabc0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -650,54 +650,6 @@ static int nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - struct nouveau_drm *drm = nouveau_bdev(bdev); - struct nvif_mmu *mmu = &drm->client.mmu; - - switch (type) { - case TTM_PL_SYSTEM: - break; - case TTM_PL_VRAM: - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - /* Some BARs do not support being ioremapped WC */ - const u8 type = mmu->type[drm->ttm.type_vram].type; - if (type & NVIF_MEM_UNCACHED) { - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - } - - man->func = &nouveau_vram_manager; - man->use_io_reserve_lru = true; - } else { - man->func = &ttm_bo_manager_func; - } - break; - case TTM_PL_TT: - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) - man->func = &nouveau_gart_manager; - else - if (!drm->agp.bridge) - man->func = &nv04_gart_manager; - else - man->func = &ttm_bo_manager_func; - - man->use_tt = true; - if (drm->agp.bridge) { - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - } else { - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - } - - break; - default: - return -EINVAL; - } return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index e89ea052cf71d..b0012021ae12d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -180,6 +180,61 @@ nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind) return 0; } +static int +nouveau_ttm_init_vram(struct nouveau_drm *drm) +{ + struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_VRAM]; + struct nvif_mmu *mmu = &drm->client.mmu; + + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + /* Some BARs do not support being ioremapped WC */ + const u8 type = mmu->type[drm->ttm.type_vram].type; + + if (type & NVIF_MEM_UNCACHED) { + man->available_caching = TTM_PL_FLAG_UNCACHED; + man->default_caching = TTM_PL_FLAG_UNCACHED; + } + + man->func = &nouveau_vram_manager; + man->use_io_reserve_lru = true; + } else { + man->func = &ttm_bo_manager_func; + } + + return ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, + drm->gem.vram_available >> PAGE_SHIFT); +} + +static int +nouveau_ttm_init_gtt(struct nouveau_drm *drm) +{ + struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_TT]; + + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) + man->func = &nouveau_gart_manager; + else + if (!drm->agp.bridge) + man->func = &nv04_gart_manager; + else + man->func = &ttm_bo_manager_func; + + man->use_tt = true; + if (drm->agp.bridge) { + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + } else { + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + } + + return ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT, + drm->gem.gart_available >> PAGE_SHIFT); +} + int nouveau_ttm_init(struct nouveau_drm *drm) { @@ -237,8 +292,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) arch_io_reserve_memtype_wc(device->func->resource_addr(device, 1), device->func->resource_size(device, 1)); - ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, - drm->gem.vram_available >> PAGE_SHIFT); + ret = nouveau_ttm_init_vram(drm); if (ret) { NV_ERROR(drm, "VRAM mm init failed, %d\n", ret); return ret; @@ -254,8 +308,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) drm->gem.gart_available = drm->agp.size; } - ret = ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT, - drm->gem.gart_available >> PAGE_SHIFT); + ret = nouveau_ttm_init_gtt(drm); if (ret) { NV_ERROR(drm, "GART mm init failed, %d\n", ret); return ret; -- GitLab From ccd0dc437f257e42016b20375d52cd1631529e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 16:29:59 +0200 Subject: [PATCH 0162/1494] drm/qxl: stop implementing init_mem_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382083/ --- drivers/gpu/drm/qxl/qxl_ttm.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index abb9fa4d80cf9..852089d7f783f 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -51,21 +51,6 @@ static struct qxl_device *qxl_get_qdev(struct ttm_bo_device *bdev) static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - switch (type) { - case TTM_PL_SYSTEM: - /* System memory */ - break; - case TTM_PL_VRAM: - case TTM_PL_PRIV: - /* "On-card" video ram */ - man->func = &ttm_bo_manager_func; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - break; - default: - DRM_ERROR("Unsupported memory type %u\n", (unsigned int)type); - return -EINVAL; - } return 0; } @@ -238,6 +223,19 @@ static struct ttm_bo_driver qxl_bo_driver = { .move_notify = &qxl_bo_move_notify, }; +static int qxl_ttm_init_mem_type(struct qxl_device *qdev, + unsigned int type, + uint64_t size) +{ + struct ttm_mem_type_manager *man = &qdev->mman.bdev.man[type]; + + man->func = &ttm_bo_manager_func; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + + return ttm_bo_init_mm(&qdev->mman.bdev, type, size); +} + int qxl_ttm_init(struct qxl_device *qdev) { int r; @@ -255,14 +253,13 @@ int qxl_ttm_init(struct qxl_device *qdev) } /* NOTE: this includes the framebuffer (aka surface 0) */ num_io_pages = qdev->rom->ram_header_offset / PAGE_SIZE; - r = ttm_bo_init_mm(&qdev->mman.bdev, TTM_PL_VRAM, - num_io_pages); + r = qxl_ttm_init_mem_type(qdev, TTM_PL_VRAM, num_io_pages); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; } - r = ttm_bo_init_mm(&qdev->mman.bdev, TTM_PL_PRIV, - qdev->surfaceram_size / PAGE_SIZE); + r = qxl_ttm_init_mem_type(qdev, TTM_PL_PRIV, + qdev->surfaceram_size / PAGE_SIZE); if (r) { DRM_ERROR("Failed initializing Surfaces heap.\n"); return r; -- GitLab From ded9f8eaddaaf669c16880c28e18c512989fdd00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 16:40:17 +0200 Subject: [PATCH 0163/1494] drm/vram-helper: stop implementing init_mem_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just initialize the memory type parameters before calling ttm_bo_init_mm. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382086/ --- drivers/gpu/drm/drm_gem_vram_helper.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 801a14c6e9e02..f7f93a49cd7f6 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1007,18 +1007,6 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { - switch (type) { - case TTM_PL_SYSTEM: - break; - case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; - default: - return -EINVAL; - } return 0; } @@ -1126,6 +1114,7 @@ EXPORT_SYMBOL(drm_vram_mm_debugfs_init); static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, uint64_t vram_base, size_t vram_size) { + struct ttm_mem_type_manager *man = &vmm->bdev.man[TTM_PL_VRAM]; int ret; vmm->vram_base = vram_base; @@ -1138,6 +1127,9 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, if (ret) return ret; + man->func = &ttm_bo_manager_func; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT); if (ret) return ret; -- GitLab From 1a3fb590856a9d7e8392d970fc07791b6703de94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 23 Jul 2020 17:13:47 +0200 Subject: [PATCH 0164/1494] drm/ttm: remove the init_mem_type callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is a very strange concept to call a function which just calls back the caller for the functions parameters. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/382085/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 7 ------- drivers/gpu/drm/drm_gem_vram_helper.c | 7 ------- drivers/gpu/drm/nouveau/nouveau_bo.c | 8 -------- drivers/gpu/drm/qxl/qxl_ttm.c | 7 ------- drivers/gpu/drm/radeon/radeon_ttm.c | 7 ------- drivers/gpu/drm/ttm/ttm_bo.c | 4 ---- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 7 ------- include/drm/ttm/ttm_bo_driver.h | 6 ------ 8 files changed, 53 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 98a77fc4a90cb..da6434ea07f13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -62,12 +62,6 @@ #define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128 -static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static int amdgpu_ttm_init_vram(struct amdgpu_device *adev) { @@ -1727,7 +1721,6 @@ static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_create = &amdgpu_ttm_tt_create, .ttm_tt_populate = &amdgpu_ttm_tt_populate, .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, - .init_mem_type = &amdgpu_init_mem_type, .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index f7f93a49cd7f6..5f03c6137ef9e 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1004,12 +1004,6 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, return NULL; } -static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static void bo_driver_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { @@ -1069,7 +1063,6 @@ static struct ttm_bo_driver bo_driver = { .ttm_tt_create = bo_driver_ttm_tt_create, .ttm_tt_populate = ttm_pool_populate, .ttm_tt_unpopulate = ttm_pool_unpopulate, - .init_mem_type = bo_driver_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bo_driver_evict_flags, .move_notify = bo_driver_move_notify, diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 23ef9b1aaabc0..5efc572c14ccb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -646,13 +646,6 @@ nouveau_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) return nouveau_sgdma_create_ttm(bo, page_flags); } -static int -nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static void nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) { @@ -1643,7 +1636,6 @@ struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = &nouveau_ttm_tt_create, .ttm_tt_populate = &nouveau_ttm_tt_populate, .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate, - .init_mem_type = nouveau_bo_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = nouveau_bo_evict_flags, .move_notify = nouveau_bo_move_ntfy, diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 852089d7f783f..32069e4799f36 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -48,12 +48,6 @@ static struct qxl_device *qxl_get_qdev(struct ttm_bo_device *bdev) return qdev; } -static int qxl_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static void qxl_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { @@ -215,7 +209,6 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo, static struct ttm_bo_driver qxl_bo_driver = { .ttm_tt_create = &qxl_ttm_tt_create, - .init_mem_type = &qxl_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &qxl_evict_flags, .move = &qxl_bo_move, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b0b59c5537856..f499d02917ac5 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -66,12 +66,6 @@ struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) return rdev; } -static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static int radeon_ttm_init_vram(struct radeon_device *rdev) { struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_VRAM]; @@ -753,7 +747,6 @@ static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_create = &radeon_ttm_tt_create, .ttm_tt_populate = &radeon_ttm_tt_populate, .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, - .init_mem_type = &radeon_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move, diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 9d316f33e6a6a..6c02a336a587a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1524,10 +1524,6 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, mutex_init(&man->io_reserve_mutex); spin_lock_init(&man->move_lock); INIT_LIST_HEAD(&man->io_reserve_lru); - - ret = bdev->driver->init_mem_type(bdev, type, man); - if (ret) - return ret; man->bdev = bdev; if (type != TTM_PL_SYSTEM) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index db4b2e2e4edb1..0e28978953274 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -736,12 +736,6 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, return NULL; } -static int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man) -{ - return 0; -} - static void vmw_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { @@ -817,7 +811,6 @@ struct ttm_bo_driver vmw_bo_driver = { .ttm_tt_create = &vmw_ttm_tt_create, .ttm_tt_populate = &vmw_ttm_populate, .ttm_tt_unpopulate = &vmw_ttm_unpopulate, - .init_mem_type = vmw_init_mem_type, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = NULL, diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index adac4cd0ba232..f76f1332fdc5f 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -157,7 +157,6 @@ struct ttm_mem_type_manager_func { * @move: The fence of the last pipelined move operation. * * This structure is used to identify and manage memory types for a device. - * It's set up by the ttm_bo_driver::init_mem_type method. */ @@ -203,8 +202,6 @@ struct ttm_mem_type_manager { * struct ttm_bo_driver * * @create_ttm_backend_entry: Callback to create a struct ttm_backend. - * @init_mem_type: Callback to initialize a struct ttm_mem_type_manager - * structure. * @evict_flags: Callback to obtain placement flags when a buffer is evicted. * @move: Callback for a driver to hook in accelerated functions to * move a buffer. @@ -247,9 +244,6 @@ struct ttm_bo_driver { */ void (*ttm_tt_unpopulate)(struct ttm_tt *ttm); - int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man); - /** * struct ttm_bo_driver member eviction_valuable * -- GitLab From c3ee8c65f63799b02e1fb828bac99fd5008fb565 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Sat, 1 Aug 2020 20:02:13 +0800 Subject: [PATCH 0165/1494] drm/panel: remove return value of function drm_panel_add The function "int drm_panel_add(struct drm_panel *panel)" always returns 0, this return value is meaningless. Also, there is no need to check return value which calls "drm_panel_add and", error branch code will never run. Signed-off-by: Bernard Zhao <bernard@vivo.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200801120216.8488-1-bernard@vivo.com --- drivers/gpu/drm/drm_panel.c | 6 +----- drivers/gpu/drm/panel/panel-arm-versatile.c | 4 +++- drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c | 6 +----- drivers/gpu/drm/panel/panel-boe-himax8279d.c | 4 +++- drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 4 +++- drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c | 4 +--- drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c | 4 +--- drivers/gpu/drm/panel/panel-ilitek-ili9322.c | 4 +++- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 4 +--- drivers/gpu/drm/panel/panel-innolux-p079zca.c | 4 +--- drivers/gpu/drm/panel/panel-jdi-lt070me05000.c | 4 ++-- drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c | 4 +++- drivers/gpu/drm/panel/panel-lg-lb035q02.c | 4 +++- drivers/gpu/drm/panel/panel-lg-lg4573.c | 4 +++- drivers/gpu/drm/panel/panel-lvds.c | 4 +--- drivers/gpu/drm/panel/panel-nec-nl8048hl11.c | 4 +++- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 4 +--- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 6 +----- drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c | 4 +++- drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c | 4 +++- drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c | 4 +++- drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c | 6 ++---- drivers/gpu/drm/panel/panel-raydium-rm67191.c | 4 +--- drivers/gpu/drm/panel/panel-ronbo-rb070d30.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-ld9040.c | 4 +++- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 4 +--- drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 6 +----- drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c | 6 +----- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 4 +++- drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c | 6 +----- drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c | 4 +--- drivers/gpu/drm/panel/panel-seiko-43wvf1g.c | 4 +--- drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 4 +++- drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c | 4 +++- drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c | 4 +++- drivers/gpu/drm/panel/panel-simple.c | 4 +--- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 4 +--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 4 +--- drivers/gpu/drm/panel/panel-sony-acx424akp.c | 4 +--- drivers/gpu/drm/panel/panel-sony-acx565akm.c | 7 +------ drivers/gpu/drm/panel/panel-tpo-td028ttec1.c | 4 +++- drivers/gpu/drm/panel/panel-tpo-td043mtea1.c | 6 +----- drivers/gpu/drm/panel/panel-tpo-tpg110.c | 4 +++- include/drm/drm_panel.h | 2 +- 44 files changed, 82 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 8c7bac85a7937..b8e9abb537cfc 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -70,16 +70,12 @@ EXPORT_SYMBOL(drm_panel_init); * * Add a panel to the global registry so that it can be looked up by display * drivers. - * - * Return: 0 on success or a negative error code on failure. */ -int drm_panel_add(struct drm_panel *panel) +void drm_panel_add(struct drm_panel *panel) { mutex_lock(&panel_lock); list_add_tail(&panel->list, &panel_list); mutex_unlock(&panel_lock); - - return 0; } EXPORT_SYMBOL(drm_panel_add); diff --git a/drivers/gpu/drm/panel/panel-arm-versatile.c b/drivers/gpu/drm/panel/panel-arm-versatile.c index 47b37fef7ee8a..abb0788843c60 100644 --- a/drivers/gpu/drm/panel/panel-arm-versatile.c +++ b/drivers/gpu/drm/panel/panel-arm-versatile.c @@ -349,7 +349,9 @@ static int versatile_panel_probe(struct platform_device *pdev) drm_panel_init(&vpanel->panel, dev, &versatile_panel_drm_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&vpanel->panel); + drm_panel_add(&vpanel->panel); + + return 0; } static const struct of_device_id versatile_panel_match[] = { diff --git a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c index 9a5b7644d756e..e95bc9f60b3fb 100644 --- a/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c +++ b/drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c @@ -315,11 +315,7 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi) return ret; } - ret = drm_panel_add(&ctx->panel); - if (ret < 0) { - dev_err(dev, "Failed to add panel: %d\n", ret); - return ret; - } + drm_panel_add(&ctx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) { diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index 7c27bd5e34860..d676b4c2a8fa4 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -895,7 +895,9 @@ static int panel_add(struct panel_info *pinfo) if (ret) return ret; - return drm_panel_add(&pinfo->base); + drm_panel_add(&pinfo->base); + + return 0; } static int panel_probe(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index db5b866357f28..3bd46600a98ba 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -787,7 +787,9 @@ static int boe_panel_add(struct boe_panel *boe) boe->base.funcs = &boe_panel_funcs; boe->base.dev = &boe->dsi->dev; - return drm_panel_add(&boe->base); + drm_panel_add(&boe->base); + + return 0; } static int boe_panel_probe(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c index 54610651ecdb3..0b7e82e5ba4e3 100644 --- a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c +++ b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c @@ -477,9 +477,7 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); dsi->mode_flags = MIPI_DSI_MODE_VIDEO; dsi->format = MIPI_DSI_FMT_RGB888; diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c index 19a6274b10f50..f9edee69fea40 100644 --- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c @@ -224,9 +224,7 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); dsi->mode_flags = MIPI_DSI_MODE_VIDEO_BURST; dsi->format = MIPI_DSI_FMT_RGB888; diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 67a64d1999f69..9688458947257 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -892,7 +892,9 @@ static int ili9322_probe(struct spi_device *spi) drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&ili->panel); + drm_panel_add(&ili->panel); + + return 0; } static int ili9322_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 3ed8635a6fbdf..066ef6c535df0 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -446,9 +446,7 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); dsi->mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE; dsi->format = MIPI_DSI_FMT_RGB888; diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index fdf030f4cf92d..1a8e69c641253 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c @@ -475,9 +475,7 @@ static int innolux_panel_add(struct mipi_dsi_device *dsi, if (err) return err; - err = drm_panel_add(&innolux->base); - if (err < 0) - return err; + drm_panel_add(&innolux->base); mipi_dsi_set_drvdata(dsi, innolux); innolux->link = dsi; diff --git a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c index 1e3fd6633981f..733010b5e4f53 100644 --- a/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c +++ b/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c @@ -440,9 +440,9 @@ static int jdi_panel_add(struct jdi_panel *jdi) drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_add(&jdi->base); + drm_panel_add(&jdi->base); - return ret; + return 0; } static void jdi_panel_del(struct jdi_panel *jdi) diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c index 0d397af23afe7..f42dc2ceeb079 100644 --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c @@ -382,7 +382,9 @@ static int kingdisplay_panel_add(struct kingdisplay_panel *kingdisplay) if (err) return err; - return drm_panel_add(&kingdisplay->base); + drm_panel_add(&kingdisplay->base); + + return 0; } static void kingdisplay_panel_del(struct kingdisplay_panel *kingdisplay) diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c index 14456b9cd5c01..f3183b68704f6 100644 --- a/drivers/gpu/drm/panel/panel-lg-lb035q02.c +++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c @@ -198,7 +198,9 @@ static int lb035q02_probe(struct spi_device *spi) drm_panel_init(&lcd->panel, &lcd->spi->dev, &lb035q02_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&lcd->panel); + drm_panel_add(&lcd->panel); + + return 0; } static int lb035q02_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index aedc485d07273..8e5160af1de5d 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -261,7 +261,9 @@ static int lg4573_probe(struct spi_device *spi) drm_panel_init(&ctx->panel, &spi->dev, &lg4573_drm_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&ctx->panel); + drm_panel_add(&ctx->panel); + + return 0; } static int lg4573_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index 5ce3f4a2b7a19..41305c3dcf318 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -227,9 +227,7 @@ static int panel_lvds_probe(struct platform_device *pdev) if (ret) return ret; - ret = drm_panel_add(&lvds->panel); - if (ret < 0) - return ret; + drm_panel_add(&lvds->panel); dev_set_drvdata(lvds->dev, lvds); return 0; diff --git a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c index f894971c1c7c5..6e5ab1debc8b4 100644 --- a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c @@ -207,7 +207,9 @@ static int nl8048_probe(struct spi_device *spi) drm_panel_init(&lcd->panel, &lcd->spi->dev, &nl8048_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&lcd->panel); + drm_panel_add(&lcd->panel); + + return 0; } static int nl8048_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index e98d54df00e7b..e67d0955e2152 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -956,9 +956,7 @@ static int nt35510_probe(struct mipi_dsi_device *dsi) nt->panel.backlight = bl; } - ret = drm_panel_add(&nt->panel); - if (ret < 0) - return ret; + drm_panel_add(&nt->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index 91df050ba3f63..3d15d99252044 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -303,11 +303,7 @@ static int nt39016_probe(struct spi_device *spi) drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs, DRM_MODE_CONNECTOR_DPI); - err = drm_panel_add(&panel->drm_panel); - if (err < 0) { - dev_err(dev, "Failed to register panel"); - return err; - } + drm_panel_add(&panel->drm_panel); return 0; } diff --git a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c index ecd76b5391d31..cb5cb27462df1 100644 --- a/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c +++ b/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c @@ -283,7 +283,9 @@ static int lcd_olinuxino_probe(struct i2c_client *client, if (ret) return ret; - return drm_panel_add(&lcd->panel); + drm_panel_add(&lcd->panel); + + return 0; } static int lcd_olinuxino_remove(struct i2c_client *client) diff --git a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c index 83e5aa47f0d67..45b975dee587b 100644 --- a/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c +++ b/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c @@ -164,7 +164,9 @@ static int osd101t2587_panel_add(struct osd101t2587_panel *osd101t2587) if (ret) return ret; - return drm_panel_add(&osd101t2587->base); + drm_panel_add(&osd101t2587->base); + + return 0; } static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi) diff --git a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c index 627dfcf8adb4d..3c20beeb17819 100644 --- a/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c +++ b/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c @@ -206,7 +206,9 @@ static int wuxga_nt_panel_add(struct wuxga_nt_panel *wuxga_nt) if (ret) return ret; - return drm_panel_add(&wuxga_nt->base); + drm_panel_add(&wuxga_nt->base); + + return 0; } static void wuxga_nt_panel_del(struct wuxga_nt_panel *wuxga_nt) diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c index e50ee26474cfe..5e9ccefb88f62 100644 --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -361,7 +361,7 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, struct rpi_touchscreen *ts; struct device_node *endpoint, *dsi_host_node; struct mipi_dsi_host *host; - int ret, ver; + int ver; struct mipi_dsi_device_info info = { .type = RPI_DSI_DRIVER_NAME, .channel = 0, @@ -429,9 +429,7 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, /* This appears last, as it's what will unblock the DSI host * driver's component bind function. */ - ret = drm_panel_add(&ts->base); - if (ret) - return ret; + drm_panel_add(&ts->base); return 0; diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c index 57ff2b1f63617..2ef3225821339 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -609,9 +609,7 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi) DRM_MODE_CONNECTOR_DSI); dev_set_drvdata(dev, panel); - ret = drm_panel_add(&panel->panel); - if (ret) - return ret; + drm_panel_add(&panel->panel); ret = mipi_dsi_attach(dsi); if (ret) diff --git a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c index a7b0b3e39e1a5..ea74958d7544d 100644 --- a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c +++ b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c @@ -200,9 +200,7 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM; dsi->format = MIPI_DSI_FMT_RGB888; diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c index 9bb2e8c7934ab..358168ed8355d 100644 --- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c +++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c @@ -354,7 +354,9 @@ static int ld9040_probe(struct spi_device *spi) drm_panel_init(&ctx->panel, dev, &ld9040_drm_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&ctx->panel); + drm_panel_add(&ctx->panel); + + return 0; } static int ld9040_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c index f02645d396aca..e88af6f8bf60d 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c @@ -212,9 +212,7 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi) drm_panel_init(&s6->panel, dev, &s6d16d0_drm_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_add(&s6->panel); - if (ret < 0) - return ret; + drm_panel_add(&s6->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c index 80ef122e7466d..2c84036c6a65e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -733,9 +733,7 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - goto unregister_backlight; + drm_panel_add(&ctx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) @@ -745,8 +743,6 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi) remove_panel: drm_panel_remove(&ctx->panel); - -unregister_backlight: backlight_device_unregister(ctx->bl_dev); return ret; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c index 1247656d73bf1..7a43eb3545cfb 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c @@ -479,9 +479,7 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi) ctx->bl_dev->props.brightness = DEFAULT_BRIGHTNESS; ctx->bl_dev->props.power = FB_BLANK_POWERDOWN; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - goto unregister_backlight; + drm_panel_add(&ctx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) @@ -491,8 +489,6 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi) remove_panel: drm_panel_remove(&ctx->panel); - -unregister_backlight: backlight_device_unregister(ctx->bl_dev); return ret; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 64421347bfd47..e086efea29505 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -479,7 +479,9 @@ static int s6e63m0_probe(struct spi_device *spi) if (ret < 0) return ret; - return drm_panel_add(&ctx->panel); + drm_panel_add(&ctx->panel); + + return 0; } static int s6e63m0_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c index 485eabecfcc95..ea63799ff2a1e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c @@ -242,11 +242,7 @@ static int s6e88a0_ams452ef01_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e88a0_ams452ef01_panel_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_add(&ctx->panel); - if (ret < 0) { - dev_err(dev, "Failed to add panel: %d\n", ret); - return ret; - } + drm_panel_add(&ctx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c index 8a028d2bd0d60..e36cb1a253187 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c @@ -1020,9 +1020,7 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs, DRM_MODE_CONNECTOR_DSI); - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c index e417dc4921c2c..0ee508576231f 100644 --- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c +++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c @@ -258,9 +258,7 @@ static int seiko_panel_probe(struct device *dev, if (err) return err; - err = drm_panel_add(&panel->base); - if (err < 0) - return err; + drm_panel_add(&panel->base); dev_set_drvdata(dev, panel); diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c index f07324b705b35..f8cd2a42ed13b 100644 --- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c +++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c @@ -325,7 +325,9 @@ static int sharp_panel_add(struct sharp_panel *sharp) if (ret) return ret; - return drm_panel_add(&sharp->base); + drm_panel_add(&sharp->base); + + return 0; } static void sharp_panel_del(struct sharp_panel *sharp) diff --git a/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c index d7bf13b9e1d62..94992f45113a9 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c @@ -187,7 +187,9 @@ static int ls037v7dw01_probe(struct platform_device *pdev) drm_panel_init(&lcd->panel, &pdev->dev, &ls037v7dw01_funcs, DRM_MODE_CONNECTOR_DPI); - return drm_panel_add(&lcd->panel); + drm_panel_add(&lcd->panel); + + return 0; } static int ls037v7dw01_remove(struct platform_device *pdev) diff --git a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c index b2e58935529cb..16dbf0f353eda 100644 --- a/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c +++ b/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c @@ -261,7 +261,9 @@ static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) if (ret) return ret; - return drm_panel_add(&sharp_nt->base); + drm_panel_add(&sharp_nt->base); + + return 0; } static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 221859652d82b..67ca543e74e8c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -613,9 +613,7 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) if (err) goto free_ddc; - err = drm_panel_add(&panel->base); - if (err < 0) - goto free_ddc; + drm_panel_add(&panel->base); dev_set_drvdata(dev, panel); diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 692041ae4eb65..12462114a52d8 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -380,9 +380,7 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) if (ret) return ret; - ret = drm_panel_add(&st7701->panel); - if (ret < 0) - return ret; + drm_panel_add(&st7701->panel); mipi_dsi_set_drvdata(dsi, st7701); st7701->dsi = dsi; diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c index 3513ae40efa8c..61e565524542c 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c @@ -382,9 +382,7 @@ static int st7789v_probe(struct spi_device *spi) if (ret) return ret; - ret = drm_panel_add(&ctx->panel); - if (ret < 0) - return ret; + drm_panel_add(&ctx->panel); return 0; } diff --git a/drivers/gpu/drm/panel/panel-sony-acx424akp.c b/drivers/gpu/drm/panel/panel-sony-acx424akp.c index 97a1b4790d3c2..57575c40f2aa6 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx424akp.c +++ b/drivers/gpu/drm/panel/panel-sony-acx424akp.c @@ -504,9 +504,7 @@ static int acx424akp_probe(struct mipi_dsi_device *dsi) acx->bl->props.brightness = 512; acx->bl->props.power = FB_BLANK_POWERDOWN; - ret = drm_panel_add(&acx->panel); - if (ret < 0) - return ret; + drm_panel_add(&acx->panel); ret = mipi_dsi_attach(dsi); if (ret < 0) { diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c index fc6a7e451abef..e95fdfb16b6c9 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c @@ -650,12 +650,7 @@ static int acx565akm_probe(struct spi_device *spi) drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs, DRM_MODE_CONNECTOR_DPI); - ret = drm_panel_add(&lcd->panel); - if (ret < 0) { - if (lcd->has_bc) - acx565akm_backlight_cleanup(lcd); - return ret; - } + drm_panel_add(&lcd->panel); return 0; } diff --git a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c index 58d683cc52154..037c14fd6bacf 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c @@ -350,7 +350,9 @@ static int td028ttec1_probe(struct spi_device *spi) if (ret) return ret; - return drm_panel_add(&lcd->panel); + drm_panel_add(&lcd->panel); + + return 0; } static int td028ttec1_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c index 9b2a356c4d9a9..49e6c93862587 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c @@ -460,11 +460,7 @@ static int td043mtea1_probe(struct spi_device *spi) drm_panel_init(&lcd->panel, &lcd->spi->dev, &td043mtea1_funcs, DRM_MODE_CONNECTOR_DPI); - ret = drm_panel_add(&lcd->panel); - if (ret < 0) { - sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group); - return ret; - } + drm_panel_add(&lcd->panel); return 0; } diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c index c7a2f0ae5ba51..cd00cfa6ba149 100644 --- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c +++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c @@ -448,7 +448,9 @@ static int tpg110_probe(struct spi_device *spi) spi_set_drvdata(spi, tpg); - return drm_panel_add(&tpg->panel); + drm_panel_add(&tpg->panel); + + return 0; } static int tpg110_remove(struct spi_device *spi) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 6193cb555accc..ff066524cb707 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -175,7 +175,7 @@ void drm_panel_init(struct drm_panel *panel, struct device *dev, const struct drm_panel_funcs *funcs, int connector_type); -int drm_panel_add(struct drm_panel *panel); +void drm_panel_add(struct drm_panel *panel); void drm_panel_remove(struct drm_panel *panel); int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); -- GitLab From 1d865be98686b8dd1c1c82db827afdd1ae967f13 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 22:12:40 +0200 Subject: [PATCH 0166/1494] dt-bindings: Add vendor prefix for Chefree The Chefree Technology Corp. is an LCD panel manufacturer. Signed-off-by: Marek Vasut <marex@denx.de> Acked-by: Rob Herring <robh@kernel.org> Cc: dri-devel@lists.freedesktop.org Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728201242.4336-1-marex@denx.de --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index da56a82b56231..1dd92dc7cbb37 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -193,6 +193,8 @@ patternProperties: description: Ceva, Inc. "^checkpoint,.*": description: Check Point Software Technologies Ltd. + "^chefree,.*": + description: Chefree Technology Corp. "^chipidea,.*": description: Chipidea, Inc "^chipone,.*": -- GitLab From 44de5cee20387b61477f44689f0f81f08aeddbe6 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 22:12:41 +0200 Subject: [PATCH 0167/1494] dt-bindings: Add DT bindings for Chefree CH101OLHLWH-002 Add DT bindings for Chefree CH101OLHLWH-002 10.1" 1280x800 LCD. This panel is connected via LVDS. Signed-off-by: Marek Vasut <marex@denx.de> Acked-by: Rob Herring <robh@kernel.org> Cc: dri-devel@lists.freedesktop.org Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728201242.4336-2-marex@denx.de --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 5a0af2b80abae..47247ace86acf 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -87,6 +87,8 @@ properties: - cdtech,s070swv29hg-dc44 # CDTech(H.K.) Electronics Limited 7" 800x480 color TFT-LCD panel - cdtech,s070wv95-ct16 + # Chefree CH101OLHLWH-002 10.1" (1280x800) color TFT LCD panel + - chefree,ch101olhlwh-002 # Chunghwa Picture Tubes Ltd. 7" WXGA TFT LCD panel - chunghwa,claa070wp03xg # Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel -- GitLab From 07c913c4d7101fbef0bac738740aa2bba395d157 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Tue, 28 Jul 2020 22:12:42 +0200 Subject: [PATCH 0168/1494] drm/panel: simple: Add Chefree CH101OLHLWH-002 panel Add support for the Chefree CH101OLHLWH-002 10.1" (1280x800) color TFT LCD panel, connected over LVDS. Timings are taken from the datasheet version P0.5. Signed-off-by: Marek Vasut <marex@denx.de> Cc: dri-devel@lists.freedesktop.org Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200728201242.4336-3-marex@denx.de --- drivers/gpu/drm/panel/panel-simple.c | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 67ca543e74e8c..3787748b5bd00 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1442,6 +1442,36 @@ static const struct panel_desc cdtech_s070wv95_ct16 = { }, }; +static const struct display_timing chefree_ch101olhlwh_002_timing = { + .pixelclock = { 68900000, 71100000, 73400000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 65, 80, 95 }, + .hback_porch = { 64, 79, 94 }, + .hsync_len = { 1, 1, 1 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 7, 11, 14 }, + .vback_porch = { 7, 11, 14 }, + .vsync_len = { 1, 1, 1 }, + .flags = DISPLAY_FLAGS_DE_HIGH, +}; + +static const struct panel_desc chefree_ch101olhlwh_002 = { + .timings = &chefree_ch101olhlwh_002_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 217, + .height = 135, + }, + .delay = { + .enable = 200, + .disable = 200, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode chunghwa_claa070wp03xg_mode = { .clock = 66770, .hdisplay = 800, @@ -3871,6 +3901,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "cdtech,s070wv95-ct16", .data = &cdtech_s070wv95_ct16, + }, { + .compatible = "chefree,ch101olhlwh-002", + .data = &chefree_ch101olhlwh_002, }, { .compatible = "chunghwa,claa070wp03xg", .data = &chunghwa_claa070wp03xg, -- GitLab From 0986191186128b10b6bbfa5220fc587ed5725e49 Mon Sep 17 00:00:00 2001 From: Melissa Wen <melissa.srw@gmail.com> Date: Thu, 30 Jul 2020 17:25:24 -0300 Subject: [PATCH 0169/1494] drm/vkms: fix xrgb on compute crc The previous memset operation was not correctly zeroing the alpha channel to compute the crc, and as a result, the IGT subtest kms_cursor_crc/pipe-A-cursor-alpha-transparent fails. Fixes: db7f419c06d7c ("drm/vkms: Compute CRC with Cursor Plane") Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200730202524.5upzuh4irboru7my@smtp.gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 4af2f19480f4f..b8b060354667e 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -33,7 +33,7 @@ static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) + (i * composer->pitch) + (j * composer->cpp); /* XRGB format ignores Alpha channel */ - memset(vaddr_out + src_offset + 24, 0, 8); + bitmap_clear(vaddr_out + src_offset, 24, 8); crc = crc32_le(crc, vaddr_out + src_offset, sizeof(u32)); } -- GitLab From 70eca5d5d3e1a8139df918fe104dc63a37554789 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat, 1 Aug 2020 11:26:25 +0200 Subject: [PATCH 0170/1494] drm/syncobj: Tune down unordered timeline DRM_ERROR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Userspace can provoke this, we generally don't allow userspace to spam dmesg. Tune it down to debug. Unfortunately we don't have easy access to the drm_device here (not at all without changing a few things), so leave it as old style dmesg output for now. References: https://patchwork.freedesktop.org/series/80146/ Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Cc: "Christian König" <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200801092625.1107609-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_syncobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 3bf73971daf32..6e74e6745ecae 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -297,7 +297,7 @@ void drm_syncobj_add_point(struct drm_syncobj *syncobj, prev = drm_syncobj_fence_get(syncobj); /* You are adding an unorder point to timeline, which could cause payload returned from query_ioctl is 0! */ if (prev && prev->seqno >= point) - DRM_ERROR("You are adding an unorder point to timeline!\n"); + DRM_DEBUG("You are adding an unorder point to timeline!\n"); dma_fence_chain_init(chain, prev, fence, point); rcu_assign_pointer(syncobj->fence, &chain->base); -- GitLab From 6a470dc2a12e99608706de030c92732f166d0dc1 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:51:58 +0200 Subject: [PATCH 0171/1494] drm/ast: Embed CRTC and connector in struct ast_private Only single instances of CRTC and connector are supported per device. Embed both in ast's structure and remove the individual memory allocations. DRM's CRTC cleanup helpers replace the rsp. destroy function in ast. While at it, also convert to_ast_connector() to a function. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 33 +++++++++++++++++++-------------- drivers/gpu/drm/ast/ast_mode.c | 34 +++++++--------------------------- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index e3a264ac7ee20..e7564055fa70e 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -98,6 +98,22 @@ enum ast_tx_chip { #define AST_HWC_SIGNATURE_HOTSPOTX 0x14 #define AST_HWC_SIGNATURE_HOTSPOTY 0x18 +struct ast_i2c_chan { + struct i2c_adapter adapter; + struct drm_device *dev; + struct i2c_algo_bit_data bit; +}; + +struct ast_connector { + struct drm_connector base; + struct ast_i2c_chan *i2c; +}; + +static inline struct ast_connector * +to_ast_connector(struct drm_connector *connector) +{ + return container_of(connector, struct ast_connector, base); +} struct ast_private { struct drm_device *dev; @@ -119,9 +135,11 @@ struct ast_private { unsigned int next_index; } cursor; - struct drm_encoder encoder; struct drm_plane primary_plane; struct drm_plane cursor_plane; + struct drm_crtc crtc; + struct drm_encoder encoder; + struct ast_connector connector; bool support_wide_screen; enum { @@ -226,19 +244,6 @@ static inline void ast_open_key(struct ast_private *ast) #define AST_VIDMEM_DEFAULT_SIZE AST_VIDMEM_SIZE_8M -struct ast_i2c_chan { - struct i2c_adapter adapter; - struct drm_device *dev; - struct i2c_algo_bit_data bit; -}; - -struct ast_connector { - struct drm_connector base; - struct ast_i2c_chan *i2c; -}; - -#define to_ast_connector(x) container_of(x, struct ast_connector, base) - struct ast_vbios_stdtable { u8 misc; u8 seq[4]; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 154cd877d9d11..78f28a4e6ed89 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -831,12 +831,6 @@ static void ast_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &ast_state->base); } -static void ast_crtc_destroy(struct drm_crtc *crtc) -{ - drm_crtc_cleanup(crtc); - kfree(crtc); -} - static struct drm_crtc_state * ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc) { @@ -872,7 +866,7 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc, static const struct drm_crtc_funcs ast_crtc_funcs = { .reset = ast_crtc_reset, .gamma_set = drm_atomic_helper_legacy_gamma_set, - .destroy = ast_crtc_destroy, + .destroy = drm_crtc_cleanup, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, .atomic_duplicate_state = ast_crtc_atomic_duplicate_state, @@ -882,27 +876,19 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { static int ast_crtc_init(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); - struct drm_crtc *crtc; + struct drm_crtc *crtc = &ast->crtc; int ret; - crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); - if (!crtc) - return -ENOMEM; - ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane, &ast->cursor_plane, &ast_crtc_funcs, NULL); if (ret) - goto err_kfree; + return ret; drm_mode_crtc_set_gamma_size(crtc, 256); drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs); return 0; - -err_kfree: - kfree(crtc); - return ret; } /* @@ -1021,7 +1007,6 @@ static void ast_connector_destroy(struct drm_connector *connector) struct ast_connector *ast_connector = to_ast_connector(connector); ast_i2c_destroy(ast_connector->i2c); drm_connector_cleanup(connector); - kfree(connector); } static const struct drm_connector_helper_funcs ast_connector_helper_funcs = { @@ -1039,15 +1024,11 @@ static const struct drm_connector_funcs ast_connector_funcs = { static int ast_connector_init(struct drm_device *dev) { - struct ast_connector *ast_connector; - struct drm_connector *connector; - struct drm_encoder *encoder; - - ast_connector = kzalloc(sizeof(struct ast_connector), GFP_KERNEL); - if (!ast_connector) - return -ENOMEM; + struct ast_private *ast = to_ast_private(dev); + struct ast_connector *ast_connector = &ast->connector; + struct drm_connector *connector = &ast_connector->base; + struct drm_encoder *encoder = &ast->encoder; - connector = &ast_connector->base; ast_connector->i2c = ast_i2c_create(dev); if (!ast_connector->i2c) drm_err(dev, "failed to add ddc bus for connector\n"); @@ -1064,7 +1045,6 @@ static int ast_connector_init(struct drm_device *dev) connector->polled = DRM_CONNECTOR_POLL_CONNECT; - encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head); drm_connector_attach_encoder(connector, encoder); return 0; -- GitLab From d50ace1e72f05708cc5dbc89b9bbb9873f150092 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:51:59 +0200 Subject: [PATCH 0172/1494] drm/ast: Separate DRM driver from PCI code Putting the DRM driver to the top of the file and the PCI code to the bottom makes ast_drv.c more readable. While at it, the patch prefixes file-scope variables with ast_. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 59 ++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 0b58f7aee6b01..9d04f2b5225cf 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -43,9 +43,33 @@ int ast_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); module_param_named(modeset, ast_modeset, int, 0400); -#define PCI_VENDOR_ASPEED 0x1a03 +/* + * DRM driver + */ + +DEFINE_DRM_GEM_FOPS(ast_fops); + +static struct drm_driver ast_driver = { + .driver_features = DRIVER_ATOMIC | + DRIVER_GEM | + DRIVER_MODESET, + + .fops = &ast_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, -static struct drm_driver driver; + DRM_GEM_VRAM_DRIVER +}; + +/* + * PCI driver + */ + +#define PCI_VENDOR_ASPEED 0x1a03 #define AST_VGA_DEVICE(id, info) { \ .class = PCI_BASE_CLASS_DISPLAY << 16, \ @@ -56,13 +80,13 @@ static struct drm_driver driver; .subdevice = PCI_ANY_ID, \ .driver_data = (unsigned long) info } -static const struct pci_device_id pciidlist[] = { +static const struct pci_device_id ast_pciidlist[] = { AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL), AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL), {0, 0, 0}, }; -MODULE_DEVICE_TABLE(pci, pciidlist); +MODULE_DEVICE_TABLE(pci, ast_pciidlist); static void ast_kick_out_firmware_fb(struct pci_dev *pdev) { @@ -94,7 +118,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) return ret; - dev = drm_dev_alloc(&driver, &pdev->dev); + dev = drm_dev_alloc(&ast_driver, &pdev->dev); if (IS_ERR(dev)) return PTR_ERR(dev); @@ -118,11 +142,9 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_drm_dev_put: drm_dev_put(dev); return ret; - } -static void -ast_pci_remove(struct pci_dev *pdev) +static void ast_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); @@ -217,30 +239,12 @@ static const struct dev_pm_ops ast_pm_ops = { static struct pci_driver ast_pci_driver = { .name = DRIVER_NAME, - .id_table = pciidlist, + .id_table = ast_pciidlist, .probe = ast_pci_probe, .remove = ast_pci_remove, .driver.pm = &ast_pm_ops, }; -DEFINE_DRM_GEM_FOPS(ast_fops); - -static struct drm_driver driver = { - .driver_features = DRIVER_ATOMIC | - DRIVER_GEM | - DRIVER_MODESET, - - .fops = &ast_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, - - DRM_GEM_VRAM_DRIVER -}; - static int __init ast_init(void) { if (vgacon_text_force() && ast_modeset == -1) @@ -261,4 +265,3 @@ module_exit(ast_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); - -- GitLab From fbe01716ed4a93ff90a289c2b75313319bf08573 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:00 +0200 Subject: [PATCH 0173/1494] drm/ast: Replace driver load/unload functions with device create/destroy The ast driver's load and unload functions are left-overs from when struct drm_driver.load/unload was still in use. The PCI probe helper allocated the DRM device and ran load to initialize it. This patch replaces this code with device create and destroy. The main difference is that the device's create function allocates the DRM device and ast structures in the same place. This will be required for switching ast to managed allocations. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 24 +++++++++++------------- drivers/gpu/drm/ast/ast_drv.h | 6 ++++-- drivers/gpu/drm/ast/ast_main.c | 24 ++++++++++++++++++------ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 9d04f2b5225cf..ad93c35b4cf70 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -109,6 +109,7 @@ static void ast_kick_out_firmware_fb(struct pci_dev *pdev) static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { + struct ast_private *ast; struct drm_device *dev; int ret; @@ -118,27 +119,23 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) return ret; - dev = drm_dev_alloc(&ast_driver, &pdev->dev); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - dev->pdev = pdev; - pci_set_drvdata(pdev, dev); - - ret = ast_driver_load(dev, ent->driver_data); - if (ret) + ast = ast_device_create(&ast_driver, pdev, ent->driver_data); + if (IS_ERR(ast)) { + ret = PTR_ERR(ast); goto err_drm_dev_put; + } + dev = ast->dev; ret = drm_dev_register(dev, ent->driver_data); if (ret) - goto err_ast_driver_unload; + goto err_ast_device_destroy; drm_fbdev_generic_setup(dev, 32); return 0; -err_ast_driver_unload: - ast_driver_unload(dev); +err_ast_device_destroy: + ast_device_destroy(ast); err_drm_dev_put: drm_dev_put(dev); return ret; @@ -147,9 +144,10 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static void ast_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); + struct ast_private *ast = to_ast_private(dev); drm_dev_unregister(dev); - ast_driver_unload(dev); + ast_device_destroy(ast); drm_dev_put(dev); } diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index e7564055fa70e..210d62f69fb91 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -159,8 +159,10 @@ static inline struct ast_private *to_ast_private(struct drm_device *dev) return dev->dev_private; } -int ast_driver_load(struct drm_device *dev, unsigned long flags); -void ast_driver_unload(struct drm_device *dev); +struct ast_private *ast_device_create(struct drm_driver *drv, + struct pci_dev *pdev, + unsigned long flags); +void ast_device_destroy(struct ast_private *ast); #define AST_IO_AR_PORT_WRITE (0x40) #define AST_IO_MISC_PORT_WRITE (0x42) diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index dd12b55d57a24..8d46166f84620 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -30,6 +30,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> @@ -378,15 +379,25 @@ static int ast_get_dram_info(struct drm_device *dev) return 0; } -int ast_driver_load(struct drm_device *dev, unsigned long flags) +struct ast_private *ast_device_create(struct drm_driver *drv, + struct pci_dev *pdev, + unsigned long flags) { + struct drm_device *dev; struct ast_private *ast; bool need_post; int ret = 0; + dev = drm_dev_alloc(drv, &pdev->dev); + if (IS_ERR(dev)) + return ERR_CAST(dev); + + dev->pdev = pdev; + pci_set_drvdata(pdev, dev); + ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL); if (!ast) - return -ENOMEM; + return ERR_PTR(-ENOMEM); dev->dev_private = ast; ast->dev = dev; @@ -435,16 +446,17 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_free; - return 0; + return ast; + out_free: kfree(ast); dev->dev_private = NULL; - return ret; + return ERR_PTR(ret); } -void ast_driver_unload(struct drm_device *dev) +void ast_device_destroy(struct ast_private *ast) { - struct ast_private *ast = to_ast_private(dev); + struct drm_device *dev = ast->dev; /* enable standard VGA decode */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); -- GitLab From 365c0e70da83a52c15feb8871ba5fea2617205c6 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:01 +0200 Subject: [PATCH 0174/1494] drm/ast: Replace struct_drm_device.dev_private with to_ast_private() The ast code still references dev_private in several place when looking up the ast device structure. Convert the remaining locations to use to_ast_private(). Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 2 +- drivers/gpu/drm/ast/ast_mode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index acf0d23514e89..8d693c8b346f9 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -47,7 +47,7 @@ static void ast_cursor_fini(struct ast_private *ast) static void ast_cursor_release(struct drm_device *dev, void *ptr) { - struct ast_private *ast = dev->dev_private; + struct ast_private *ast = to_ast_private(dev); ast_cursor_fini(ast); } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 78f28a4e6ed89..cdbdf3489deec 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -663,7 +663,7 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, { struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; - struct ast_private *ast = plane->dev->dev_private; + struct ast_private *ast = to_ast_private(plane->dev); unsigned int offset_x, offset_y; offset_x = AST_MAX_HWC_WIDTH - fb->width; -- GitLab From 21d79b690e78a0e6885a6cd70fcee4a5beeda356 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:02 +0200 Subject: [PATCH 0175/1494] drm/ast: Don't use ast->dev if dev is available Several places in ast use ast->dev, when a dev pointer is already available within the function. Remove the extra indirection. No functional changes made. This is just a small cleanup before embedding the DRM device instance in struct ast_private. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-6-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 2 +- drivers/gpu/drm/ast/ast_post.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index cdbdf3489deec..897a1ad2541eb 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1079,7 +1079,7 @@ int ast_mode_config_init(struct ast_private *ast) dev->mode_config.min_height = 0; dev->mode_config.preferred_depth = 24; dev->mode_config.prefer_shadow = 1; - dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0); + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); if (ast->chip == AST2100 || ast->chip == AST2200 || diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index c043fe7175530..b1d42a639ecea 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -368,9 +368,9 @@ void ast_post_gpu(struct drm_device *dev) u32 reg; struct ast_private *ast = to_ast_private(dev); - pci_read_config_dword(ast->dev->pdev, 0x04, ®); + pci_read_config_dword(dev->pdev, 0x04, ®); reg |= 0x3; - pci_write_config_dword(ast->dev->pdev, 0x04, reg); + pci_write_config_dword(dev->pdev, 0x04, reg); ast_enable_vga(dev); ast_open_key(ast); -- GitLab From e0f5a738cfe572bed3deb08fab0b5273b9535b74 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:03 +0200 Subject: [PATCH 0176/1494] drm/ast: Embed struct drm_device in struct ast_private Turns struct ast_private into a subclass of struct drm_device by embedding the latter. This allows for using DRM's managed device allocation. The use of struct drm_device.dev_private is deprecated. The patch converts the last remaining users to to_ast_private(). Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-7-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_cursor.c | 6 ++--- drivers/gpu/drm/ast/ast_drv.c | 2 +- drivers/gpu/drm/ast/ast_drv.h | 4 +-- drivers/gpu/drm/ast/ast_main.c | 42 ++++++++++---------------------- drivers/gpu/drm/ast/ast_mm.c | 2 +- drivers/gpu/drm/ast/ast_mode.c | 2 +- drivers/gpu/drm/ast/ast_post.c | 2 +- 7 files changed, 22 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 8d693c8b346f9..6c96f74cdb9e3 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -57,7 +57,7 @@ static void ast_cursor_release(struct drm_device *dev, void *ptr) */ int ast_cursor_init(struct ast_private *ast) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; size_t size, i; struct drm_gem_vram_object *gbo; void __iomem *vaddr; @@ -168,7 +168,7 @@ static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int h int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; struct drm_gem_vram_object *gbo; int ret; void *src; @@ -217,7 +217,7 @@ static void ast_cursor_set_base(struct ast_private *ast, u64 address) void ast_cursor_page_flip(struct ast_private *ast) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; struct drm_gem_vram_object *gbo; s64 off; diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index ad93c35b4cf70..c394383a79793 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -124,7 +124,7 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ret = PTR_ERR(ast); goto err_drm_dev_put; } - dev = ast->dev; + dev = &ast->base; ret = drm_dev_register(dev, ent->driver_data); if (ret) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 210d62f69fb91..acd9bbfec98ed 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -116,7 +116,7 @@ to_ast_connector(struct drm_connector *connector) } struct ast_private { - struct drm_device *dev; + struct drm_device base; void __iomem *regs; void __iomem *ioregs; @@ -156,7 +156,7 @@ struct ast_private { static inline struct ast_private *to_ast_private(struct drm_device *dev) { - return dev->dev_private; + return container_of(dev, struct ast_private, base); } struct ast_private *ast_device_create(struct drm_driver *drv, diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 8d46166f84620..792fb7f616ecd 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -388,25 +388,17 @@ struct ast_private *ast_device_create(struct drm_driver *drv, bool need_post; int ret = 0; - dev = drm_dev_alloc(drv, &pdev->dev); - if (IS_ERR(dev)) - return ERR_CAST(dev); + ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_private, base); + if (IS_ERR(ast)) + return ast; + dev = &ast->base; dev->pdev = pdev; pci_set_drvdata(pdev, dev); - ast = kzalloc(sizeof(struct ast_private), GFP_KERNEL); - if (!ast) - return ERR_PTR(-ENOMEM); - - dev->dev_private = ast; - ast->dev = dev; - ast->regs = pci_iomap(dev->pdev, 1, 0); - if (!ast->regs) { - ret = -EIO; - goto out_free; - } + if (!ast->regs) + return ERR_PTR(-EIO); /* * If we don't have IO space at all, use MMIO now and @@ -421,17 +413,16 @@ struct ast_private *ast_device_create(struct drm_driver *drv, /* "map" IO regs if the above hasn't done so already */ if (!ast->ioregs) { ast->ioregs = pci_iomap(dev->pdev, 2, 0); - if (!ast->ioregs) { - ret = -EIO; - goto out_free; - } + if (!ast->ioregs) + return ERR_PTR(-EIO); } ast_detect_chip(dev, &need_post); ret = ast_get_dram_info(dev); if (ret) - goto out_free; + return ERR_PTR(ret); + drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n", ast->mclk, ast->dram_type, ast->dram_bus_width); @@ -440,29 +431,22 @@ struct ast_private *ast_device_create(struct drm_driver *drv, ret = ast_mm_init(ast); if (ret) - goto out_free; + return ERR_PTR(ret); ret = ast_mode_config_init(ast); if (ret) - goto out_free; + return ERR_PTR(ret); return ast; - -out_free: - kfree(ast); - dev->dev_private = NULL; - return ERR_PTR(ret); } void ast_device_destroy(struct ast_private *ast) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; /* enable standard VGA decode */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); ast_release_firmware(dev); kfree(ast->dp501_fw_addr); - - kfree(ast); } diff --git a/drivers/gpu/drm/ast/ast_mm.c b/drivers/gpu/drm/ast/ast_mm.c index 9186ec3ebbe09..8392ebde504b3 100644 --- a/drivers/gpu/drm/ast/ast_mm.c +++ b/drivers/gpu/drm/ast/ast_mm.c @@ -85,9 +85,9 @@ static void ast_mm_release(struct drm_device *dev, void *ptr) int ast_mm_init(struct ast_private *ast) { + struct drm_device *dev = &ast->base; u32 vram_size; int ret; - struct drm_device *dev = ast->dev; vram_size = ast_get_vram_size(ast); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 897a1ad2541eb..62fe682a7de63 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1063,7 +1063,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = { int ast_mode_config_init(struct ast_private *ast) { - struct drm_device *dev = ast->dev; + struct drm_device *dev = &ast->base; int ret; ret = ast_cursor_init(ast); diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index b1d42a639ecea..8902c2f84bf99 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -365,8 +365,8 @@ static void ast_init_dram_reg(struct drm_device *dev) void ast_post_gpu(struct drm_device *dev) { - u32 reg; struct ast_private *ast = to_ast_private(dev); + u32 reg; pci_read_config_dword(dev->pdev, 0x04, ®); reg |= 0x3; -- GitLab From 2c0b6566d621227ca5716d799e1b3c37e525a31d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:04 +0200 Subject: [PATCH 0177/1494] drm/ast: Managed release of ast firmware The ast driver loads firmware for the DP501 display encoder. The patch replaces the removal code with a managed release function. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-8-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_dp501.c | 23 ++++++++++++++--------- drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_main.c | 3 --- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 4b85a504825a2..88121c0e0d05c 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -8,11 +8,24 @@ MODULE_FIRMWARE("ast_dp501_fw.bin"); +static void ast_release_firmware(void *data) +{ + struct ast_private *ast = data; + + release_firmware(ast->dp501_fw); + ast->dp501_fw = NULL; +} + static int ast_load_dp501_microcode(struct drm_device *dev) { struct ast_private *ast = to_ast_private(dev); + int ret; + + ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); + if (ret) + return ret; - return request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); + return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast); } static void send_ack(struct ast_private *ast) @@ -435,11 +448,3 @@ void ast_init_3rdtx(struct drm_device *dev) } } } - -void ast_release_firmware(struct drm_device *dev) -{ - struct ast_private *ast = to_ast_private(dev); - - release_firmware(ast->dp501_fw); - ast->dp501_fw = NULL; -} diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index acd9bbfec98ed..af26483106bd7 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -312,7 +312,6 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size); bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata); u8 ast_get_dp501_max_clk(struct drm_device *dev); void ast_init_3rdtx(struct drm_device *dev); -void ast_release_firmware(struct drm_device *dev); /* ast_cursor.c */ int ast_cursor_init(struct ast_private *ast); diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 792fb7f616ecd..e3b7748335a3e 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -442,11 +442,8 @@ struct ast_private *ast_device_create(struct drm_driver *drv, void ast_device_destroy(struct ast_private *ast) { - struct drm_device *dev = &ast->base; - /* enable standard VGA decode */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); - ast_release_firmware(dev); kfree(ast->dp501_fw_addr); } -- GitLab From 4bc85b82c8ba5cfad6d750748d36e2b852fad80d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:05 +0200 Subject: [PATCH 0178/1494] drm/ast: Manage release of firmware backup memory The ast driver keeps a backup copy of the DP501 encoder's firmware. This patch adds managed release of the allocated memory. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-9-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index e3b7748335a3e..67e20727d82d7 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -33,6 +33,7 @@ #include <drm/drm_drv.h> #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_managed.h> #include "ast_drv.h" @@ -231,11 +232,11 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ast->tx_chip_type = AST_TX_SIL164; break; case 0x08: - ast->dp501_fw_addr = kzalloc(32*1024, GFP_KERNEL); + ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL); if (ast->dp501_fw_addr) { /* backup firmware */ if (ast_backup_fw(dev, ast->dp501_fw_addr, 32*1024)) { - kfree(ast->dp501_fw_addr); + drmm_kfree(dev, ast->dp501_fw_addr); ast->dp501_fw_addr = NULL; } } @@ -444,6 +445,4 @@ void ast_device_destroy(struct ast_private *ast) { /* enable standard VGA decode */ ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); - - kfree(ast->dp501_fw_addr); } -- GitLab From cff0adca1edd6eb2bc6116e4d83e442f372cca64 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 15:52:06 +0200 Subject: [PATCH 0179/1494] drm/ast: Managed device release This turns the ast's device cleanup code into a managed release helper function. Note that the code uses devres helpers. The release function switches the device back to VGA mode and therefore runs during HW device cleanup; not at DRM device cleanup. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200730135206.30239-10-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.c | 17 +++-------------- drivers/gpu/drm/ast/ast_drv.h | 1 - drivers/gpu/drm/ast/ast_main.c | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index c394383a79793..f0b4af1c390aa 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -120,35 +120,24 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return ret; ast = ast_device_create(&ast_driver, pdev, ent->driver_data); - if (IS_ERR(ast)) { - ret = PTR_ERR(ast); - goto err_drm_dev_put; - } + if (IS_ERR(ast)) + return PTR_ERR(ast); dev = &ast->base; ret = drm_dev_register(dev, ent->driver_data); if (ret) - goto err_ast_device_destroy; + return ret; drm_fbdev_generic_setup(dev, 32); return 0; - -err_ast_device_destroy: - ast_device_destroy(ast); -err_drm_dev_put: - drm_dev_put(dev); - return ret; } static void ast_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - struct ast_private *ast = to_ast_private(dev); drm_dev_unregister(dev); - ast_device_destroy(ast); - drm_dev_put(dev); } static int ast_drm_freeze(struct drm_device *dev) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index af26483106bd7..c1af6b7259339 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -162,7 +162,6 @@ static inline struct ast_private *to_ast_private(struct drm_device *dev) struct ast_private *ast_device_create(struct drm_driver *drv, struct pci_dev *pdev, unsigned long flags); -void ast_device_destroy(struct ast_private *ast); #define AST_IO_AR_PORT_WRITE (0x40) #define AST_IO_MISC_PORT_WRITE (0x42) diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 67e20727d82d7..d62749a10cdd8 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -380,6 +380,18 @@ static int ast_get_dram_info(struct drm_device *dev) return 0; } +/* + * Run this function as part of the HW device cleanup; not + * when the DRM device gets released. + */ +static void ast_device_release(void *data) +{ + struct ast_private *ast = data; + + /* enable standard VGA decode */ + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); +} + struct ast_private *ast_device_create(struct drm_driver *drv, struct pci_dev *pdev, unsigned long flags) @@ -438,11 +450,9 @@ struct ast_private *ast_device_create(struct drm_driver *drv, if (ret) return ERR_PTR(ret); - return ast; -} + ret = devm_add_action_or_reset(dev->dev, ast_device_release, ast); + if (ret) + return ERR_PTR(ret); -void ast_device_destroy(struct ast_private *ast) -{ - /* enable standard VGA decode */ - ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x04); + return ast; } -- GitLab From 0b34d58b6c321a30b5a97ec6c9a71e6f472827d2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:37 +0200 Subject: [PATCH 0180/1494] drm/mgag200: Enable caching for SHMEM pages SHMEM pages use write-combine caching by default, but can also use the platform's default page caching. Doing so may improve the performance of I/O on the framebuffer. Mgag200's hardware does not access framebuffer pages directly (i.e., via DMA), so enabling caching does not have an effect on consistency of the framebuffer memory or the displayed data. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-2-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index e19660f4a6371..7189c7745baf8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -36,6 +36,7 @@ static struct drm_driver mgag200_driver = { .major = DRIVER_MAJOR, .minor = DRIVER_MINOR, .patchlevel = DRIVER_PATCHLEVEL, + .gem_create_object = drm_gem_shmem_create_object_cached, DRM_GEM_SHMEM_DRIVER_OPS, }; -- GitLab From 42452165dc7777e144f8a8550f5fcf484597715d Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:38 +0200 Subject: [PATCH 0181/1494] drm/mgag200: Move register initialization into helper function The mgag200 driver maps registers into the address space. Move the code into a separate helper function. No functional changes. One small difference is in the handling of SDRAM/SGRAM. MGA devices can come with either SDRAM or SGRAM. So far, the driver checked for SDRAM, which is the common case. The patch moves this code into a separate helper and checks for SGRAM, which is the special case. The test itself is the same as before. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-3-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 37 ++++++++++++++++++++++----- drivers/gpu/drm/mgag200/mgag200_reg.h | 2 ++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 7189c7745baf8..e50c682c4702a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -44,18 +44,26 @@ static struct drm_driver mgag200_driver = { * DRM device */ -static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) +static bool mgag200_has_sgram(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; - int ret, option; + u32 option; + int ret; - mdev->flags = mgag200_flags_from_driver_data(flags); - mdev->type = mgag200_type_from_driver_data(flags); + ret = pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option); + if (drm_WARN(dev, ret, "failed to read PCI config dword: %d\n", ret)) + return false; + + return !!(option & PCI_MGA_OPTION_HARDPWMSK); +} - pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option); - mdev->has_sdram = !(option & (1 << 14)); +static int mgag200_regs_init(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + + mdev->has_sdram = !mgag200_has_sgram(mdev); - /* BAR 0 is the framebuffer, BAR 1 contains registers */ + /* BAR 1 contains registers */ mdev->rmmio_base = pci_resource_start(dev->pdev, 1); mdev->rmmio_size = pci_resource_len(dev->pdev, 1); @@ -69,6 +77,21 @@ static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) if (mdev->rmmio == NULL) return -ENOMEM; + return 0; +} + +static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) +{ + struct drm_device *dev = &mdev->base; + int ret; + + mdev->flags = mgag200_flags_from_driver_data(flags); + mdev->type = mgag200_type_from_driver_data(flags); + + ret = mgag200_regs_init(mdev); + if (ret) + return ret; + /* stash G200 SE model number for later use */ if (IS_G200_SE(mdev)) { mdev->unique_rev_id = RREG32(0x1e24); diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index c3b7bcad52ed1..a44c08bf40741 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -282,6 +282,8 @@ #define PCI_MGA_OPTION2 0x50 #define PCI_MGA_OPTION3 0x54 +#define PCI_MGA_OPTION_HARDPWMSK BIT(14) + #define RAMDAC_OFFSET 0x3c00 /* TVP3026 direct registers */ -- GitLab From 2021708e0d6eed7b5a8bd11071ae1ac40df6c060 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:39 +0200 Subject: [PATCH 0182/1494] drm/mgag200: Initialize PCI registers early during device setup So far, PCI option registers were initialized as part of modesetting, which is late in the process. As these registers control fundamental operation, they should be set early. The patch moves the PCI option handling into device register setup, before even the device MMIO memory is being mapped. No functional changes made. Moving the PCI code next to the device-register setup also allows to remove the has_sdram field from struct mga_device. The state is now local to the init helper. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-4-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 32 +++++++++++++++++++- drivers/gpu/drm/mgag200/mgag200_drv.h | 1 - drivers/gpu/drm/mgag200/mgag200_mode.c | 41 -------------------------- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index e50c682c4702a..3dbb00045c241 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -60,8 +60,38 @@ static bool mgag200_has_sgram(struct mga_device *mdev) static int mgag200_regs_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; + u32 option, option2; + + switch (mdev->type) { + case G200_SE_A: + case G200_SE_B: + if (mgag200_has_sgram(mdev)) + option |= PCI_MGA_OPTION_HARDPWMSK; + option2 = 0x00008000; + break; + case G200_WB: + case G200_EW3: + option = 0x41049120; + option2 = 0x0000b000; + break; + case G200_EV: + option = 0x00000120; + option2 = 0x0000b000; + break; + case G200_EH: + case G200_EH3: + option = 0x00000120; + option2 = 0x0000b000; + break; + default: + option = 0; + option2 = 0; + } - mdev->has_sdram = !mgag200_has_sgram(mdev); + if (option) + pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option); + if (option2) + pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2); /* BAR 1 contains registers */ mdev->rmmio_base = pci_resource_start(dev->pdev, 1); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 3817520bfefc7..819c03cc626b6 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -161,7 +161,6 @@ struct mga_device { size_t vram_fb_available; enum mga_type type; - int has_sdram; int bpp_shifts[4]; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index e0d037a7413c6..3aa078e69a5ab 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -9,7 +9,6 @@ */ #include <linux/delay.h> -#include <linux/pci.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_state_helper.h> @@ -877,45 +876,6 @@ static void mgag200_set_startadd(struct mga_device *mdev, WREG_ECRT(0x00, crtcext0); } -static void mgag200_set_pci_regs(struct mga_device *mdev) -{ - uint32_t option = 0, option2 = 0; - struct drm_device *dev = &mdev->base; - - switch (mdev->type) { - case G200_SE_A: - case G200_SE_B: - if (mdev->has_sdram) - option = 0x40049120; - else - option = 0x4004d120; - option2 = 0x00008000; - break; - case G200_WB: - case G200_EW3: - option = 0x41049120; - option2 = 0x0000b000; - break; - case G200_EV: - option = 0x00000120; - option2 = 0x0000b000; - break; - case G200_EH: - case G200_EH3: - option = 0x00000120; - option2 = 0x0000b000; - break; - case G200_ER: - break; - } - - if (option) - pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option); - - if (option2) - pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2); -} - static void mgag200_set_dac_regs(struct mga_device *mdev) { size_t i; @@ -988,7 +948,6 @@ static void mgag200_init_regs(struct mga_device *mdev) { u8 crtc11, crtcext3, crtcext4, misc; - mgag200_set_pci_regs(mdev); mgag200_set_dac_regs(mdev); WREG_SEQ(2, 0x0f); -- GitLab From 78e5b5036a1ebcb937452a72364d77538ad6e41f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:40 +0200 Subject: [PATCH 0183/1494] drm/mgag200: Enable MGA mode during device register initialization MGA cards can run in traditional VGA mode or an enhanced MGA mode; with the latter being required for KMS. So far, MGA mode was enabled during modesetting. As it's fundamental for device operation, the patch moves it next to the device register setup. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-5-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 5 +++++ drivers/gpu/drm/mgag200/mgag200_mode.c | 6 +----- drivers/gpu/drm/mgag200/mgag200_reg.h | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 3dbb00045c241..ac9ac5b6d587a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -61,6 +61,7 @@ static int mgag200_regs_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; u32 option, option2; + u8 crtcext3; switch (mdev->type) { case G200_SE_A: @@ -107,6 +108,10 @@ static int mgag200_regs_init(struct mga_device *mdev) if (mdev->rmmio == NULL) return -ENOMEM; + RREG_ECRT(0x03, crtcext3); + crtcext3 |= MGAREG_CRTCEXT3_MGAMODE; + WREG_ECRT(0x03, crtcext3); + return 0; } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 3aa078e69a5ab..7161b1651aa03 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -946,7 +946,7 @@ static void mgag200_set_dac_regs(struct mga_device *mdev) static void mgag200_init_regs(struct mga_device *mdev) { - u8 crtc11, crtcext3, crtcext4, misc; + u8 crtc11, crtcext4, misc; mgag200_set_dac_regs(mdev); @@ -961,12 +961,8 @@ static void mgag200_init_regs(struct mga_device *mdev) WREG_CRT(14, 0); WREG_CRT(15, 0); - RREG_ECRT(0x03, crtcext3); - - crtcext3 |= BIT(7); /* enable MGA mode */ crtcext4 = 0x00; - WREG_ECRT(0x03, crtcext3); WREG_ECRT(0x04, crtcext4); RREG_CRT(0x11, crtc11); diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h index a44c08bf40741..977be0565c061 100644 --- a/drivers/gpu/drm/mgag200/mgag200_reg.h +++ b/drivers/gpu/drm/mgag200/mgag200_reg.h @@ -256,6 +256,8 @@ #define MGAREG_CRTCEXT1_VSYNCOFF BIT(5) #define MGAREG_CRTCEXT1_HSYNCOFF BIT(4) +#define MGAREG_CRTCEXT3_MGAMODE BIT(7) + /* Cursor X and Y position */ #define MGA_CURPOSXL 0x3c0c #define MGA_CURPOSXH 0x3c0d -- GitLab From b9fa77ec1a59f71b0a9b79954ce2429dee434e57 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:41 +0200 Subject: [PATCH 0184/1494] drm/mgag200: Set MISC memory flags in mm init code The modesetting code initialized several memory-related flags in the MISC register. Move this code to MM initialization. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-6-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mm.c | 6 ++++++ drivers/gpu/drm/mgag200/mgag200_mode.c | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mm.c b/drivers/gpu/drm/mgag200/mgag200_mm.c index 7b69392bcb891..1b1918839e1e8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mm.c +++ b/drivers/gpu/drm/mgag200/mgag200_mm.c @@ -90,9 +90,15 @@ static void mgag200_mm_release(struct drm_device *dev, void *ptr) int mgag200_mm_init(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; + u8 misc; resource_size_t start, len; int ret; + misc = RREG8(MGA_MISC_IN); + misc |= MGAREG_MISC_RAMMAPEN | + MGAREG_MISC_HIGH_PG_SEL; + WREG8(MGA_MISC_OUT, misc); + /* BAR 0 is VRAM */ start = pci_resource_start(dev->pdev, 0); len = pci_resource_len(dev->pdev, 0); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 7161b1651aa03..66818ee10694f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -978,9 +978,7 @@ static void mgag200_init_regs(struct mga_device *mdev) WREG_ECRT(0x34, 0x5); misc = RREG8(MGA_MISC_IN); - misc |= MGAREG_MISC_IOADSEL | - MGAREG_MISC_RAMMAPEN | - MGAREG_MISC_HIGH_PG_SEL; + misc |= MGAREG_MISC_IOADSEL; WREG8(MGA_MISC_OUT, misc); } -- GitLab From 9053cad2f0935d3614b49926de571c677fa38528 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:42 +0200 Subject: [PATCH 0185/1494] drm/mgag200: Clear <page> field during MM init The modesetting code initialized the memory-related register CRTCEXT4. Move this code to MM initialization. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-7-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_mm.c | 2 ++ drivers/gpu/drm/mgag200/mgag200_mode.c | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_mm.c b/drivers/gpu/drm/mgag200/mgag200_mm.c index 1b1918839e1e8..641f1aa992be3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mm.c +++ b/drivers/gpu/drm/mgag200/mgag200_mm.c @@ -94,6 +94,8 @@ int mgag200_mm_init(struct mga_device *mdev) resource_size_t start, len; int ret; + WREG_ECRT(0x04, 0x00); + misc = RREG8(MGA_MISC_IN); misc |= MGAREG_MISC_RAMMAPEN | MGAREG_MISC_HIGH_PG_SEL; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 66818ee10694f..4fa64cf884cbd 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -946,7 +946,7 @@ static void mgag200_set_dac_regs(struct mga_device *mdev) static void mgag200_init_regs(struct mga_device *mdev) { - u8 crtc11, crtcext4, misc; + u8 crtc11, misc; mgag200_set_dac_regs(mdev); @@ -961,10 +961,6 @@ static void mgag200_init_regs(struct mga_device *mdev) WREG_CRT(14, 0); WREG_CRT(15, 0); - crtcext4 = 0x00; - - WREG_ECRT(0x04, crtcext4); - RREG_CRT(0x11, crtc11); crtc11 &= ~(MGAREG_CRTC11_CRTCPROTECT | MGAREG_CRTC11_VINTEN | -- GitLab From fb18825fa0380b7ee913925996b2d3477d57628c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:43 +0200 Subject: [PATCH 0186/1494] drm/mgag200: Move G200SE's unique id into model-specific data The unique revision id is only useful for G200SE devices. Store the value in model-specific data within struct mga_device. While at it, the patch also adds an init helper for the value. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-8-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 19 +++++++++++++------ drivers/gpu/drm/mgag200/mgag200_drv.h | 8 ++++++-- drivers/gpu/drm/mgag200/mgag200_mode.c | 18 +++++++++++------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ac9ac5b6d587a..f7652e16365c8 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -115,6 +115,17 @@ static int mgag200_regs_init(struct mga_device *mdev) return 0; } +static void mgag200_g200se_init_unique_id(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + + /* stash G200 SE model number for later use */ + mdev->model.g200se.unique_rev_id = RREG32(0x1e24); + + drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", + mdev->model.g200se.unique_rev_id); +} + static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) { struct drm_device *dev = &mdev->base; @@ -127,12 +138,8 @@ static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) if (ret) return ret; - /* stash G200 SE model number for later use */ - if (IS_G200_SE(mdev)) { - mdev->unique_rev_id = RREG32(0x1e24); - drm_dbg(dev, "G200 SE unique revision id is 0x%x\n", - mdev->unique_rev_id); - } + if (IS_G200_SE(mdev)) + mgag200_g200se_init_unique_id(mdev); ret = mgag200_mm_init(mdev); if (ret) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 819c03cc626b6..048efe635affe 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -166,8 +166,12 @@ struct mga_device { int fb_mtrr; - /* SE model number stored in reg 0x1e24 */ - u32 unique_rev_id; + union { + struct { + /* SE model number stored in reg 0x1e24 */ + u32 unique_rev_id; + } g200se; + } model; struct mga_connector connector; struct drm_simple_display_pipe display_pipe; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 4fa64cf884cbd..752409c7f326b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -112,6 +112,7 @@ static inline void mga_wait_busy(struct mga_device *mdev) static int mga_g200se_set_plls(struct mga_device *mdev, long clock) { + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; unsigned int vcomax, vcomin, pllreffreq; unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn; @@ -121,7 +122,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock) unsigned int fvv; unsigned int i; - if (mdev->unique_rev_id <= 0x03) { + if (unique_rev_id <= 0x03) { m = n = p = 0; vcomax = 320000; @@ -219,7 +220,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock) WREG_DAC(MGA1064_PIX_PLLC_N, n); WREG_DAC(MGA1064_PIX_PLLC_P, p); - if (mdev->unique_rev_id >= 0x04) { + if (unique_rev_id >= 0x04) { WREG_DAC(0x1a, 0x09); msleep(20); WREG_DAC(0x1a, 0x01); @@ -1183,12 +1184,13 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, const struct drm_display_mode *mode, const struct drm_framebuffer *fb) { + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; unsigned int hiprilvl; u8 crtcext6; - if (mdev->unique_rev_id >= 0x04) { + if (unique_rev_id >= 0x04) { hiprilvl = 0; - } else if (mdev->unique_rev_id >= 0x02) { + } else if (unique_rev_id >= 0x02) { unsigned int bpp; unsigned long mb; @@ -1213,7 +1215,7 @@ static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev, else hiprilvl = 5; - } else if (mdev->unique_rev_id >= 0x01) { + } else if (unique_rev_id >= 0x01) { hiprilvl = 3; } else { hiprilvl = 4; @@ -1337,7 +1339,9 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector, int bpp = 32; if (IS_G200_SE(mdev)) { - if (mdev->unique_rev_id == 0x01) { + u32 unique_rev_id = mdev->model.g200se.unique_rev_id; + + if (unique_rev_id == 0x01) { if (mode->hdisplay > 1600) return MODE_VIRTUAL_X; if (mode->vdisplay > 1200) @@ -1345,7 +1349,7 @@ static enum drm_mode_status mga_vga_mode_valid(struct drm_connector *connector, if (mga_vga_calculate_mode_bandwidth(mode, bpp) > (24400 * 1024)) return MODE_BANDWIDTH; - } else if (mdev->unique_rev_id == 0x02) { + } else if (unique_rev_id == 0x02) { if (mode->hdisplay > 1920) return MODE_VIRTUAL_X; if (mode->vdisplay > 1200) -- GitLab From e20dfd27f7aa257ce01992540a36bc4e818f8452 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Thu, 30 Jul 2020 12:28:44 +0200 Subject: [PATCH 0187/1494] drm/mgag200: Add support for G200 desktop cards This patch adds support for G200 desktop cards. We can reuse the whole memory and modesetting code. A few PCI and DAC register values have to be updated accordingly. The most significant change is in the PLL setup. The driver parses the device's BIOS to retrieve clock limits and reference clocks. With no BIOS found, safe defaults are being used. v2: * copy BIOS ROM to system memory and access with regular load/store; resolves potential HW limitations * fix some stray whitespaces Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Co-developed-by: Egbert Eich <eich@suse.com> Signed-off-by: Egbert Eich <eich@suse.com> Co-developed-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Takashi Iwai <tiwai@suse.de> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730102844.10995-9-tzimmermann@suse.de --- MAINTAINERS | 2 +- drivers/gpu/drm/mgag200/Kconfig | 12 +-- drivers/gpu/drm/mgag200/mgag200_drv.c | 137 ++++++++++++++++++++++++- drivers/gpu/drm/mgag200/mgag200_drv.h | 10 ++ drivers/gpu/drm/mgag200/mgag200_mode.c | 80 +++++++++++++++ 5 files changed, 232 insertions(+), 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5d7130f8d3421..f12a868b10fdf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5406,7 +5406,7 @@ S: Orphan / Obsolete F: drivers/gpu/drm/mga/ F: include/uapi/drm/mga_drm.h -DRM DRIVER FOR MGA G200 SERVER GRAPHICS CHIPS +DRM DRIVER FOR MGA G200 GRAPHICS CHIPS M: Dave Airlie <airlied@redhat.com> S: Odd Fixes F: drivers/gpu/drm/mgag200/ diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig index 93be766715c9b..eec59658a938b 100644 --- a/drivers/gpu/drm/mgag200/Kconfig +++ b/drivers/gpu/drm/mgag200/Kconfig @@ -1,13 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_MGAG200 - tristate "Kernel modesetting driver for MGA G200 server engines" + tristate "Matrox G200" depends on DRM && PCI && MMU select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER help - This is a KMS driver for the MGA G200 server chips, it - does not support the original MGA G200 or any of the desktop - chips. It requires 0.3.0 of the modesetting userspace driver, - and a version of mga driver that will fail on KMS enabled - devices. - + This is a KMS driver for Matrox G200 chips. It supports the original + MGA G200 desktop chips and the server variants. It requires 0.3.0 + of the modesetting userspace driver, and a version of mga driver + that will fail on KMS enabled devices. diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index f7652e16365c8..5c854bc7dc86f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -64,6 +64,14 @@ static int mgag200_regs_init(struct mga_device *mdev) u8 crtcext3; switch (mdev->type) { + case G200_PCI: + case G200_AGP: + if (mgag200_has_sgram(mdev)) + option = 0x4049cd21; + else + option = 0x40499121; + option2 = 0x00008000; + break; case G200_SE_A: case G200_SE_B: if (mgag200_has_sgram(mdev)) @@ -115,6 +123,129 @@ static int mgag200_regs_init(struct mga_device *mdev) return 0; } +static void mgag200_g200_interpret_bios(struct mga_device *mdev, + const unsigned char *bios, + size_t size) +{ + static const char matrox[] = {'M', 'A', 'T', 'R', 'O', 'X'}; + static const unsigned int expected_length[6] = { + 0, 64, 64, 64, 128, 128 + }; + struct drm_device *dev = &mdev->base; + const unsigned char *pins; + unsigned int pins_len, version; + int offset; + int tmp; + + /* Test for MATROX string. */ + if (size < 45 + sizeof(matrox)) + return; + if (memcmp(&bios[45], matrox, sizeof(matrox)) != 0) + return; + + /* Get the PInS offset. */ + if (size < MGA_BIOS_OFFSET + 2) + return; + offset = (bios[MGA_BIOS_OFFSET + 1] << 8) | bios[MGA_BIOS_OFFSET]; + + /* Get PInS data structure. */ + + if (size < offset + 6) + return; + pins = bios + offset; + if (pins[0] == 0x2e && pins[1] == 0x41) { + version = pins[5]; + pins_len = pins[2]; + } else { + version = 1; + pins_len = pins[0] + (pins[1] << 8); + } + + if (version < 1 || version > 5) { + drm_warn(dev, "Unknown BIOS PInS version: %d\n", version); + return; + } + if (pins_len != expected_length[version]) { + drm_warn(dev, "Unexpected BIOS PInS size: %d expeced: %d\n", + pins_len, expected_length[version]); + return; + } + if (size < offset + pins_len) + return; + + drm_dbg_kms(dev, "MATROX BIOS PInS version %d size: %d found\n", + version, pins_len); + + /* Extract the clock values */ + + switch (version) { + case 1: + tmp = pins[24] + (pins[25] << 8); + if (tmp) + mdev->model.g200.pclk_max = tmp * 10; + break; + case 2: + if (pins[41] != 0xff) + mdev->model.g200.pclk_max = (pins[41] + 100) * 1000; + break; + case 3: + if (pins[36] != 0xff) + mdev->model.g200.pclk_max = (pins[36] + 100) * 1000; + if (pins[52] & 0x20) + mdev->model.g200.ref_clk = 14318; + break; + case 4: + if (pins[39] != 0xff) + mdev->model.g200.pclk_max = pins[39] * 4 * 1000; + if (pins[92] & 0x01) + mdev->model.g200.ref_clk = 14318; + break; + case 5: + tmp = pins[4] ? 8000 : 6000; + if (pins[123] != 0xff) + mdev->model.g200.pclk_min = pins[123] * tmp; + if (pins[38] != 0xff) + mdev->model.g200.pclk_max = pins[38] * tmp; + if (pins[110] & 0x01) + mdev->model.g200.ref_clk = 14318; + break; + default: + break; + } +} + +static void mgag200_g200_init_refclk(struct mga_device *mdev) +{ + struct drm_device *dev = &mdev->base; + unsigned char __iomem *rom; + unsigned char *bios; + size_t size; + + mdev->model.g200.pclk_min = 50000; + mdev->model.g200.pclk_max = 230000; + mdev->model.g200.ref_clk = 27050; + + rom = pci_map_rom(dev->pdev, &size); + if (!rom) + return; + + bios = vmalloc(size); + if (!bios) + goto out; + memcpy_fromio(bios, rom, size); + + if (size != 0 && bios[0] == 0x55 && bios[1] == 0xaa) + mgag200_g200_interpret_bios(mdev, bios, size); + + drm_dbg_kms(dev, "pclk_min: %ld pclk_max: %ld ref_clk: %ld\n", + mdev->model.g200.pclk_min, mdev->model.g200.pclk_max, + mdev->model.g200.ref_clk); + + vfree(bios); +out: + pci_unmap_rom(dev->pdev, rom); +} + static void mgag200_g200se_init_unique_id(struct mga_device *mdev) { struct drm_device *dev = &mdev->base; @@ -138,7 +269,9 @@ static int mgag200_device_init(struct mga_device *mdev, unsigned long flags) if (ret) return ret; - if (IS_G200_SE(mdev)) + if (mdev->type == G200_PCI || mdev->type == G200_AGP) + mgag200_g200_init_refclk(mdev); + else if (IS_G200_SE(mdev)) mgag200_g200se_init_unique_id(mdev); ret = mgag200_mm_init(mdev); @@ -182,6 +315,8 @@ mgag200_device_create(struct pci_dev *pdev, unsigned long flags) */ static const struct pci_device_id mgag200_pciidlist[] = { + { PCI_VENDOR_ID_MATROX, 0x520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_PCI }, + { PCI_VENDOR_ID_MATROX, 0x521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_AGP }, { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD}, { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 048efe635affe..749a075fe9e4c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -38,6 +38,8 @@ #define RREG32(reg) ioread32(((void __iomem *)mdev->rmmio) + (reg)) #define WREG32(reg, v) iowrite32(v, ((void __iomem *)mdev->rmmio) + (reg)) +#define MGA_BIOS_OFFSET 0x7ffc + #define ATTR_INDEX 0x1fc0 #define ATTR_DATA 0x1fc1 @@ -129,6 +131,8 @@ struct mga_mc { }; enum mga_type { + G200_PCI, + G200_AGP, G200_SE_A, G200_SE_B, G200_WB, @@ -167,12 +171,18 @@ struct mga_device { int fb_mtrr; union { + struct { + long ref_clk; + long pclk_min; + long pclk_max; + } g200; struct { /* SE model number stored in reg 0x1e24 */ u32 unique_rev_id; } g200se; } model; + struct mga_connector connector; struct drm_simple_display_pipe display_pipe; }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 752409c7f326b..38672f9e5c4f3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -108,6 +108,77 @@ static inline void mga_wait_busy(struct mga_device *mdev) } while ((status & 0x01) && time_before(jiffies, timeout)); } +/* + * PLL setup + */ + +static int mgag200_g200_set_plls(struct mga_device *mdev, long clock) +{ + struct drm_device *dev = &mdev->base; + const int post_div_max = 7; + const int in_div_min = 1; + const int in_div_max = 6; + const int feed_div_min = 7; + const int feed_div_max = 127; + u8 testm, testn; + u8 n = 0, m = 0, p, s; + long f_vco; + long computed; + long delta, tmp_delta; + long ref_clk = mdev->model.g200.ref_clk; + long p_clk_min = mdev->model.g200.pclk_min; + long p_clk_max = mdev->model.g200.pclk_max; + + if (clock > p_clk_max) { + drm_err(dev, "Pixel Clock %ld too high\n", clock); + return 1; + } + + if (clock < p_clk_min >> 3) + clock = p_clk_min >> 3; + + f_vco = clock; + for (p = 0; + p <= post_div_max && f_vco < p_clk_min; + p = (p << 1) + 1, f_vco <<= 1) + ; + + delta = clock; + + for (testm = in_div_min; testm <= in_div_max; testm++) { + for (testn = feed_div_min; testn <= feed_div_max; testn++) { + computed = ref_clk * (testn + 1) / (testm + 1); + if (computed < f_vco) + tmp_delta = f_vco - computed; + else + tmp_delta = computed - f_vco; + if (tmp_delta < delta) { + delta = tmp_delta; + m = testm; + n = testn; + } + } + } + f_vco = ref_clk * (n + 1) / (m + 1); + if (f_vco < 100000) + s = 0; + else if (f_vco < 140000) + s = 1; + else if (f_vco < 180000) + s = 2; + else + s = 3; + + drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n", + clock, f_vco, m, n, p, s); + + WREG_DAC(MGA1064_PIX_PLLC_M, m); + WREG_DAC(MGA1064_PIX_PLLC_N, n); + WREG_DAC(MGA1064_PIX_PLLC_P, (p | (s << 3))); + + return 0; +} + #define P_ARRAY_SIZE 9 static int mga_g200se_set_plls(struct mga_device *mdev, long clock) @@ -717,6 +788,9 @@ static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock) u8 misc; switch(mdev->type) { + case G200_PCI: + case G200_AGP: + return mgag200_g200_set_plls(mdev, clock); case G200_SE_A: case G200_SE_B: return mga_g200se_set_plls(mdev, clock); @@ -894,6 +968,12 @@ static void mgag200_set_dac_regs(struct mga_device *mdev) }; switch (mdev->type) { + case G200_PCI: + case G200_AGP: + dacvalue[MGA1064_SYS_PLL_M] = 0x04; + dacvalue[MGA1064_SYS_PLL_N] = 0x2D; + dacvalue[MGA1064_SYS_PLL_P] = 0x19; + break; case G200_SE_A: case G200_SE_B: dacvalue[MGA1064_VREF_CTL] = 0x03; -- GitLab From 2d05f56af8f52d52dc614ddf4d51c00ea5afb67f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Wed, 29 Jul 2020 15:41:44 +0200 Subject: [PATCH 0188/1494] fbdev: Remove trailing whitespace Removes trailing whitespaces in several places. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200729134148.6855-2-tzimmermann@suse.de --- drivers/video/fbdev/core/fbmem.c | 10 +++++----- include/linux/fb.h | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 30e73ec4ad5c8..dd0ccf35f7b79 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -777,7 +777,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_read) return info->fbops->fb_read(info, buf, count, ppos); - + total_size = info->screen_size; if (total_size == 0) @@ -842,7 +842,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_write) return info->fbops->fb_write(info, buf, count, ppos); - + total_size = info->screen_size; if (total_size == 0) @@ -1061,7 +1061,7 @@ EXPORT_SYMBOL(fb_set_var); int fb_blank(struct fb_info *info, int blank) -{ +{ struct fb_event event; int ret = -EINVAL; @@ -1437,7 +1437,7 @@ __releases(&info->lock) return res; } -static int +static int fb_release(struct inode *inode, struct file *file) __acquires(&info->lock) __releases(&info->lock) @@ -1627,7 +1627,7 @@ static int do_register_framebuffer(struct fb_info *fb_info) fb_info->pixmap.access_align = 32; fb_info->pixmap.flags = FB_PIXMAP_DEFAULT; } - } + } fb_info->pixmap.offset = 0; if (!fb_info->pixmap.blit_x) diff --git a/include/linux/fb.h b/include/linux/fb.h index 2b530e6d86e4a..714187bc13ac8 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -124,7 +124,7 @@ struct fb_cursor_user { * Register/unregister for framebuffer events */ -/* The resolution of the passed in fb_info about to change */ +/* The resolution of the passed in fb_info about to change */ #define FB_EVENT_MODE_CHANGE 0x01 #ifdef CONFIG_GUMSTIX_AM200EPD @@ -459,12 +459,12 @@ struct fb_info { #if IS_ENABLED(CONFIG_FB_BACKLIGHT) /* assigned backlight device */ - /* set before framebuffer registration, + /* set before framebuffer registration, remove after unregister */ struct backlight_device *bl_dev; /* Backlight level curve */ - struct mutex bl_curve_mutex; + struct mutex bl_curve_mutex; u8 bl_curve[FB_BACKLIGHT_LEVELS]; #endif #ifdef CONFIG_FB_DEFERRED_IO @@ -483,8 +483,8 @@ struct fb_info { char __iomem *screen_base; /* Virtual address */ char *screen_buffer; }; - unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ - void *pseudo_palette; /* Fake palette of 16 colors */ + unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ + void *pseudo_palette; /* Fake palette of 16 colors */ #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 u32 state; /* Hardware state i.e suspend */ @@ -587,11 +587,11 @@ static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { * `Generic' versions of the frame buffer device operations */ -extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); -extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); +extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); +extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_blank(struct fb_info *info, int blank); -extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); +extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); /* * Drawing operations where framebuffer is in system RAM -- GitLab From 85806f6d58f4db8aa398833ce46fedcd82ab58a1 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Mon, 6 Jul 2020 14:59:31 +0200 Subject: [PATCH 0189/1494] omapfb/dss: Include the right header The hdmi4.c and hdmi5.c files include the legacy GPIO header <linux/gpio.h> but does not use any of the symbols from this file. What it does use is the implicit inclusion of <linux/of.h> leading to compile errors if we just drop this include. Include the right header. Cc: Tony Lindgren <tony@atomide.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200706125931.752539-1-linus.walleij@linaro.org --- drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c | 2 +- drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c index 22f1d37a968ab..496b43bdad211 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c @@ -19,7 +19,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/clk.h> -#include <linux/gpio.h> +#include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <video/omapfb_dss.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c index a06b6f1355bdb..e3d441ade241d 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c @@ -24,7 +24,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/clk.h> -#include <linux/gpio.h> +#include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <video/omapfb_dss.h> -- GitLab From ad04fae0de07580359b7ab3e19a678a775fdf07f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" <gustavoars@kernel.org> Date: Tue, 7 Jul 2020 16:05:39 -0500 Subject: [PATCH 0190/1494] fbdev: Use fallthrough pseudo-keyword Replace the existing /* fall through */ comments and its variants with the new pseudo-keyword macro fallthrough[1]. Also, remove unnecessary fall-through markings when it is the case. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html?highlight=fallthrough#implicit-switch-case-fall-through Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200707210539.GA12530@embeddedor --- drivers/video/fbdev/acornfb.c | 2 +- drivers/video/fbdev/arcfb.c | 2 +- drivers/video/fbdev/atmel_lcdfb.c | 4 ++-- drivers/video/fbdev/aty/radeon_pm.c | 6 +++--- drivers/video/fbdev/cirrusfb.c | 4 ++-- drivers/video/fbdev/controlfb.c | 2 +- drivers/video/fbdev/core/fbmem.c | 2 +- drivers/video/fbdev/fsl-diu-fb.c | 4 ++-- drivers/video/fbdev/gxt4500.c | 2 +- drivers/video/fbdev/i740fb.c | 2 +- drivers/video/fbdev/offb.c | 4 ++-- drivers/video/fbdev/omap/lcdc.c | 4 ++-- drivers/video/fbdev/omap/omapfb_main.c | 20 +++++++++---------- drivers/video/fbdev/omap2/omapfb/dss/dispc.c | 4 ++-- .../video/fbdev/omap2/omapfb/omapfb-ioctl.c | 2 +- .../video/fbdev/omap2/omapfb/omapfb-main.c | 2 +- drivers/video/fbdev/pm2fb.c | 4 ++-- drivers/video/fbdev/pxafb.c | 2 +- drivers/video/fbdev/s3c-fb.c | 6 +++--- drivers/video/fbdev/sa1100fb.c | 2 +- drivers/video/fbdev/savage/savagefb_driver.c | 3 +-- drivers/video/fbdev/sh_mobile_lcdcfb.c | 4 ++-- drivers/video/fbdev/sm501fb.c | 2 +- drivers/video/fbdev/tdfxfb.c | 2 +- drivers/video/fbdev/xen-fbfront.c | 2 +- 25 files changed, 46 insertions(+), 47 deletions(-) diff --git a/drivers/video/fbdev/acornfb.c b/drivers/video/fbdev/acornfb.c index 09a9ad901dad8..bcc92aecf6668 100644 --- a/drivers/video/fbdev/acornfb.c +++ b/drivers/video/fbdev/acornfb.c @@ -857,7 +857,7 @@ static void acornfb_parse_dram(char *opt) case 'M': case 'm': size *= 1024; - /* Fall through */ + fallthrough; case 'K': case 'k': size *= 1024; diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c index 6f7838979f0a9..1447324ed0b64 100644 --- a/drivers/video/fbdev/arcfb.c +++ b/drivers/video/fbdev/arcfb.c @@ -419,7 +419,7 @@ static int arcfb_ioctl(struct fb_info *info, schedule(); finish_wait(&arcfb_waitq, &wait); } - /* fall through */ + fallthrough; case FBIO_GETCONTROL2: { diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c index 1e252192569a8..8c1d47e52b1a6 100644 --- a/drivers/video/fbdev/atmel_lcdfb.c +++ b/drivers/video/fbdev/atmel_lcdfb.c @@ -508,7 +508,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, case 32: var->transp.offset = 24; var->transp.length = 8; - /* fall through */ + fallthrough; case 24: if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { /* RGB:888 mode */ @@ -633,7 +633,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; - case 15: /* fall through */ + case 15: fallthrough; case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index 7c4483c7f313a..f3d8123d7f363 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c @@ -1208,11 +1208,11 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo) case 1: if (mc & 0x4) break; - /* fall through */ + fallthrough; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET; - /* fall through */ + fallthrough; case 0: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET; @@ -1221,7 +1221,7 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo) case 1: if (!(mc & 0x4)) break; - /* fall through */ + fallthrough; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET; diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c index 3df64a9731945..15a9ee7cd734d 100644 --- a/drivers/video/fbdev/cirrusfb.c +++ b/drivers/video/fbdev/cirrusfb.c @@ -1476,11 +1476,11 @@ static void init_vgachip(struct fb_info *info) mdelay(100); /* mode */ vga_wgfx(cinfo->regbase, CL_GR31, 0x00); - /* fall through */ + fallthrough; case BT_GD5480: /* from Klaus' NetBSD driver: */ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); - /* fall through */ + fallthrough; case BT_ALPINE: /* put blitter into 542x compat */ vga_wgfx(cinfo->regbase, CL_GR33, 0x00); diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c index 9c4f1be856eca..a88dcb63eeb45 100644 --- a/drivers/video/fbdev/controlfb.c +++ b/drivers/video/fbdev/controlfb.c @@ -713,7 +713,7 @@ static int controlfb_blank(int blank_mode, struct fb_info *info) break; case FB_BLANK_POWERDOWN: ctrl &= ~0x33; - /* fall through */ + fallthrough; case FB_BLANK_NORMAL: ctrl |= 0x400; break; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index dd0ccf35f7b79..d0e4ee84ee15a 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1310,7 +1310,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, case FBIOGET_CON2FBMAP: case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); - /* fall through */ + fallthrough; case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); break; diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c index 67ebfe5c9f1d8..a547c21c7e928 100644 --- a/drivers/video/fbdev/fsl-diu-fb.c +++ b/drivers/video/fbdev/fsl-diu-fb.c @@ -1287,7 +1287,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, dev_warn(info->dev, "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n", MFB_SET_PIXFMT_OLD); - /* fall through */ + fallthrough; case MFB_SET_PIXFMT: if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) return -EFAULT; @@ -1297,7 +1297,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, dev_warn(info->dev, "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n", MFB_GET_PIXFMT_OLD); - /* fall through */ + fallthrough; case MFB_GET_PIXFMT: pix_fmt = ad->pix_fmt; if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c index 13ded3a107084..e5475ae1e1587 100644 --- a/drivers/video/fbdev/gxt4500.c +++ b/drivers/video/fbdev/gxt4500.c @@ -534,7 +534,7 @@ static int gxt4500_setcolreg(unsigned int reg, unsigned int red, break; case DFA_PIX_32BIT: val |= (reg << 24); - /* fall through */ + fallthrough; case DFA_PIX_24BIT: val |= (reg << 16) | (reg << 8); break; diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index c65ec7386e87b..e6f35f8feefcb 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -430,7 +430,7 @@ static int i740fb_decode_var(const struct fb_var_screeninfo *var, break; case 9 ... 15: bpp = 15; - /* fall through */ + fallthrough; case 16: if ((1000000 / var->pixclock) > DACSPEED16) { dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index 5cd0f5f6a4ae7..4501e848a36f2 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -141,7 +141,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ out_le32(par->cmap_adr + 0x58, in_le32(par->cmap_adr + 0x58) & ~0x20); - /* fall through */ + fallthrough; case cmap_r128: /* Set palette index & data */ out_8(par->cmap_adr + 0xb0, regno); @@ -211,7 +211,7 @@ static int offb_blank(int blank, struct fb_info *info) /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ out_le32(par->cmap_adr + 0x58, in_le32(par->cmap_adr + 0x58) & ~0x20); - /* fall through */ + fallthrough; case cmap_r128: /* Set palette index & data */ out_8(par->cmap_adr + 0xb0, i); diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c index fa73acfc1371d..7317c9aad6772 100644 --- a/drivers/video/fbdev/omap/lcdc.c +++ b/drivers/video/fbdev/omap/lcdc.c @@ -328,13 +328,13 @@ static int omap_lcdc_setup_plane(int plane, int channel_out, lcdc.bpp = 12; break; } - /* fallthrough */ + fallthrough; case OMAPFB_COLOR_YUV422: if (lcdc.ext_mode) { lcdc.bpp = 16; break; } - /* fallthrough */ + fallthrough; default: /* FIXME: other BPPs. * bpp1: code 0, size 256 diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 0cbcc74fa9439..3d090d2d9ed9e 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -253,7 +253,7 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, if (fbdev->ctrl->setcolreg) r = fbdev->ctrl->setcolreg(regno, red, green, blue, transp, update_hw_pal); - /* Fallthrough */ + fallthrough; case OMAPFB_COLOR_RGB565: case OMAPFB_COLOR_RGB444: if (r != 0) @@ -443,7 +443,7 @@ static int set_color_mode(struct omapfb_plane_struct *plane, return 0; case 12: var->bits_per_pixel = 16; - /* fall through */ + fallthrough; case 16: if (plane->fbdev->panel->bpp == 12) plane->color_mode = OMAPFB_COLOR_RGB444; @@ -1531,27 +1531,27 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state) case OMAPFB_ACTIVE: for (i = 0; i < fbdev->mem_desc.region_cnt; i++) unregister_framebuffer(fbdev->fb_info[i]); - /* fall through */ + fallthrough; case 7: omapfb_unregister_sysfs(fbdev); - /* fall through */ + fallthrough; case 6: if (fbdev->panel->disable) fbdev->panel->disable(fbdev->panel); - /* fall through */ + fallthrough; case 5: omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); - /* fall through */ + fallthrough; case 4: planes_cleanup(fbdev); - /* fall through */ + fallthrough; case 3: ctrl_cleanup(fbdev); - /* fall through */ + fallthrough; case 2: if (fbdev->panel->cleanup) fbdev->panel->cleanup(fbdev->panel); - /* fall through */ + fallthrough; case 1: dev_set_drvdata(fbdev->dev, NULL); kfree(fbdev); @@ -1854,7 +1854,7 @@ static int __init omapfb_setup(char *options) case 'm': case 'M': vram *= 1024; - /* Fall through */ + fallthrough; case 'k': case 'K': vram *= 1024; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c index 3920a0db0390c..b2d6e6df21615 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c @@ -1861,7 +1861,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY) width = width >> 1; - /* fall through */ + fallthrough; case OMAP_DSS_ROT_90: case OMAP_DSS_ROT_270: *offset1 = 0; @@ -1884,7 +1884,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY) width = width >> 1; - /* fall through */ + fallthrough; case OMAP_DSS_ROT_90 + 4: case OMAP_DSS_ROT_270 + 4: *offset1 = 0; diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c index f40be68d5aac9..ea8c88aa44771 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c @@ -760,7 +760,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) r = -ENODEV; break; } - /* FALLTHROUGH */ + fallthrough; case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c index 836e7b1639ce5..a3decc7fadde3 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c @@ -882,7 +882,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, / (var->bits_per_pixel >> 2); break; } - /* fall through */ + fallthrough; default: screen_width = fix->line_length / (var->bits_per_pixel >> 3); break; diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c index c7c98d8e23592..0642555289e06 100644 --- a/drivers/video/fbdev/pm2fb.c +++ b/drivers/video/fbdev/pm2fb.c @@ -233,10 +233,10 @@ static u32 to3264(u32 timing, int bpp, int is64) switch (bpp) { case 24: timing *= 3; - /* fall through */ + fallthrough; case 8: timing >>= 1; - /* fall through */ + fallthrough; case 16: timing >>= 1; case 32: diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index a53d24fb71834..f1551e00eb12f 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -1614,7 +1614,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) */ if (old_state != C_DISABLE_PM) break; - /* fall through */ + fallthrough; case C_ENABLE: /* diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c index 9dc925054930e..ba316bd56efd7 100644 --- a/drivers/video/fbdev/s3c-fb.c +++ b/drivers/video/fbdev/s3c-fb.c @@ -284,7 +284,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /* 666 with one bit alpha/transparency */ var->transp.offset = 18; var->transp.length = 1; - /* fall through */ + fallthrough; case 18: var->bits_per_pixel = 32; @@ -312,7 +312,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, case 25: var->transp.length = var->bits_per_pixel - 24; var->transp.offset = 24; - /* fall through */ + fallthrough; case 24: /* our 24bpp is unpacked, so 32bpp */ var->bits_per_pixel = 32; @@ -809,7 +809,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) case FB_BLANK_POWERDOWN: wincon &= ~WINCONx_ENWIN; sfb->enabled &= ~(1 << index); - /* fall through - to FB_BLANK_NORMAL */ + fallthrough; /* to FB_BLANK_NORMAL */ case FB_BLANK_NORMAL: /* disable the DMA and display 0x0 (black) */ diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index bda6cc313c8b9..e31cf63b0a62d 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -935,7 +935,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) */ if (old_state != C_DISABLE_PM) break; - /* fall through */ + fallthrough; case C_ENABLE: /* diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 3fd87aeb6c798..661398e40ff43 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -1859,8 +1859,7 @@ static int savage_init_hw(struct savagefb_par *par) vga_out8(0x3d4, 0x68, par); /* memory control 1 */ if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6)) RamSavage4[1] = 8; - - /*FALLTHROUGH*/ + fallthrough; case S3_SAVAGE2000: videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024; diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index 8a27d12e6ea87..c1043420dbd3e 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -1594,7 +1594,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: info->fix.ypanstep = 2; - /* Fall through */ + fallthrough; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: info->fix.xpanstep = 2; @@ -2085,7 +2085,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: info->fix.ypanstep = 2; - /* Fall through */ + fallthrough; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: info->fix.xpanstep = 2; diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index 3dd1b1d76e983..6a52eba645596 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1005,7 +1005,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) case FB_BLANK_POWERDOWN: ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE; sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0); - /* fall through */ + fallthrough; case FB_BLANK_NORMAL: ctrl |= SM501_DC_CRT_CONTROL_BLANK; diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c index f73e26c18c090..f056d80f6359f 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -523,7 +523,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) case 32: var->transp.offset = 24; var->transp.length = 8; - /* fall through */ + fallthrough; case 24: var->red.offset = 16; var->green.offset = 8; diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 00307b8693bf5..5ec51445bee88 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -677,7 +677,7 @@ static void xenfb_backend_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state. */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; -- GitLab From 522ec6e0eed0ab0678e7d5b5bf00487dfe83f7ce Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Thu, 30 Jul 2020 18:04:33 -0400 Subject: [PATCH 0191/1494] drm/amdkfd: Replace bitmask with event idx in SMI event msg Event bitmask is a 64-bit mask with only 1 bit set. Sending this event bitmask in KFD SMI event message is both wasteful of memory and potentially limiting to only 64 events. Instead send event index in SMI event message. Please note this change does not break the ABI for the two event types defined so far. The new index is identical to the mask used before. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Suggested-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 24 +++++++++++---------- include/uapi/linux/kfd_ioctl.h | 10 ++++++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 86c2c3e97944b..4d4b6e3ab697b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -149,7 +149,7 @@ static int kfd_smi_ev_release(struct inode *inode, struct file *filep) return 0; } -static void add_event_to_kfifo(struct kfd_dev *dev, unsigned long long smi_event, +static void add_event_to_kfifo(struct kfd_dev *dev, unsigned int smi_event, char *event_msg, int len) { struct kfd_smi_client *client; @@ -157,14 +157,15 @@ static void add_event_to_kfifo(struct kfd_dev *dev, unsigned long long smi_event rcu_read_lock(); list_for_each_entry_rcu(client, &dev->smi_clients, list) { - if (!(READ_ONCE(client->events) & smi_event)) + if (!(READ_ONCE(client->events) & + KFD_SMI_EVENT_MASK_FROM_INDEX(smi_event))) continue; spin_lock(&client->lock); if (kfifo_avail(&client->fifo) >= len) { kfifo_in(&client->fifo, event_msg, len); wake_up_all(&client->wait_queue); } else { - pr_debug("smi_event(EventID: %llu): no space left\n", + pr_debug("smi_event(EventID: %u): no space left\n", smi_event); } spin_unlock(&client->lock); @@ -180,21 +181,21 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, /* * ThermalThrottle msg = throttle_bitmask(8): * thermal_interrupt_count(16): - * 16 bytes event + 1 byte space + 8 byte throttle_bitmask + + * 1 byte event + 1 byte space + 8 byte throttle_bitmask + * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n + - * 1 byte \0 = 44 + * 1 byte \0 = 29 */ - char fifo_in[44]; + char fifo_in[29]; int len; if (list_empty(&dev->smi_clients)) return; - len = snprintf(fifo_in, 44, "%x %x:%llx\n", + len = snprintf(fifo_in, 29, "%x %x:%llx\n", KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, atomic64_read(&adev->smu.throttle_int_counter)); - add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); + add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); } void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) @@ -202,9 +203,10 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; struct amdgpu_task_info task_info; /* VmFault msg = (hex)uint32_pid(8) + :(1) + task name(16) = 25 */ - /* 16 bytes event + 1 byte space + 25 bytes msg + 1 byte \n = 43 + /* 1 byte event + 1 byte space + 25 bytes msg + 1 byte \n + + * 1 byte \0 = 29 */ - char fifo_in[43]; + char fifo_in[29]; int len; if (list_empty(&dev->smi_clients)) @@ -216,7 +218,7 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) if (!task_info.pid) return; - len = snprintf(fifo_in, 43, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, + len = snprintf(fifo_in, 29, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, task_info.pid, task_info.task_name); add_event_to_kfifo(dev, KFD_SMI_EVENT_VMFAULT, fifo_in, len); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index df6c7a43aadcf..cb1f963a84e0a 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -449,9 +449,13 @@ struct kfd_ioctl_import_dmabuf_args { /* * KFD SMI(System Management Interface) events */ -/* Event type (defined by bitmask) */ -#define KFD_SMI_EVENT_VMFAULT 0x0000000000000001 -#define KFD_SMI_EVENT_THERMAL_THROTTLE 0x0000000000000002 +enum kfd_smi_event { + KFD_SMI_EVENT_NONE = 0, /* not used */ + KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ + KFD_SMI_EVENT_THERMAL_THROTTLE = 2, +}; + +#define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) struct kfd_ioctl_smi_events_args { __u32 gpuid; /* to KFD */ -- GitLab From acc0204cdb8e60d2e57053ed766d8280eb01118b Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Tue, 21 Jul 2020 18:02:00 +0800 Subject: [PATCH 0192/1494] drm/amdgpu: add bad page count threshold in module parameter(v3) bad_page_threshold could be configured to enable/disable the associated bad page retirement feature in RAS. When it's -1, ras will use typical bad page failure value to handle bad page retirement. When it's 0, disable bad page retirement, and no bad page will be recorded and saved. For other valid value, driver will use this manual value as the threshold value of totoal bad pages. v2: correct documentation of this parameter. v3: remove confused statement in documentation. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 58e39429395fc..e2eed5c630fcd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -178,6 +178,7 @@ extern uint amdgpu_dm_abm_level; extern struct amdgpu_mgpu_info mgpu_info; extern int amdgpu_ras_enable; extern uint amdgpu_ras_mask; +extern int amdgpu_bad_page_threshold; extern int amdgpu_async_gfx_ring; extern int amdgpu_mcbp; extern int amdgpu_discovery; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 26127c7d2f32d..dc47549641e26 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -156,6 +156,7 @@ struct amdgpu_mgpu_info mgpu_info = { }; int amdgpu_ras_enable = -1; uint amdgpu_ras_mask = 0xffffffff; +int amdgpu_bad_page_threshold = -1; /** * DOC: vramlimit (int) @@ -765,6 +766,16 @@ module_param_named(tmz, amdgpu_tmz, int, 0444); MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)"); module_param_named(reset_method, amdgpu_reset_method, int, 0444); +/** + * DOC: bad_page_threshold (int) + * Bad page threshold is to specify the threshold value of faulty pages + * detected by RAS ECC, that may result in GPU entering bad status if total + * faulty pages by ECC exceed threshold value and leave it for user's further + * check. + */ +MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); +module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); + static const struct pci_device_id pciidlist[] = { #ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, -- GitLab From c84d46707ebbfc303268e27d5aeb8bb4e6d5b1ff Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Wed, 22 Jul 2020 10:00:27 +0800 Subject: [PATCH 0193/1494] drm/amdgpu: validate bad page threshold in ras(v3) Bad page threshold value should be valid in the range between -1 and max records length of eeprom. It could determine when saved bad pages exceed threshold value, and proceed corresponding actions. v2: When using the default typical value, it should be min value between typical value and eeprom max records length. v3: drop the case of setting bad_page_cnt_threshold to be 0xFFFFFFFF, as it confuses user. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 48 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 ++ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 5 ++ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 2 + 4 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 5680f7eafcb18..6660094a10631 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -69,6 +69,9 @@ const char *ras_block_string[] = { /* inject address is 52 bits */ #define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) +/* typical ECC bad page rate(1 bad page per 100MB VRAM) */ +#define RAS_BAD_PAGE_RATE (100 * 1024 * 1024ULL) + enum amdgpu_ras_retire_page_reservation { AMDGPU_RAS_RETIRE_PAGE_RESERVED, AMDGPU_RAS_RETIRE_PAGE_PENDING, @@ -1699,6 +1702,47 @@ static bool amdgpu_ras_check_bad_page(struct amdgpu_device *adev, return ret; } +static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, + uint32_t max_length) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + int tmp_threshold = amdgpu_bad_page_threshold; + u64 val; + + /* + * Justification of value bad_page_cnt_threshold in ras structure + * + * Generally, -1 <= amdgpu_bad_page_threshold <= max record length + * in eeprom, and introduce two scenarios accordingly. + * + * Bad page retirement enablement: + * - If amdgpu_bad_page_threshold = -1, + * bad_page_cnt_threshold = typical value by formula. + * + * - When the value from user is 0 < amdgpu_bad_page_threshold < + * max record length in eeprom, use it directly. + * + * Bad page retirement disablement: + * - If amdgpu_bad_page_threshold = 0, bad page retirement + * functionality is disabled, and bad_page_cnt_threshold will + * take no effect. + */ + + if (tmp_threshold < -1) + tmp_threshold = -1; + else if (tmp_threshold > max_length) + tmp_threshold = max_length; + + if (tmp_threshold == -1) { + val = adev->gmc.mc_vram_size; + do_div(val, RAS_BAD_PAGE_RATE); + con->bad_page_cnt_threshold = min(lower_32_bits(val), + max_length); + } else { + con->bad_page_cnt_threshold = tmp_threshold; + } +} + /* called in gpu recovery/init */ int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev) { @@ -1776,6 +1820,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_err_handler_data **data; + uint32_t max_eeprom_records_len = 0; int ret; if (con) @@ -1794,6 +1839,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) atomic_set(&con->in_recovery, 0); con->adev = adev; + max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); + amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); + ret = amdgpu_ras_eeprom_init(&con->eeprom_control); if (ret) goto free; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index b2667342cf674..4672649a9293c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -336,6 +336,9 @@ struct amdgpu_ras { struct amdgpu_ras_eeprom_control eeprom_control; bool error_query_ready; + + /* bad page count threshold */ + uint32_t bad_page_cnt_threshold; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index c0096097bbcf4..a2c982b1eac62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -499,6 +499,11 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, return ret == num ? 0 : -EIO; } +inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void) +{ + return EEPROM_MAX_RECORD_NUM; +} + /* Used for testing if bugs encountered */ #if 0 void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 9e7d640920fb1..e285e8cafd489 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -84,6 +84,8 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, bool write, int num); +inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void); + void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control); #endif // _AMDGPU_RAS_EEPROM_H -- GitLab From 1d6a9d122d2c7817ad1bae0e59c8a29450c2b14d Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 23 Jul 2020 15:35:53 +0800 Subject: [PATCH 0194/1494] drm/amdgpu: add bad gpu tag definition This tag will be hired for bad gpu detection in eeprom's access. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index a2c982b1eac62..35c0c849d49b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -46,6 +46,9 @@ #define EEPROM_TABLE_HDR_VAL 0x414d4452 #define EEPROM_TABLE_VER 0x00010000 +/* Bad GPU tag ‘BADG’ */ +#define EEPROM_TABLE_HDR_BAD 0x42414447 + /* Assume 2 Mbit size */ #define EEPROM_SIZE_BYTES 256000 #define EEPROM_PAGE__SIZE_BYTES 256 -- GitLab From b82e65a93510465cb4c203c938245f137a4e95dc Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 23 Jul 2020 15:42:19 +0800 Subject: [PATCH 0195/1494] drm/amdgpu: break driver init process when it's bad GPU(v5) When retrieving bad gpu tag from eeprom, GPU init should fail as the GPU needs to be retired for further check. v2: Fix spelling typo, correct the condition to detect bad gpu tag and refine error message. v3: Refine function argument name. v4: Fix missing check of returning value of i2c initialization error case. v5: Use dev_err to print PCI information in dmesg instead of DRM_ERROR. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 +++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 18 ++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 +++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 3 ++- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 40caa7437ce24..905c5ab486a1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2055,13 +2055,19 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) * it should be called after amdgpu_device_ip_hw_init_phase2 since * for some ASICs the RAS EEPROM code relies on SMU fully functioning * for I2C communication which only true at this point. - * recovery_init may fail, but it can free all resources allocated by - * itself and its failure should not stop amdgpu init process. + * + * amdgpu_ras_recovery_init may fail, but the upper only cares the + * failure from bad gpu situation and stop amdgpu init process + * accordingly. For other failed cases, it will still release all + * the resource and print error message, rather than returning one + * negative value to upper level. * * Note: theoretically, this should be called before all vram allocations * to protect retired page from abusing */ - amdgpu_ras_recovery_init(adev); + r = amdgpu_ras_recovery_init(adev); + if (r) + goto init_failed; if (adev->gmc.xgmi.num_physical_nodes > 1) amdgpu_xgmi_add_device(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 6660094a10631..1a1652ea76b01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1821,6 +1821,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_err_handler_data **data; uint32_t max_eeprom_records_len = 0; + bool exc_err_limit = false; int ret; if (con) @@ -1842,8 +1843,12 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); - ret = amdgpu_ras_eeprom_init(&con->eeprom_control); - if (ret) + ret = amdgpu_ras_eeprom_init(&con->eeprom_control, &exc_err_limit); + /* + * This calling fails when exc_err_limit is true or + * ret != 0. + */ + if (exc_err_limit || ret) goto free; if (con->eeprom_control.num_recs) { @@ -1867,6 +1872,15 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) out: dev_warn(adev->dev, "Failed to initialize ras recovery!\n"); + /* + * Except error threshold exceeding case, other failure cases in this + * function would not fail amdgpu driver init. + */ + if (!exc_err_limit) + ret = 0; + else + ret = -EINVAL; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 35c0c849d49b6..da8b35a5b41ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -241,7 +241,8 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) } -int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) +int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit) { int ret = 0; struct amdgpu_device *adev = to_amdgpu_device(control); @@ -254,6 +255,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) .buf = buff, }; + *exceed_err_limit = false; + /* Verify i2c adapter is initialized */ if (!adev->pm.smu_i2c.algo) return -ENOENT; @@ -282,6 +285,11 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", control->num_recs); + } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && + (amdgpu_bad_page_threshold != 0)) { + *exceed_err_limit = true; + dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " + "disabling the GPU.\n"); } else { DRM_INFO("Creating new EEPROM table"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index e285e8cafd489..9839b4ea5e189 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -76,7 +76,8 @@ struct eeprom_table_record { unsigned char mcumc_id; }__attribute__((__packed__)); -int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control); +int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit); int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, -- GitLab From 35cd2cdadbccf08e9b4d5a8fca4914dc37ab48e0 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 23 Jul 2020 15:50:42 +0800 Subject: [PATCH 0196/1494] drm/amdgpu: skip bad page reservation once issuing from eeprom write Once the ras recovery is issued from eeprom write itself, bad page reservation should be ignored, otherwise, recursive calling of writting to eeprom would happen. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 14 +++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 1a1652ea76b01..d081de232c666 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -62,8 +62,6 @@ const char *ras_block_string[] = { #define ras_err_str(i) (ras_error_string[ffs(i)]) #define ras_block_str(i) (ras_block_string[i]) -#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS 1 -#define AMDGPU_RAS_FLAG_INIT_NEED_RESET 2 #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) /* inject address is 52 bits */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 4672649a9293c..cf9f60202334d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -31,6 +31,10 @@ #include "ta_ras_if.h" #include "amdgpu_ras_eeprom.h" +#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0) +#define AMDGPU_RAS_FLAG_INIT_NEED_RESET (0x1 << 1) +#define AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV (0x1 << 2) + enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__UMC = 0, AMDGPU_RAS_BLOCK__SDMA, @@ -503,10 +507,14 @@ static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - /* save bad page to eeprom before gpu reset, - * i2c may be unstable in gpu reset + /* + * Save bad page to eeprom before gpu reset, i2c may be unstable + * in gpu reset. + * + * Also, exclude the case when ras recovery issuer is + * eeprom page write itself. */ - if (in_task()) + if (!(ras->flags & AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV) && in_task()) amdgpu_ras_reserve_bad_pages(adev); if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0) -- GitLab From 9c06f91ff2349da67651cddf88507aa967b58b08 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 23 Jul 2020 16:05:00 +0800 Subject: [PATCH 0197/1494] drm/amdgpu: schedule ras recovery when reaching bad page threshold(v2) Once the bad page saved to eeprom reaches the configured threshold, ras recovery will be issued to notify user. v2: Fix spelling typo. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index da8b35a5b41ca..461dfd22bc1c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -394,8 +394,10 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, int i, ret = 0; struct i2c_msg *msgs, *msg; unsigned char *buffs, *buff; + bool sched_ras_recovery = false; struct eeprom_table_record *record; struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); if (adev->asic_type != CHIP_VEGA20 && adev->asic_type != CHIP_ARCTURUS) return 0; @@ -413,11 +415,30 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, goto free_buff; } + /* + * If saved bad pages number exceeds the bad page threshold for + * the whole VRAM, update table header to mark the BAD GPU tag + * and schedule one ras recovery after eeprom write is done, + * this can avoid the missing for latest records. + * + * This new header will be picked up and checked in the bootup + * by ras recovery, which may break bootup process to notify + * user this GPU is in bad state and to retire such GPU for + * further check. + */ + if (write && (amdgpu_bad_page_threshold != 0) && + ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) { + dev_warn(adev->dev, + "Saved bad pages(%d) reaches threshold value(%d).\n", + control->num_recs + num, ras->bad_page_cnt_threshold); + control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD; + sched_ras_recovery = true; + } + /* In case of overflow just start from beginning to not lose newest records */ if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES)) control->next_addr = EEPROM_RECORD_START; - /* * TODO Currently makes EEPROM writes for each record, this creates * internal fragmentation. Optimized the code to do full page write of @@ -493,6 +514,20 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, __update_tbl_checksum(control, records, num, old_hdr_byte_sum); __update_table_header(control, buffs); + + if (sched_ras_recovery) { + /* + * Before scheduling ras recovery, assert the related + * flag first, which shall bypass common bad page + * reservation execution in amdgpu_ras_reset_gpu. + */ + amdgpu_ras_get_context(adev)->flags |= + AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV; + + dev_warn(adev->dev, "Conduct ras recovery due to bad " + "page threshold reached.\n"); + amdgpu_ras_reset_gpu(adev); + } } else if (!__validate_tbl_checksum(control, records, num)) { DRM_WARN("EEPROM Table checksum mismatch!"); /* TODO Uncomment when EEPROM read/write is relliable */ -- GitLab From e8fbaf03429d085b05e66b153a8363b746c94b43 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 23 Jul 2020 16:20:02 +0800 Subject: [PATCH 0198/1494] drm/amdgpu: break GPU recovery once it's in bad state(v4) When GPU executes recovery and retriving bad GPU tag from external eerpom device, the recovery will be broken and error message is printed as well for user's awareness. v2: Refine warning message in threshold reaching case, and fix spelling typo. v3: Fix explicit calling of bad gpu. v4: Rename function names. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 ++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 + .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 40 +++++++++++++++++++ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 4 ++ 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 905c5ab486a1d..d01d7969d47b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4125,8 +4125,23 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, amdgpu_fbdev_set_suspend(tmp_adev, 0); - /* must succeed. */ - amdgpu_ras_resume(tmp_adev); + /* + * The GPU enters bad state once faulty pages + * by ECC has reached the threshold, and ras + * recovery is scheduled next. So add one check + * here to break recovery if it indeed exceeds + * bad page threshold, and remind user to + * retire this GPU or setting one bigger + * bad_page_threshold value to fix this once + * probing driver again. + */ + if (!amdgpu_ras_check_err_threshold(tmp_adev)) { + /* must succeed. */ + amdgpu_ras_resume(tmp_adev); + } else { + r = -EINVAL; + goto out; + } /* Update PSP FW topology after reset */ if (hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1) @@ -4134,7 +4149,6 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, } } - out: if (!r) { amdgpu_irq_gpu_reset_resume_helper(tmp_adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d081de232c666..ab65dfd719272 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2205,3 +2205,19 @@ bool amdgpu_ras_need_emergency_restart(struct amdgpu_device *adev) return false; } + +bool amdgpu_ras_check_err_threshold(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + bool exc_err_limit = false; + + if (con && (amdgpu_bad_page_threshold != 0)) + amdgpu_ras_eeprom_check_err_threshold(&con->eeprom_control, + &exc_err_limit); + + /* + * We are only interested in variable exc_err_limit, + * as it says if GPU is in bad state or not. + */ + return exc_err_limit; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index cf9f60202334d..70a6fca736178 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -497,6 +497,8 @@ void amdgpu_ras_suspend(struct amdgpu_device *adev); unsigned long amdgpu_ras_query_error_count(struct amdgpu_device *adev, bool is_ce); +bool amdgpu_ras_check_err_threshold(struct amdgpu_device *adev); + /* error handling functions */ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, struct eeprom_table_record *bps, int pages); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 461dfd22bc1c7..7848a426c95b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -386,6 +386,46 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address) return curr_address; } +int amdgpu_ras_eeprom_check_err_threshold( + struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + unsigned char buff[EEPROM_ADDRESS_SIZE + + EEPROM_TABLE_HEADER_SIZE] = { 0 }; + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + struct i2c_msg msg = { + .addr = control->i2c_address, + .flags = I2C_M_RD, + .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, + .buf = buff, + }; + int ret; + + *exceed_err_limit = false; + + /* read EEPROM table header */ + mutex_lock(&control->tbl_mutex); + ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); + if (ret < 1) { + dev_err(adev->dev, "Failed to read EEPROM table header.\n"); + goto err; + } + + __decode_table_header_from_buff(hdr, &buff[2]); + + if (hdr->header == EEPROM_TABLE_HDR_BAD) { + dev_warn(adev->dev, "This GPU is in BAD status."); + dev_warn(adev->dev, "Please retire it or setting one bigger " + "threshold value when reloading driver.\n"); + *exceed_err_limit = true; + } + +err: + mutex_unlock(&control->tbl_mutex); + return 0; +} + int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records, bool write, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 9839b4ea5e189..c7a5e5c7c61eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -80,6 +80,10 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, bool *exceed_err_limit); int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); +int amdgpu_ras_eeprom_check_err_threshold( + struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit); + int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records, bool write, -- GitLab From bf0b91b78f002faa1be1902a75eeb0797f9fbcf3 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Wed, 22 Jul 2020 10:37:01 +0800 Subject: [PATCH 0199/1494] drm/amdgpu: restore ras flags when user resets eeprom(v2) RAS flags needs to be cleaned as well when user requires one clean eeprom. v2: RAS flags shall be restored after eeprom reset succeeds. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index ab65dfd719272..19ac2e6ad60e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -368,12 +368,19 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user * static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { - struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; + struct amdgpu_device *adev = + (struct amdgpu_device *)file_inode(f)->i_private; int ret; - ret = amdgpu_ras_eeprom_reset_table(&adev->psp.ras.ras->eeprom_control); + ret = amdgpu_ras_eeprom_reset_table( + &(amdgpu_ras_get_context(adev)->eeprom_control)); - return ret == 1 ? size : -EIO; + if (ret == 1) { + amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS; + return size; + } else { + return -EIO; + } } static const struct file_operations amdgpu_ras_debugfs_ctrl_ops = { -- GitLab From eb0c3cd48f5f27abf3ba92bd142b71ef76229706 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Fri, 31 Jul 2020 14:39:57 +0800 Subject: [PATCH 0200/1494] drm/amdgpu: add one definition for RAS's sysfs/debugfs name(v2) Add one definition for the RAS module's FS name. It's used in both debugfs and sysfs cases. v2: Use static variable instead of macro definition. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 19ac2e6ad60e1..08869e4a5374c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -34,6 +34,8 @@ #include "amdgpu_xgmi.h" #include "ivsrcid/nbio/irqsrcs_nbif_7_4.h" +static const char *RAS_FS_NAME = "ras"; + const char *ras_error_string[] = { "none", "parity", @@ -1037,7 +1039,7 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) NULL }; struct attribute_group group = { - .name = "ras", + .name = RAS_FS_NAME, .attrs = attrs, .bin_attrs = bin_attrs, }; @@ -1078,7 +1080,7 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) NULL }; struct attribute_group group = { - .name = "ras", + .name = RAS_FS_NAME, .attrs = attrs, .bin_attrs = bin_attrs, }; @@ -1113,7 +1115,7 @@ int amdgpu_ras_sysfs_create(struct amdgpu_device *adev, if (sysfs_add_file_to_group(&adev->dev->kobj, &obj->sysfs_attr.attr, - "ras")) { + RAS_FS_NAME)) { put_obj(obj); return -EINVAL; } @@ -1133,7 +1135,7 @@ int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev, sysfs_remove_file_from_group(&adev->dev->kobj, &obj->sysfs_attr.attr, - "ras"); + RAS_FS_NAME); obj->attr_inuse = 0; put_obj(obj); @@ -1179,7 +1181,7 @@ static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct drm_minor *minor = adev->ddev->primary; - con->dir = debugfs_create_dir("ras", minor->debugfs_root); + con->dir = debugfs_create_dir(RAS_FS_NAME, minor->debugfs_root); debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir, adev, &amdgpu_ras_debugfs_ctrl_ops); debugfs_create_file("ras_eeprom_reset", S_IWUGO | S_IRUGO, con->dir, -- GitLab From f848159b570ecdcd157ad5b52eb58e5cb3a075a7 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Fri, 31 Jul 2020 15:06:32 +0800 Subject: [PATCH 0201/1494] drm/amdgpu: decouple sysfs creating of bad page node Bad page information should not be exposed by sysfs when bad page retirement is disabled, so decouple it from ras sysfs group creating, and add one guard before creating. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 63 ++++++++++++++++--------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 08869e4a5374c..3949470edbb01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1027,6 +1027,33 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev, return scnprintf(buf, PAGE_SIZE, "feature mask: 0x%x\n", con->features); } +static void amdgpu_ras_sysfs_add_bad_page_node(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct attribute_group group; + struct bin_attribute *bin_attrs[] = { + &con->badpages_attr, + NULL, + }; + + con->badpages_attr = (struct bin_attribute) { + .attr = { + .name = "gpu_vram_bad_pages", + .mode = S_IRUGO, + }, + .size = 0, + .private = NULL, + .read = amdgpu_ras_sysfs_badpages_read, + }; + + group.name = RAS_FS_NAME; + group.bin_attrs = bin_attrs; + + sysfs_bin_attr_init(bin_attrs[0]); + + sysfs_update_group(&adev->dev->kobj, &group); +} + static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -1034,14 +1061,9 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) &con->features_attr.attr, NULL }; - struct bin_attribute *bin_attrs[] = { - &con->badpages_attr, - NULL - }; struct attribute_group group = { .name = RAS_FS_NAME, .attrs = attrs, - .bin_attrs = bin_attrs, }; con->features_attr = (struct device_attribute) { @@ -1052,22 +1074,20 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) .show = amdgpu_ras_sysfs_features_read, }; - con->badpages_attr = (struct bin_attribute) { - .attr = { - .name = "gpu_vram_bad_pages", - .mode = S_IRUGO, - }, - .size = 0, - .private = NULL, - .read = amdgpu_ras_sysfs_badpages_read, - }; - sysfs_attr_init(attrs[0]); - sysfs_bin_attr_init(bin_attrs[0]); return sysfs_create_group(&adev->dev->kobj, &group); } +static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + + sysfs_remove_file_from_group(&adev->dev->kobj, + &con->badpages_attr.attr, + RAS_FS_NAME); +} + static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -1075,14 +1095,9 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) &con->features_attr.attr, NULL }; - struct bin_attribute *bin_attrs[] = { - &con->badpages_attr, - NULL - }; struct attribute_group group = { .name = RAS_FS_NAME, .attrs = attrs, - .bin_attrs = bin_attrs, }; sysfs_remove_group(&adev->dev->kobj, &group); @@ -1151,6 +1166,9 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev) amdgpu_ras_sysfs_remove(adev, &obj->head); } + if (amdgpu_bad_page_threshold != 0) + amdgpu_ras_sysfs_remove_bad_page_node(adev); + amdgpu_ras_sysfs_remove_feature_node(adev); return 0; @@ -1278,6 +1296,9 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev) { amdgpu_ras_sysfs_create_feature_node(adev); + if (amdgpu_bad_page_threshold != 0) + amdgpu_ras_sysfs_add_bad_page_node(adev); + return 0; } -- GitLab From a219ecbb83859940bd1959180bd555f28f2043a7 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Mon, 27 Jul 2020 14:56:27 +0800 Subject: [PATCH 0202/1494] drm/amdgpu: disable page reservation when amdgpu_bad_page_threshold = 0 When amdgpu_bad_page_threshold = 0, bad page reservation stuffs are skipped in either UMC ECC irq or page retirement calling of sync flood isr. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 3949470edbb01..89cb0ae9da9d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1676,7 +1676,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) int ret = 0; /* no bad page record, skip eeprom access */ - if (!control->num_recs) + if (!control->num_recs || (amdgpu_bad_page_threshold == 0)) return ret; bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL); @@ -1780,7 +1780,8 @@ int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev) struct amdgpu_bo *bo = NULL; int i, ret = 0; - if (!con || !con->eh_data) + /* Not reserve bad page when amdgpu_bad_page_threshold == 0. */ + if (!con || !con->eh_data || (amdgpu_bad_page_threshold == 0)) return 0; mutex_lock(&con->recovery_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index af1b1ccf613c9..262baf0f61ea0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -125,8 +125,9 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, "detected in UMC block\n", err_data->ue_count); - if (err_data->err_addr_cnt && - amdgpu_ras_add_bad_pages(adev, err_data->err_addr, + if ((amdgpu_bad_page_threshold != 0) && + err_data->err_addr_cnt && + amdgpu_ras_add_bad_pages(adev, err_data->err_addr, err_data->err_addr_cnt)) dev_warn(adev->dev, "Failed to add ras bad page!\n"); -- GitLab From 9b856defbe355f886f99777e667506841bd267a8 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Mon, 27 Jul 2020 15:51:05 +0800 Subject: [PATCH 0203/1494] drm/amdgpu: update eeprom once specifying one bigger threshold(v3) During driver's probe, when it hits bad gpu tag in eeprom i2c init calling(the tag was set when reported bad page reaches bad page threshold in last driver's working loop), there are some strategys to deal with the cases: 1. when the module parameter amdgpu_bad_page_threshold = 0, that means page retirement feature is disabled, so just resetting the eeprom is fine. 2. When amdgpu_bad_page_threshold is not 0, and moreover, user sets one bigger valid data in order to make current boot up succeeds, correct eeprom header tag and do not break booting. 3. For other cases, driver's probe will be broken. v2: Just update eeprom header tag instead of resetting the whole table header when user sets one bigger threshold data. v3: Use dev_info/dev_err to print PCI device information, which helps in mGPU case. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 7848a426c95b6..e5e3ed113d63c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -216,6 +216,24 @@ static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, return true; } +static int amdgpu_ras_eeprom_correct_header_tag( + struct amdgpu_ras_eeprom_control *control, + uint32_t header) +{ + unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE]; + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + int ret = 0; + + memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE); + + mutex_lock(&control->tbl_mutex); + hdr->header = header; + ret = __update_table_header(control, buff); + mutex_unlock(&control->tbl_mutex); + + return ret; +} + int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) { unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; @@ -248,6 +266,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, struct amdgpu_device *adev = to_amdgpu_device(control); unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); struct i2c_msg msg = { .addr = 0, .flags = I2C_M_RD, @@ -287,9 +306,16 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && (amdgpu_bad_page_threshold != 0)) { - *exceed_err_limit = true; - dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " + if (ras->bad_page_cnt_threshold > control->num_recs) { + dev_info(adev->dev, "Using one valid bigger bad page " + "threshold and correcting eeprom header tag.\n"); + ret = amdgpu_ras_eeprom_correct_header_tag(control, + EEPROM_TABLE_HDR_VAL); + } else { + *exceed_err_limit = true; + dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " "disabling the GPU.\n"); + } } else { DRM_INFO("Creating new EEPROM table"); -- GitLab From a300de40f66b87fa90703c94ffb22917f98eb902 Mon Sep 17 00:00:00 2001 From: Monk Liu <Monk.Liu@amd.com> Date: Mon, 27 Jul 2020 15:20:12 +0800 Subject: [PATCH 0204/1494] drm/amdgpu: introduce a new parameter to configure how many KCQ we want(v5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit what: the MQD's save and restore of KCQ (kernel compute queue) cost lots of clocks during world switch which impacts a lot to multi-VF performance how: introduce a paramter to control the number of KCQ to avoid performance drop if there is no kernel compute queue needed notes: this paramter only affects gfx 8/9/10 v2: refine namings v3: choose queues for each ring to that try best to cross pipes evenly. v4: fix indentation some cleanupsin the gfx_compute_queue_acquire() v5: further fix on indentations more cleanupsin gfx_compute_queue_acquire() TODO: in the future we will let hypervisor driver to set this paramter automatically thus no need for user to configure it through modprobe in virtual machine Signed-off-by: Monk Liu <Monk.Liu@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 49 +++++++++------------- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 30 ++++++------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 29 ++++++------- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 31 +++++++------- 7 files changed, 76 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e2eed5c630fcd..75631b3396a3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -202,6 +202,7 @@ extern int amdgpu_si_support; #ifdef CONFIG_DRM_AMDGPU_CIK extern int amdgpu_cik_support; #endif +extern int amdgpu_num_kcq; #define AMDGPU_VM_MAX_NUM_CTX 4096 #define AMDGPU_SG_THRESHOLD (256*1024*1024) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d01d7969d47b4..79b0da3e86391 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1199,6 +1199,11 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) amdgpu_gmc_tmz_set(adev); + if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { + amdgpu_num_kcq = 8; + dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid paramter provided by user\n"); + } + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index dc47549641e26..6d66705a11413 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -150,6 +150,7 @@ int amdgpu_noretry; int amdgpu_force_asic_type = -1; int amdgpu_tmz = 0; int amdgpu_reset_method = -1; /* auto */ +int amdgpu_num_kcq = -1; struct amdgpu_mgpu_info mgpu_info = { .mutex = __MUTEX_INITIALIZER(mgpu_info.mutex), @@ -776,6 +777,9 @@ module_param_named(reset_method, amdgpu_reset_method, int, 0444); MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); +MODULE_PARM_DESC(num_kcq, "number of kernel compute queue user want to setup (8 if set to greater than 8 or less than 0, only affect gfx 8+)"); +module_param_named(num_kcq, amdgpu_num_kcq, int, 0444); + static const struct pci_device_id pciidlist[] = { #ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 8eff0173360de..0cd9de69932bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -202,40 +202,29 @@ bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev, void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev) { - int i, queue, pipe, mec; + int i, queue, pipe; bool multipipe_policy = amdgpu_gfx_is_multipipe_capable(adev); - - /* policy for amdgpu compute queue ownership */ - for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) { - queue = i % adev->gfx.mec.num_queue_per_pipe; - pipe = (i / adev->gfx.mec.num_queue_per_pipe) - % adev->gfx.mec.num_pipe_per_mec; - mec = (i / adev->gfx.mec.num_queue_per_pipe) - / adev->gfx.mec.num_pipe_per_mec; - - /* we've run out of HW */ - if (mec >= adev->gfx.mec.num_mec) - break; - - if (multipipe_policy) { - /* policy: amdgpu owns the first two queues of the first MEC */ - if (mec == 0 && queue < 2) - set_bit(i, adev->gfx.mec.queue_bitmap); - } else { - /* policy: amdgpu owns all queues in the first pipe */ - if (mec == 0 && pipe == 0) - set_bit(i, adev->gfx.mec.queue_bitmap); + int max_queues_per_mec = min(adev->gfx.mec.num_pipe_per_mec * + adev->gfx.mec.num_queue_per_pipe, + adev->gfx.num_compute_rings); + + if (multipipe_policy) { + /* policy: make queues evenly cross all pipes on MEC1 only */ + for (i = 0; i < max_queues_per_mec; i++) { + pipe = i % adev->gfx.mec.num_pipe_per_mec; + queue = (i / adev->gfx.mec.num_pipe_per_mec) % + adev->gfx.mec.num_queue_per_pipe; + + set_bit(pipe * adev->gfx.mec.num_queue_per_pipe + queue, + adev->gfx.mec.queue_bitmap); } + } else { + /* policy: amdgpu owns all queues in the given pipe */ + for (i = 0; i < max_queues_per_mec; ++i) + set_bit(i, adev->gfx.mec.queue_bitmap); } - /* update the number of active compute rings */ - adev->gfx.num_compute_rings = - bitmap_weight(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); - - /* If you hit this case and edited the policy, you probably just - * need to increase AMDGPU_MAX_COMPUTE_RINGS */ - if (WARN_ON(adev->gfx.num_compute_rings > AMDGPU_MAX_COMPUTE_RINGS)) - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + dev_dbg(adev->dev, "mec queue bitmap weight=%d\n", bitmap_weight(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES)); } void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index fe8ccc9be6827..622f4425bf594 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4022,21 +4022,23 @@ static int gfx_v10_0_mec_init(struct amdgpu_device *adev) amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX10_MEC_HPD_SIZE; - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - gfx_v10_0_mec_fini(adev); - return r; - } + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + gfx_v10_0_mec_fini(adev); + return r; + } - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; @@ -7159,7 +7161,7 @@ static int gfx_v10_0_early_init(void *handle) break; } - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; gfx_v10_0_set_kiq_pm4_funcs(adev); gfx_v10_0_set_ring_funcs(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 8d7208959c952..7df567a6656dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1343,21 +1343,22 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX8_MEC_HPD_SIZE; + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + return r; + } - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - return r; - } - - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } return 0; } @@ -5294,7 +5295,7 @@ static int gfx_v8_0_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; adev->gfx.num_gfx_rings = GFX8_NUM_GFX_RINGS; - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; adev->gfx.funcs = &gfx_v8_0_gfx_funcs; gfx_v8_0_set_ring_funcs(adev); gfx_v8_0_set_irq_funcs(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e4e751f87092b..ef07e59cd4261 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1938,22 +1938,23 @@ static int gfx_v9_0_mec_init(struct amdgpu_device *adev) /* take ownership of the relevant compute queues */ amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX9_MEC_HPD_SIZE; + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + gfx_v9_0_mec_fini(adev); + return r; + } - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - gfx_v9_0_mec_fini(adev); - return r; - } - - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; @@ -4625,7 +4626,7 @@ static int gfx_v9_0_early_init(void *handle) adev->gfx.num_gfx_rings = 0; else adev->gfx.num_gfx_rings = GFX9_NUM_GFX_RINGS; - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; gfx_v9_0_set_kiq_pm4_funcs(adev); gfx_v9_0_set_ring_funcs(adev); gfx_v9_0_set_irq_funcs(adev); -- GitLab From 0ad7a64d69cdbe520d0df80d100cd6b891cc12fb Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Mon, 3 Aug 2020 14:24:50 +0800 Subject: [PATCH 0205/1494] drm/amdgpu: enable RAS support for sienna cichlid enabled GECC error injection and query support Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 89cb0ae9da9d4..1a55f6f492fdb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1965,8 +1965,9 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = 0; if (amdgpu_sriov_vf(adev) || !adev->is_atom_fw || - (adev->asic_type != CHIP_VEGA20 && - adev->asic_type != CHIP_ARCTURUS)) + (adev->asic_type != CHIP_VEGA20 && + adev->asic_type != CHIP_ARCTURUS && + adev->asic_type != CHIP_SIENNA_CICHLID)) return; if (amdgpu_atomfirmware_mem_ecc_supported(adev)) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 35d21f330b0ab..dd91a93de62ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -633,6 +633,10 @@ static int gmc_v10_0_late_init(void *handle) if (r) return r; + r = amdgpu_gmc_ras_late_init(adev); + if (r) + return r; + return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0); } -- GitLab From 4bfb74282f064f738abb22734a675326f41c230c Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Mon, 3 Aug 2020 15:52:52 +0800 Subject: [PATCH 0206/1494] drm/amdgpu: added RAS EEPROM device support check updated RAS EEPROM init/threshold sequences to check for device support Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index e5e3ed113d63c..0e64c39a23722 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -59,6 +59,15 @@ #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev +static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) +{ + if ((adev->asic_type == CHIP_VEGA20) || + (adev->asic_type == CHIP_ARCTURUS)) + return true; + + return false; +} + static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, uint16_t *i2c_addr) { @@ -276,6 +285,9 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, *exceed_err_limit = false; + if (!__is_ras_eeprom_supported(adev)) + return 0; + /* Verify i2c adapter is initialized */ if (!adev->pm.smu_i2c.algo) return -ENOENT; @@ -430,6 +442,9 @@ int amdgpu_ras_eeprom_check_err_threshold( *exceed_err_limit = false; + if (!__is_ras_eeprom_supported(adev)) + return 0; + /* read EEPROM table header */ mutex_lock(&control->tbl_mutex); ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); @@ -465,7 +480,7 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct amdgpu_device *adev = to_amdgpu_device(control); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - if (adev->asic_type != CHIP_VEGA20 && adev->asic_type != CHIP_ARCTURUS) + if (!__is_ras_eeprom_supported(adev)) return 0; buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE, -- GitLab From 734e4c97ab05db4157244284510a9fa45a9e889a Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Wed, 17 Jun 2020 15:28:04 -0400 Subject: [PATCH 0207/1494] drm/amd/display: DSC Slice height debugfs write entry [Why] We need to be able to specify slice height for any connector's DSC [How] Overwrite computed parameters in dsc_cfg, with the value needed/ Overwrites for both SST and MST connectors, but in different places, but the process is identical. Overwrites only if DSC is decided to be enabled on that connector. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 93 +++++++++++++++++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 7 ++ 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 342663fcd44d7..26217e5e800de 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4670,9 +4670,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, /* Overwrite the stream flag if DSC is enabled through debugfs */ if (aconnector->dsc_settings.dsc_clock_en) stream->timing.flags.DSC = 1; + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable, - aconnector->dsc_settings.dsc_slice_width); + aconnector->dsc_settings.dsc_slice_width); + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height) + stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable, + aconnector->dsc_settings.dsc_slice_height); } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a06ad133a23a8..1a31473d39921 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -345,6 +345,7 @@ struct amdgpu_display_manager { struct dsc_preferred_settings { bool dsc_clock_en; uint32_t dsc_slice_width; + uint32_t dsc_slice_height; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 550138012123e..b4c470c75cbe3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1274,6 +1274,22 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, return size; } +/* function: read DSC slice height parameter on the connector + * + * The read function: dp_dsc_slice_height_read + * returns dsc slice height used in the current configuration + * The return is an integer: 0 or other positive number + * + * Access the status with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + * 0 - means that DSC is disabled + * + * Any other number more than zero represents the + * slice height currently used by DSC in pixels + * + */ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1331,6 +1347,82 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, return result; } +/* function: write DSC slice height parameter + * + * The write function: dp_dsc_slice_height_write + * overwrites automatically generated DSC configuration + * of slice height. + * + * The user has to write the slice height divisible by the + * picture height. + * + * Also the user has to write height in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite slice height (example sets to 128 pixels): + * + * echo 0x80 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + * - To stop overwriting and let driver find the optimal size, + * set the height to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + */ +static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + uint8_t param_nums = 0; + long param[1] = {0}; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_slice_height = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1640,6 +1732,7 @@ static const struct file_operations dp_dsc_slice_width_debugfs_fops = { static const struct file_operations dp_dsc_slice_height_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_slice_height_read, + .write = dp_dsc_slice_height_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index b8a900e963d3f..4d74780f21a45 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -452,6 +452,7 @@ struct dsc_mst_fairness_params { struct drm_dp_mst_port *port; bool clock_overwrite; uint32_t slice_width_overwrite; + uint32_t slice_height_overwrite; }; struct dsc_mst_fairness_vars { @@ -490,6 +491,11 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( params[i].timing->h_addressable, params[i].slice_width_overwrite); + + if (params[i].slice_height_overwrite) + params[i].timing->dsc_cfg.num_slices_v = DIV_ROUND_UP( + params[i].timing->v_addressable, + params[i].slice_height_overwrite); } else { params[i].timing->flags.DSC = 0; } @@ -707,6 +713,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (params[count].clock_overwrite) debugfs_overwrite = true; params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; + params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- GitLab From d8a8258ec1a2b8d99bdc67d03fe62ca5cec98a14 Mon Sep 17 00:00:00 2001 From: Eric Bernstein <eric.bernstein@amd.com> Date: Mon, 20 Jul 2020 16:10:22 -0400 Subject: [PATCH 0208/1494] drm/amd/display: Update virtual stream encoder Signed-off-by: Eric Bernstein <eric.bernstein@amd.com> Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/virtual/virtual_stream_encoder.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index b8040da94b9db..944c0327763c1 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -87,6 +87,17 @@ static void virtual_enc_dp_set_odm_combine( bool odm_combine) {} +static void virtual_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{} + +static void virtual_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, + bool enable) +{} + static const struct stream_encoder_funcs virtual_str_enc_funcs = { .dp_set_odm_combine = virtual_enc_dp_set_odm_combine, @@ -114,6 +125,8 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { .audio_mute_control = virtual_audio_mute_control, .set_avmute = virtual_stream_encoder_set_avmute, .hdmi_reset_stream_attribute = virtual_stream_encoder_reset_hdmi_stream_attribute, + .dig_connect_to_otg = virtual_dig_connect_to_otg, + .setup_stereo_sync = virtual_setup_stereo_sync, }; bool virtual_stream_encoder_construct( -- GitLab From 1174eb89ccf54166a0cbbef86e6044811320a754 Mon Sep 17 00:00:00 2001 From: Eric Bernstein <eric.bernstein@amd.com> Date: Mon, 20 Jul 2020 19:18:43 -0400 Subject: [PATCH 0209/1494] drm/amd/display: Use parameter for call to set output mux Signed-off-by: Eric Bernstein <eric.bernstein@amd.com> Reviewed-by: Chris Park <Chris.Park@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 02742cca4d845..9f8ab679616c1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3102,6 +3102,9 @@ void core_link_enable_stream( struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; +#endif DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); if (!IS_DIAG_DC(dc->ctx->dce_environment) && @@ -3136,8 +3139,8 @@ void core_link_enable_stream( pipe_ctx->stream->link->link_state_valid = true; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) - if (pipe_ctx->stream_res.tg->funcs->set_out_mux) - pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); + if (pipe_ctx->stream_res.tg->funcs->set_out_mux) + pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest); #endif if (dc_is_dvi_signal(pipe_ctx->stream->signal)) -- GitLab From 6224220dc778e6e7b2139f6f29803d6dbdc33d95 Mon Sep 17 00:00:00 2001 From: Igor Kravchenko <Igor.Kravchenko@amd.com> Date: Sun, 19 Jul 2020 20:45:28 -0400 Subject: [PATCH 0210/1494] drm/amd/display: Read VBIOS Golden Settings Tbl [Why] For ver.4.4 and higher VBIOS contains default setting table. {How] Read Golden Settings Table from VBIOS, apply Aux tuning parameters. Signed-off-by: Igor Kravchenko <Igor.Kravchenko@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/bios/bios_parser.c | 2 + .../drm/amd/display/dc/bios/bios_parser2.c | 81 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 + .../gpu/drm/amd/display/dc/dc_bios_types.h | 4 + drivers/gpu/drm/amd/display/dc/dc_types.h | 14 ++++ .../drm/amd/display/dc/dce/dce_link_encoder.h | 4 +- .../amd/display/dc/dcn10/dcn10_link_encoder.h | 10 ++- .../amd/display/dc/dcn20/dcn20_link_encoder.c | 14 +++- .../amd/display/dc/dcn20/dcn20_link_encoder.h | 5 +- drivers/gpu/drm/amd/include/atomfirmware.h | 54 ++++++++++++- 10 files changed, 182 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 008d4d11339d9..ad394aefa5d90 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -2834,6 +2834,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .bios_parser_destroy = bios_parser_destroy, .get_board_layout_info = bios_get_board_layout_info, + + .get_atom_dc_golden_table = NULL }; static bool bios_parser_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index b8684131151d8..f8db92fed9cfb 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -2079,6 +2079,85 @@ static uint16_t bios_parser_pack_data_tables( return 0; } +static struct atom_dc_golden_table_v1 *bios_get_golden_table( + struct bios_parser *bp, + uint32_t rev_major, + uint32_t rev_minor, + uint16_t *dc_golden_table_ver) +{ + struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL; + uint32_t dc_golden_offset = 0; + *dc_golden_table_ver = 0; + + if (!DATA_TABLES(dce_info)) + return NULL; + + /* ver.4.4 or higher */ + switch (rev_major) { + case 4: + switch (rev_minor) { + case 4: + disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl_4_4) + return NULL; + dc_golden_offset = disp_cntl_tbl_4_4->dc_golden_table_offset; + *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver; + break; + } + break; + } + + if (!dc_golden_offset) + return NULL; + + if (*dc_golden_table_ver != 1) + return NULL; + + return GET_IMAGE(struct atom_dc_golden_table_v1, + dc_golden_offset); +} + +static enum bp_result bios_get_atom_dc_golden_table( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_OK; + struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + uint16_t dc_golden_table_ver = 0; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + if (!header) + return BP_RESULT_UNSUPPORTED; + + get_atom_data_table_revision(header, &tbl_revision); + + atom_dc_golden_table = bios_get_golden_table(bp, + tbl_revision.major, + tbl_revision.minor, + &dc_golden_table_ver); + + if (!atom_dc_golden_table) + return BP_RESULT_UNSUPPORTED; + + dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver; + dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val; + dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val; + dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val; + dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val; + dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val; + dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val; + dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val; + dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val; + dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val; + + return result; +} + + static const struct dc_vbios_funcs vbios_funcs = { .get_connectors_number = bios_parser_get_connectors_number, @@ -2128,6 +2207,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_board_layout_info = bios_get_board_layout_info, .pack_data_tables = bios_parser_pack_data_tables, + + .get_atom_dc_golden_table = bios_get_atom_dc_golden_table }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9f8ab679616c1..071c7b32b282c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1540,6 +1540,9 @@ static bool dc_link_construct(struct dc_link *link, } } + if (bios->funcs->get_atom_dc_golden_table) + bios->funcs->get_atom_dc_golden_table(bios); + /* * TODO check if GPIO programmed correctly * diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 845a3054f21fd..d06d07042a120 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -133,6 +133,9 @@ struct dc_vbios_funcs { uint16_t (*pack_data_tables)( struct dc_bios *dcb, void *dst); + + enum bp_result (*get_atom_dc_golden_table)( + struct dc_bios *dcb); }; struct bios_registers { @@ -154,6 +157,7 @@ struct dc_bios { struct dc_firmware_info fw_info; bool fw_info_valid; struct dc_vram_info vram_info; + struct dc_golden_table golden_table; }; #endif /* DC_BIOS_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 29fe5389f973d..946ba929c6f64 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -890,6 +890,20 @@ struct dsc_dec_dpcd_caps { uint32_t branch_max_line_width; }; +struct dc_golden_table { + uint16_t dc_golden_table_ver; + uint32_t aux_dphy_rx_control0_val; + uint32_t aux_dphy_tx_control_val; + uint32_t aux_dphy_rx_control1_val; + uint32_t dc_gpio_aux_ctrl_0_val; + uint32_t dc_gpio_aux_ctrl_1_val; + uint32_t dc_gpio_aux_ctrl_2_val; + uint32_t dc_gpio_aux_ctrl_3_val; + uint32_t dc_gpio_aux_ctrl_4_val; + uint32_t dc_gpio_aux_ctrl_5_val; +}; + + #if defined(CONFIG_DRM_AMD_DC_DCN3_0) enum dc_gpu_mem_alloc_type { DC_MEM_ALLOC_TYPE_GART, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 40ea2220330c3..cb714a48b171c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -38,7 +38,8 @@ #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) #define HPD_REG_LIST(id)\ SRI(DC_HPD_CONTROL, HPD, id) @@ -135,6 +136,7 @@ struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; + uint32_t AUX_DPHY_RX_CONTROL1; }; struct dce110_link_enc_hpd_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index cf59ab0034dc6..04dabed5f1c59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -31,10 +31,10 @@ #define TO_DCN10_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dcn10_link_encoder, base) - #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) #define HPD_REG_LIST(id)\ SRI(DC_HPD_CONTROL, HPD, id) @@ -73,6 +73,7 @@ struct dcn10_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; uint32_t AUX_DPHY_TX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL1; }; struct dcn10_link_enc_hpd_registers { @@ -443,7 +444,10 @@ struct dcn10_link_enc_registers { type AUX_TX_PRECHARGE_LEN; \ type AUX_TX_PRECHARGE_SYMBOLS; \ type AUX_MODE_DET_CHECK_DELAY;\ - type DPCS_DBG_CBUS_DIS + type DPCS_DBG_CBUS_DIS;\ + type AUX_RX_PRECHARGE_SKIP;\ + type AUX_RX_TIMEOUT_LEN;\ + type AUX_RX_TIMEOUT_LEN_MUL struct dcn10_link_enc_shift { DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c index 8d209dae66e6a..15c2ff264ff60 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c @@ -309,7 +309,6 @@ bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) void enc2_hw_init(struct link_encoder *enc) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - /* 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 @@ -333,9 +332,18 @@ void enc2_hw_init(struct link_encoder *enc) AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 AUX_RX_DETECTION_THRESHOLD [30:28] = 1 */ - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); + + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); + } else { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c4d); - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + } //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index db09f40075c2e..bf0044f7417ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -191,7 +191,10 @@ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh) + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) #define UNIPHY_DCN2_REG_LIST(id) \ SRI(CLOCK_ENABLE, SYMCLK, id), \ diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index c2544c81dfb2b..3e526c394f6cb 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -941,7 +941,6 @@ struct atom_display_controller_info_v4_1 uint8_t reserved3[8]; }; - struct atom_display_controller_info_v4_2 { struct atom_common_table_header table_header; @@ -976,6 +975,59 @@ struct atom_display_controller_info_v4_2 uint8_t reserved3[8]; }; +struct atom_display_controller_info_v4_4 { + struct atom_common_table_header table_header; + uint32_t display_caps; + uint32_t bootup_dispclk_10khz; + uint16_t dce_refclk_10khz; + uint16_t i2c_engine_refclk_10khz; + uint16_t dvi_ss_percentage; // in unit of 0.001% + uint16_t dvi_ss_rate_10hz; + uint16_t hdmi_ss_percentage; // in unit of 0.001% + uint16_t hdmi_ss_rate_10hz; + uint16_t dp_ss_percentage; // in unit of 0.001% + uint16_t dp_ss_rate_10hz; + uint8_t dvi_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t hdmi_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t dp_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t ss_reserved; + uint8_t dfp_hardcode_mode_num; // DFP hardcode mode number defined in StandardVESA_TimingTable when EDID is not available + uint8_t dfp_hardcode_refreshrate;// DFP hardcode mode refreshrate defined in StandardVESA_TimingTable when EDID is not available + uint8_t vga_hardcode_mode_num; // VGA hardcode mode number defined in StandardVESA_TimingTable when EDID is not avablable + uint8_t vga_hardcode_refreshrate;// VGA hardcode mode number defined in StandardVESA_TimingTable when EDID is not avablable + uint16_t dpphy_refclk_10khz; + uint16_t hw_chip_id; + uint8_t dcnip_min_ver; + uint8_t dcnip_max_ver; + uint8_t max_disp_pipe_num; + uint8_t max_vbios_active_disp_pipum; + uint8_t max_ppll_num; + uint8_t max_disp_phy_num; + uint8_t max_aux_pairs; + uint8_t remotedisplayconfig; + uint32_t dispclk_pll_vco_freq; + uint32_t dp_ref_clk_freq; + uint32_t max_mclk_chg_lat; // Worst case blackout duration for a memory clock frequency (p-state) change, units of 100s of ns (0.1 us) + uint32_t max_sr_exit_lat; // Worst case memory self refresh exit time, units of 100ns of ns (0.1us) + uint32_t max_sr_enter_exit_lat; // Worst case memory self refresh entry followed by immediate exit time, units of 100ns of ns (0.1us) + uint16_t dc_golden_table_offset; // point of struct of atom_dc_golden_table_vxx + uint16_t dc_golden_table_ver; + uint32_t reserved3[3]; +}; + +struct atom_dc_golden_table_v1 +{ + uint32_t aux_dphy_rx_control0_val; + uint32_t aux_dphy_tx_control_val; + uint32_t aux_dphy_rx_control1_val; + uint32_t dc_gpio_aux_ctrl_0_val; + uint32_t dc_gpio_aux_ctrl_1_val; + uint32_t dc_gpio_aux_ctrl_2_val; + uint32_t dc_gpio_aux_ctrl_3_val; + uint32_t dc_gpio_aux_ctrl_4_val; + uint32_t dc_gpio_aux_ctrl_5_val; + uint32_t reserved[23]; +}; enum dce_info_caps_def { -- GitLab From a245528c598dc80fe909a5ea77372d071fd3a111 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Fri, 26 Jun 2020 14:30:29 -0400 Subject: [PATCH 0211/1494] drm/amd/display: populate new dml variable Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Reviewed-by: Eric Bernstein <Eric.Bernstein@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index b0064087b9bbb..afdd4f0d9d718 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -467,7 +467,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] = 1; mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0; - mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;; + mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = -- GitLab From 5268bf136ef08c6a30d132036de3092d8219da8c Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Fri, 19 Jun 2020 14:02:38 -0400 Subject: [PATCH 0212/1494] drm/amd/display: DSC Bit target rate debugfs write entry [Why] We need to be able to specify bits per pixel for DSC on any connector. [How] Overwrite computed DSC target rate in dsc_cfg, with requested value. Overwrites for both SST and MST connectors, but in different places, but the process is identical. Overwrites only if DSC is decided to be enabled on that connector. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 86 +++++++++++++++++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 9 +- 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 26217e5e800de..765680b62d6a4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4678,6 +4678,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height) stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable, aconnector->dsc_settings.dsc_slice_height); + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) + stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1a31473d39921..a8fff3413af33 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -346,6 +346,7 @@ struct dsc_preferred_settings { bool dsc_clock_en; uint32_t dsc_slice_width; uint32_t dsc_slice_height; + uint32_t dsc_bits_per_pixel; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index b4c470c75cbe3..9260b27659e48 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1423,6 +1423,18 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, return size; } +/* function: read DSC target rate on the connector in bits per pixel + * + * The read function: dp_dsc_bits_per_pixel_read + * returns target rate of compression in bits per pixel + * The return is an integer: 0 or other positive integer + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1480,6 +1492,79 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, return result; } +/* function: write DSC target rate in bits per pixel + * + * The write function: dp_dsc_bits_per_pixel_write + * overwrites automatically generated DSC configuration + * of DSC target bit rate. + * + * Also the user has to write bpp in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite rate (example sets to 256 bpp x 1/16): + * + * echo 0x100 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + * - To stop overwriting and let driver find the optimal rate, + * set the rate to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + */ +static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + uint8_t param_nums = 0; + long param[1] = {0}; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_bits_per_pixel = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1739,6 +1824,7 @@ static const struct file_operations dp_dsc_slice_height_debugfs_fops = { static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_bits_per_pixel_read, + .write = dp_dsc_bits_per_pixel_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 4d74780f21a45..a222335133e0e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -453,6 +453,7 @@ struct dsc_mst_fairness_params { bool clock_overwrite; uint32_t slice_width_overwrite; uint32_t slice_height_overwrite; + uint32_t bpp_overwrite; }; struct dsc_mst_fairness_vars { @@ -486,7 +487,12 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p params[i].timing, ¶ms[i].timing->dsc_cfg)) { params[i].timing->flags.DSC = 1; - params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + + if (params[i].bpp_overwrite) + params[i].timing->dsc_cfg.bits_per_pixel = params[i].bpp_overwrite; + else + params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + if (params[i].slice_width_overwrite) params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( params[i].timing->h_addressable, @@ -714,6 +720,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, debugfs_overwrite = true; params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; + params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- GitLab From 06ff02fc1e14f9503340b1a140dde95eeaa000fe Mon Sep 17 00:00:00 2001 From: Harry Wentland <harry.wentland@amd.com> Date: Tue, 30 Jun 2020 11:16:05 -0400 Subject: [PATCH 0213/1494] drm/amd/display: Fix logger context [Why&How] use correct logger context Signed-off-by: Harry Wentland <harry.wentland@amd.com> Reviewed-by: Roman Li <Roman.Li@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index ca9eedb643f29..949b61351edea 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -71,8 +71,9 @@ enum dentist_divider_range { #define CTX \ clk_mgr->base.ctx + #define DC_LOGGER \ - clk_mgr->ctx->logger + clk_mgr->base.ctx->logger -- GitLab From 87353ae837c30c68b89b0d88005fefabe087859d Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Fri, 19 Jun 2020 14:07:03 -0400 Subject: [PATCH 0214/1494] drm/amd/display: Comments on how to use DSC debugfs some entries [why] Some of the DSC debugfs read enteries are missing comments explaining how to use and how to comprehend the results. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9260b27659e48..9610e628baf00 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1565,6 +1565,21 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu return size; } +/* function: read DSC picture width parameter on the connector + * + * The read function: dp_dsc_pic_width_read + * returns dsc picture width used in the current configuration + * It is the same as h_addressable of the current + * display's timing + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_pic_width + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1679,6 +1694,21 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, return result; } +/* function: read DSC chunk size parameter on the connector + * + * The read function: dp_dsc_chunk_size_read + * returns dsc chunk size set in the current configuration + * The value is calculated automatically by DSC code + * and depends on slice parameters and bpp target rate + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_chunk_size + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1736,6 +1766,21 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, return result; } +/* function: read DSC slice bpg offset on the connector + * + * The read function: dp_dsc_slice_bpg_offset_read + * returns dsc bpg slice offset set in the current configuration + * The value is calculated automatically by DSC code + * and depends on slice parameters and bpp target rate + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_bpg_offset + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { -- GitLab From d024656757dc07e9f77d1eed854ce8f885f11856 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Thu, 23 Jul 2020 13:06:23 -0400 Subject: [PATCH 0215/1494] drm/amd/display: AMD OUI (DPCD 0x00300) skipped on some sink [Why] Sink OUI supported cap is not set so driver skips programming it. [How] Revert the change the skips OUI programming if the cap is not set Signed-off-by: Aric Cyr <aric.cyr@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d7d2dcd49c062..9bc03f26efdaf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4339,22 +4339,6 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) void dpcd_set_source_specific_data(struct dc_link *link) { - uint8_t dspc = 0; - enum dc_status ret; - - ret = core_link_read_dpcd(link, DP_DOWN_STREAM_PORT_COUNT, &dspc, - sizeof(dspc)); - - if (ret != DC_OK) { - DC_LOG_ERROR("Error in DP aux read transaction," - " not writing source specific data\n"); - return; - } - - /* Return if OUI unsupported */ - if (!(dspc & DP_OUI_SUPPORT)) - return; - if (!link->dc->vendor_signature.is_valid) { struct dpcd_amd_signature amd_signature; amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0; -- GitLab From 519d91d87f2e19727de772402ac0977633bbd13a Mon Sep 17 00:00:00 2001 From: "JinZe.Xu" <JinZe.Xu@amd.com> Date: Tue, 21 Jul 2020 17:52:41 +0800 Subject: [PATCH 0216/1494] drm/amd/display: Use helper function to check for HDMI signal [How] Use dc_is_hdmi_signal to determine signal type. Signed-off-by: JinZe.Xu <JinZe.Xu@amd.com> Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 071c7b32b282c..4bd6e03a7ef37 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3282,7 +3282,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) dc_is_virtual_signal(pipe_ctx->stream->signal)) return; - if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { core_link_set_avmute(pipe_ctx, true); } -- GitLab From 0914d1154f0ff03944d485f610efa3158aee4a06 Mon Sep 17 00:00:00 2001 From: George Shen <george.shen@amd.com> Date: Fri, 17 Jul 2020 13:19:27 -0400 Subject: [PATCH 0217/1494] drm/amd/display: Change null plane state swizzle mode to 4kb_s [Why] During SetPathMode and UpdatePlanes, the plane state can be null. We default to linear swizzle mode when plane state is null. This resulted in bandwidth validation failing when trying to set 8K60 mode (which previously passed validation during rebuild timing list). [How] Change the default swizzle mode from linear to 4kb_s and update pitch accordingly. Signed-off-by: George Shen <george.shen@amd.com> Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 2a5e7175926ae..790baf5526959 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2223,7 +2223,7 @@ int dcn20_populate_dml_pipes_from_context( if (!res_ctx->pipe_ctx[i].plane_state) { pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; pipes[pipe_cnt].pipe.src.source_scan = dm_horz; - pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_linear; + pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s; pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile; pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable; if (pipes[pipe_cnt].pipe.src.viewport_width > 1920) @@ -2235,7 +2235,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.surface_width_y = pipes[pipe_cnt].pipe.src.viewport_width; pipes[pipe_cnt].pipe.src.surface_height_c = pipes[pipe_cnt].pipe.src.viewport_height; pipes[pipe_cnt].pipe.src.surface_width_c = pipes[pipe_cnt].pipe.src.viewport_width; - pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 63) / 64) * 64; /* linear sw only */ + pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 255) / 256) * 256; pipes[pipe_cnt].pipe.src.source_format = dm_444_32; pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/ pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/ -- GitLab From da83b385f3eba1d695bc8014d8a5c0a791188c16 Mon Sep 17 00:00:00 2001 From: Igor Kravchenko <Igor.Kravchenko@amd.com> Date: Fri, 24 Jul 2020 11:10:40 -0400 Subject: [PATCH 0218/1494] drm/amd/display: Display goes blank after inst [why] Display goes blank after driver installation. Aux tuning parameters must be used for 2.x only. Wrong dc_golden_table offset was used. [How] Implement a new enc3_hw_init function without VBIOS constants usage to be called for 3.x Calculate dc_golden_table offset using sum of base dce_info offset and golden table offset Signed-off-by: Igor Kravchenko <Igor.Kravchenko@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/bios/bios_parser2.c | 4 +- .../display/dc/dcn30/dcn30_dio_link_encoder.c | 53 ++++++++++++++++++- .../display/dc/dcn30/dcn30_dio_link_encoder.h | 2 + 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f8db92fed9cfb..078b7e3441855 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -2101,7 +2101,7 @@ static struct atom_dc_golden_table_v1 *bios_get_golden_table( DATA_TABLES(dce_info)); if (!disp_cntl_tbl_4_4) return NULL; - dc_golden_offset = disp_cntl_tbl_4_4->dc_golden_table_offset; + dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset; *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver; break; } @@ -2115,7 +2115,7 @@ static struct atom_dc_golden_table_v1 *bios_get_golden_table( return NULL; return GET_IMAGE(struct atom_dc_golden_table_v1, - dc_golden_offset); + dc_golden_offset); } static enum bp_result bios_get_atom_dc_golden_table( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c index c29326e9856a2..2ae159e2dd6e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c @@ -62,7 +62,7 @@ static const struct link_encoder_funcs dcn30_link_enc_funcs = { .read_state = link_enc2_read_state, .validate_output_with_stream = dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc2_hw_init, + .hw_init = enc3_hw_init, .setup = dcn10_link_encoder_setup, .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, .enable_dp_output = dcn20_link_encoder_enable_dp_output, @@ -203,3 +203,54 @@ void dcn30_link_encoder_construct( enc10->base.features.flags.bits.HDMI_6GB_EN = 0; } } + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc3_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 585d1ce63db19..8e9fd59ccde82 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -73,4 +73,6 @@ void dcn30_link_encoder_construct( const struct dcn10_link_enc_shift *link_shift, const struct dcn10_link_enc_mask *link_mask); +void enc3_hw_init(struct link_encoder *enc); + #endif /* __DC_LINK_ENCODER__DCN30_H__ */ -- GitLab From 3d4e52d0cf24b424c668fa8ab1269725796d4ec4 Mon Sep 17 00:00:00 2001 From: Victor Lu <victorchengchi.lu@amd.com> Date: Tue, 21 Jul 2020 12:08:34 -0400 Subject: [PATCH 0219/1494] drm/amd/display: Add debugfs for forcing stream timing sync [why] There's currently no method to enable multi-stream synchronization from userspace and we don't check the VSDB bits to know whether or not specific displays should have the feature enable. [how] Add a debugfs entry that controls a new DM debug option, "force_timing_sync". This debug option will set on any newly created stream following the change to the debug option. Expose a new interface from DC that performs the timing sync and a helper to the "force_timing_sync" debugfs that iterates over the current streams and modifies the current synchornization state and grouping. Example usage to force a resync (from an X based desktop): echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync xset dpms force off && xset dpms force on Signed-off-by: Victor Lu <victorchengchi.lu@amd.com> Reviewed-by: Aurabindo Jayamohanan Pillai <Aurabindo.Pillai@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Acked-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 ++ .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 35 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 13 ++++--- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 ++ 5 files changed, 75 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 765680b62d6a4..27dfd285a9445 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8034,6 +8034,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, goto fail; } + /* + * TODO: Check VSDB bits to decide whether this should + * be enabled or not. + */ + new_stream->triggered_crtc_reset.enabled = + dm->force_timing_sync; + dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level; ret = fill_hdr_info_packet(drm_new_conn_state, @@ -9190,3 +9197,22 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) return dc_link_set_psr_allow_active(stream->link, false, true); } + +void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) +{ + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + int i; + + mutex_lock(&adev->dm.dc_lock); + if (dc->current_state) { + for (i = 0; i < dc->current_state->stream_count; ++i) + dc->current_state->streams[i] + ->triggered_crtc_reset.enabled = + adev->dm.force_timing_sync; + + dm_enable_per_frame_crtc_master_sync(dc->current_state); + dc_trigger_sync(dc, dc->current_state); + } + mutex_unlock(&adev->dm.dc_lock); +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a8fff3413af33..fd863331dee1c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -340,6 +340,7 @@ struct amdgpu_display_manager { * fake encoders used for DP MST. */ struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; + bool force_timing_sync; }; struct dsc_preferred_settings { @@ -493,6 +494,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct edid *edid); +void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); + #define MAX_COLOR_LUT_ENTRIES 4096 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */ #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9610e628baf00..ae6b1313403e9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2183,6 +2183,38 @@ static const struct drm_info_list amdgpu_dm_debugfs_list[] = { {"amdgpu_mst_topology", &mst_topo}, }; +/* + * Sets the force_timing_sync debug optino from the given string. + * All connected displays will be force synchronized immediately. + * Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync + */ +static int force_timing_sync_set(void *data, u64 val) +{ + struct amdgpu_device *adev = data; + + adev->dm.force_timing_sync = (bool)val; + + amdgpu_dm_trigger_timing_sync(adev->ddev); + + return 0; +} + +/* + * Gets the force_timing_sync debug option value into the given buffer. + * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync + */ +static int force_timing_sync_get(void *data, u64 *val) +{ + struct amdgpu_device *adev = data; + + *val = adev->dm.force_timing_sync; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(force_timing_sync_ops, force_timing_sync_get, + force_timing_sync_set, "%llu\n"); + /* * Sets the DC visual confirm debug option from the given string. * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm @@ -2242,5 +2274,8 @@ int dtn_debugfs_init(struct amdgpu_device *adev) debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root, adev, &dmub_fw_state_fops); + debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root, + adev, &force_timing_sync_ops); + return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 92eb1ca1634fc..5aa3b89471c31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1238,6 +1238,14 @@ bool dc_enable_stereo( return ret; } +void dc_trigger_sync(struct dc *dc, struct dc_state *context) +{ + if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { + enable_timing_multisync(dc, context); + program_timing_sync(dc, context); + } +} + /* * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. @@ -1297,10 +1305,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c if (result != DC_OK) return result; - if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { - enable_timing_multisync(dc, context); - program_timing_sync(dc, context); - } + dc_trigger_sync(dc, context); /* Program all planes within new context*/ if (dc->hwss.program_front_end_for_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 633442bc7ef26..37743073772bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -397,6 +397,8 @@ bool dc_enable_stereo( struct dc_stream_state *streams[], uint8_t stream_count); +/* Triggers multi-stream synchronization. */ +void dc_trigger_sync(struct dc *dc, struct dc_state *context); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, -- GitLab From 4453fbec106b5ab69389bf48a27af228a8434b97 Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Wed, 22 Jul 2020 00:32:14 -0400 Subject: [PATCH 0220/1494] drm/amd/display: Separate pipe disconnect from rest of progrmaming [Why] When changing pixel formats for HDR (e.g. ARGB -> FP16) there are configurations that change from 2 pipes to 1 pipe. In these cases, it seems that disconnecting MPCC and doing a surface update at the same time(after unlocking) causes some registers to be updated slightly faster than others after unlocking (e.g. if the pixel format is updated to FP16 before the new surface address is programmed, we get corruption on the screen because the pixel formats aren't matching). We separate disconnecting MPCC from the rest of the pipe programming sequence to prevent this. [How] Move MPCC disconnect into separate operation than the rest of the pipe programming. Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++ .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 114 ++++++++++++++++++ .../drm/amd/display/dc/dcn20/dcn20_hwseq.h | 7 ++ .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 + .../gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 + .../gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 7 files changed, 141 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5aa3b89471c31..ebbb8182228d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,6 +2300,7 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { + bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2330,6 +2331,15 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && + dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ + dc->hwss.interdependent_update_lock(dc, context, true); + mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); + } + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1d..73eb4e76a0b1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1624,6 +1624,120 @@ static void dcn20_program_pipe( } } +bool dcn20_disconnect_pipes( + struct dc *dc, + struct dc_state *context) +{ + int i; + struct dce_hwseq *hws = dc->hwseq; + bool mpcc_disconnected = false; + DC_LOGGER_INIT(dc->ctx->logger); + + /* Set pipe update flags and lock pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) + dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], + &context->res_ctx.pipe_ctx[i]); + + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + /* OTG blank before disabling all front ends */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable + && !context->res_ctx.pipe_ctx[i].top_pipe + && !context->res_ctx.pipe_ctx[i].prev_odm_pipe + && context->res_ctx.pipe_ctx[i].stream) { + hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); + } + } + + /* Disconnect mpcc */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { + hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); + mpcc_disconnected = true; + } + } + } + + if (mpcc_disconnected) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + + if (!pipe_ctx || !plane_state || !pipe_ctx->stream) + continue; + + // Only update scaler and viewport here if we lose a pipe split. + // This is to prevent half the screen from being black when we + // unlock after disconnecting MPCC. + if (!(old_pipe && !pipe_ctx->top_pipe && + !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) + continue; + + if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { + if (pipe_ctx->update_flags.bits.scaler || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change || + plane_state->update_flags.bits.per_pixel_alpha_change || + pipe_ctx->stream->update_flags.bits.scaling) { + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; + ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); + /* scaler configuration */ + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + } + + if (pipe_ctx->update_flags.bits.viewport || + (context == dc->current_state && plane_state->update_flags.bits.position_change) || + (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || + (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { + + hubp->funcs->mem_program_viewport( + hubp, + &pipe_ctx->plane_res.scl_data.viewport, + &pipe_ctx->plane_res.scl_data.viewport_c); + } + } + } + } + return mpcc_disconnected; +} + +void dcn20_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *pipe_ctx; + struct timing_generator *tg; + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + tg = pipe_ctx->stream_res.tg; + + /* + * Only wait for top pipe's tg penindg bit + * Also skip if pipe is disabled. + */ + if (pipe_ctx->top_pipe || + !pipe_ctx->stream || !pipe_ctx->plane_state || + !tg->funcs->is_tg_enabled(tg)) + continue; + + /* + * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. + * For some reason waiting for OTG_UPDATE_PENDING cleared + * seems to not trigger the update right away, and if we + * lock again before VUPDATE then we don't get a separated + * operation. + */ + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + } +} + void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 83220e34c1a92..7befd35a23596 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -131,6 +131,13 @@ void dcn20_dccg_init(struct dce_hwseq *hws); int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); +bool dcn20_disconnect_pipes( + struct dc *dc, + struct dc_state *context); + +void dcn20_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context); + #ifndef TRIM_FSFT bool dcn20_optimize_timing_for_fsft(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 3dde6f26de474..55afb70d33e5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index b187f71afa652..264302b27d4ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 9afee71604902..845aaf1c816c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 3c986717dcd56..64c1be818b0e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,10 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); + bool (*disconnect_pipes)(struct dc *dc, + struct dc_state *context); + void (*wait_for_pending_cleared)(struct dc *dc, + struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- GitLab From ded750e6faaf965f7b07f8468488381dcb790c9c Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Fri, 24 Jul 2020 21:37:56 -0400 Subject: [PATCH 0221/1494] drm/amd/display: [FW Promotion] Release 0.0.27 | [Header Changes] | - Reworked the FW versioning to include hotfix | and test bits Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8b27cf0f1d513..55717ae4724d3 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,11 +36,20 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x636e7b294 +#define DMUB_FW_VERSION_GIT_HASH 0xd7f4bb6ee #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 26 -#define DMUB_FW_VERSION_UCODE ((DMUB_FW_VERSION_MAJOR << 24) | (DMUB_FW_VERSION_MINOR << 16) | DMUB_FW_VERSION_REVISION) +#define DMUB_FW_VERSION_REVISION 27 +#define DMUB_FW_VERSION_TEST 0 +#define DMUB_FW_VERSION_VBIOS 0 +#define DMUB_FW_VERSION_HOTFIX 0 +#define DMUB_FW_VERSION_UCODE (((DMUB_FW_VERSION_MAJOR & 0xFF) << 24) | \ + ((DMUB_FW_VERSION_MINOR & 0xFF) << 16) | \ + ((DMUB_FW_VERSION_REVISION & 0xFF) << 8) | \ + ((DMUB_FW_VERSION_TEST & 0x1) << 7) | \ + ((DMUB_FW_VERSION_VBIOS & 0x1) << 6) | \ + (DMUB_FW_VERSION_HOTFIX & 0x3F)) + #endif //<DMUB_TYPES>================================================================== -- GitLab From c4dfb54986fd79ac992c56c5a31af9469d60d5cf Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 27 Jul 2020 10:53:38 -0400 Subject: [PATCH 0222/1494] drm/amd/display: 3.2.97 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ae0e27c67ef9c..6d4cab948607c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.96" +#define DC_VER "3.2.97" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 66f3db4ba62db74d0f6c5a0f872592f1a0ed7670 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 30 Jul 2020 15:21:33 -0400 Subject: [PATCH 0223/1494] drm/amdgpu/smu: rework i2c adpater registration The i2c init/fini functions just register the i2c adapter. There is no need to call them during hw init/fini. They only need to be called once per driver init/fini. The previous behavior broke runtime pm because we unregistered the i2c adapter during suspend. Tested-by: Tom St Denis <tom.stdenis@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 12 ++++++------ drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 14 -------------- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 14 -------------- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 14 -------------- 4 files changed, 6 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 55463e7a11e2a..d03b4852ed5fa 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -579,6 +579,10 @@ static int smu_smc_table_sw_init(struct smu_context *smu) if (ret) return ret; + ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); + if (ret) + return ret; + return 0; } @@ -586,6 +590,8 @@ static int smu_smc_table_sw_fini(struct smu_context *smu) { int ret; + smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + ret = smu_free_memory_pool(smu); if (ret) return ret; @@ -845,10 +851,6 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - ret = smu_i2c_init(smu, &adev->pm.smu_i2c); - if (ret) - return ret; - ret = smu_disable_umc_cdr_12gbps_workaround(smu); if (ret) { dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n"); @@ -1047,8 +1049,6 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; - smu_i2c_fini(smu, &adev->pm.smu_i2c); - cancel_work_sync(&smu->throttling_logging_work); ret = smu_disable_thermal_alert(smu); diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index f13979687b9e6..0147a5b9b06d4 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2080,22 +2080,11 @@ static const struct i2c_algorithm arcturus_i2c_algo = { .functionality = arcturus_i2c_func, }; -static bool arcturus_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (arcturus_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2111,9 +2100,6 @@ static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!arcturus_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 6aaf483858a0f..c33bdc6747f29 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -2457,22 +2457,11 @@ static const struct i2c_algorithm navi10_i2c_algo = { .functionality = navi10_i2c_func, }; -static bool navi10_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (navi10_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2488,9 +2477,6 @@ static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter * static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!navi10_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f64a1be94cb8c..f373e2d0d31ca 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -2630,22 +2630,11 @@ static const struct i2c_algorithm sienna_cichlid_i2c_algo = { .functionality = sienna_cichlid_i2c_func, }; -static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (sienna_cichlid_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2661,9 +2650,6 @@ static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_a static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!sienna_cichlid_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } -- GitLab From 37912e963dadcc831dd2a766780ff0b8738773d8 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 17:38:29 -0400 Subject: [PATCH 0224/1494] drm/amdgpu: handle bo size 0 in amdgpu_bo_create_kernel_at (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just return early to match other bo_create functions. v2: check if the bo_ptr is NULL rather than checking the size. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> (v1) Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5ac7b55614750..a3cf38d25fc15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -374,6 +374,9 @@ int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev, if (r) return r; + if ((*bo_ptr) == NULL) + return 0; + /* * Remove the original mem node and create a new one at the request * position. -- GitLab From adb5be812251cbcae364e5016ad71c955faedbd8 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 13:57:20 -0400 Subject: [PATCH 0225/1494] drm/amdgpu: use create_at for the stolen pre-OS buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should be functionally the same since nothing else is allocated at that point, but let's be exact. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 605d266754f69..a188216bccc2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1979,10 +1979,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel(adev, adev->gmc.stolen_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->stolen_vga_memory, - NULL, &stolen_vga_buf); + r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_size, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->stolen_vga_memory, + &stolen_vga_buf); if (r) return r; -- GitLab From 81b54fb7a2c038e8eaae7036ad973e913463c34d Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 14:10:46 -0400 Subject: [PATCH 0226/1494] drm/amdgpu: use a define for the memory size of the vga emulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than open coding it everywhere. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 ++-- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 75631b3396a3c..5d605e4733192 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -214,6 +214,8 @@ extern int amdgpu_num_kcq; #define AMDGPUFB_CONN_LIMIT 4 #define AMDGPU_BIOS_NUM_SCRATCH 16 +#define AMDGPU_VBIOS_VGA_ALLOCATION (9 * 1024 * 1024) /* reserve 8MB for vga emulator and 1 MB for FB */ + /* hard reset data */ #define AMDGPU_ASIC_RESET_DATA 0x39d5e86b diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index dd91a93de62ae..943773e0c3c3d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -747,7 +747,7 @@ static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport; u32 pitch; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 538e7ee35cdf2..4de996868d326 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -805,7 +805,7 @@ static unsigned gmc_v6_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 0f8e8aff9114c..4113f2d33b75f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -970,7 +970,7 @@ static unsigned gmc_v7_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index abe64010f0d57..f29ff9afcc108 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1087,7 +1087,7 @@ static unsigned gmc_v8_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c5f94bab4a010..ac15d7678d245 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1077,11 +1077,11 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) * Check related code in gmc_v9_0_sw_fini * */ if (gmc_v9_0_keep_stolen_memory(adev)) - return 9 * 1024 * 1024; + return AMDGPU_VBIOS_VGA_ALLOCATION; d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport; -- GitLab From fcbc92e2e1c38b3626aa871caa5124d5341f85bf Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 17:46:00 -0400 Subject: [PATCH 0227/1494] drm/amdgpu: move stolen vga bo from amdgpu to amdgpu.gmc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since that is where we store the other data related to the stolen vga memory. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5d605e4733192..af51160bcf601 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -769,7 +769,6 @@ struct amdgpu_device { bool is_atom_fw; uint8_t *bios; uint32_t bios_size; - struct amdgpu_bo *stolen_vga_memory; uint32_t bios_scratch_reg_offset; uint32_t bios_scratch[AMDGPU_BIOS_NUM_SCRATCH]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 9d58c56f6cfc4..ddb64be670c20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -213,7 +213,8 @@ struct amdgpu_gmc { uint8_t vram_vendor; uint32_t srbm_soft_reset; bool prt_warning; - uint64_t stolen_size; + uint64_t stolen_vga_size; + struct amdgpu_bo *stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a188216bccc2c..39781127d0599 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1979,9 +1979,9 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_size, + r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->stolen_vga_memory, + &adev->gmc.stolen_vga_memory, &stolen_vga_buf); if (r) return r; @@ -2043,7 +2043,7 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { void *stolen_vga_buf; /* return the VGA stolen memory (if any) back to VRAM */ - amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 943773e0c3c3d..187c108f2fde4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -860,7 +860,7 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v10_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v10_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 4de996868d326..28ddb41a78c8d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -862,7 +862,7 @@ static int gmc_v6_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v6_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v6_0_get_vbios_fb_size(adev); r = amdgpu_bo_init(adev); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 4113f2d33b75f..8b8ecbb99d84d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1035,7 +1035,7 @@ static int gmc_v7_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v7_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v7_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index f29ff9afcc108..8e3763ec268fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1160,7 +1160,7 @@ static int gmc_v8_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v8_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v8_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index ac15d7678d245..b66c60680dba9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1243,7 +1243,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v9_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1282,7 +1282,7 @@ static int gmc_v9_0_sw_fini(void *handle) amdgpu_vm_manager_fini(adev); if (gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); -- GitLab From 5db62dc8d4f35dc11054f24ba2c86f6c3422918a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 17:55:30 -0400 Subject: [PATCH 0228/1494] drm/amdgpu: move keep stolen memory check into gmc core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than leaving this as a gmc v9 specific hack. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 ++++++++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 11 +++-------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index ddb64be670c20..0cf18f01e67a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,6 +215,7 @@ struct amdgpu_gmc { bool prt_warning; uint64_t stolen_vga_size; struct amdgpu_bo *stolen_vga_memory; + bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 39781127d0599..fd61769202b39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2042,8 +2042,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) void amdgpu_ttm_late_init(struct amdgpu_device *adev) { void *stolen_vga_buf; + /* return the VGA stolen memory (if any) back to VRAM */ - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + if (!adev->gmc.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); } /** @@ -2051,10 +2053,15 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) */ void amdgpu_ttm_fini(struct amdgpu_device *adev) { + void *stolen_vga_buf; + if (!adev->mman.initialized) return; amdgpu_ttm_training_reserve_vram_fini(adev); + /* return the stolen vga memory back to VRAM */ + if (adev->gmc.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index b66c60680dba9..c5d2e4390fbab 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -932,8 +932,7 @@ static int gmc_v9_0_late_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int r; - if (!gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_late_init(adev); + amdgpu_bo_late_init(adev); r = amdgpu_gmc_allocate_vm_inv_eng(adev); if (r) @@ -1076,7 +1075,7 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) * TODO Remove once GART corruption is resolved * Check related code in gmc_v9_0_sw_fini * */ - if (gmc_v9_0_keep_stolen_memory(adev)) + if (adev->gmc.keep_stolen_vga_memory) return AMDGPU_VBIOS_VGA_ALLOCATION; d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); @@ -1243,6 +1242,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; + adev->gmc.keep_stolen_vga_memory = gmc_v9_0_keep_stolen_memory(adev); adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); /* Memory manager */ @@ -1275,15 +1275,10 @@ static int gmc_v9_0_sw_init(void *handle) static int gmc_v9_0_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - void *stolen_vga_buf; amdgpu_gmc_ras_fini(adev); amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); - - if (gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); - amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); amdgpu_gart_fini(adev); -- GitLab From 0635019412eb2db60fb1d34be8ed8225a0c70bd9 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:05:11 -0400 Subject: [PATCH 0229/1494] drm/amdgpu: add support for extended stolen vga memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow us to split the allocation for systems where we have to keep the stolen memory around to avoid S3 issues. This way we don't waste as much memory and still avoid any screen artifacts during the bios to driver transition. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 0cf18f01e67a4..8f4af955d72ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,6 +215,8 @@ struct amdgpu_gmc { bool prt_warning; uint64_t stolen_vga_size; struct amdgpu_bo *stolen_vga_memory; + uint64_t stolen_extended_size; + struct amdgpu_bo *stolen_extended_memory; bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fd61769202b39..ec975251b171c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1915,7 +1915,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) uint64_t gtt_size; int r; u64 vis_vram_limit; - void *stolen_vga_buf; + void *stolen_vga_buf, *stolen_extended_buf; mutex_init(&adev->mman.gtt_window_lock); @@ -1985,6 +1985,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) &stolen_vga_buf); if (r) return r; + r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, + adev->gmc.stolen_extended_size, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gmc.stolen_extended_memory, + &stolen_extended_buf); + if (r) + return r; DRM_INFO("amdgpu: %uM of VRAM memory ready\n", (unsigned) (adev->gmc.real_vram_size / (1024 * 1024))); @@ -2041,11 +2048,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) */ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { - void *stolen_vga_buf; + void *stolen_vga_buf, *stolen_extended_buf; /* return the VGA stolen memory (if any) back to VRAM */ if (!adev->gmc.keep_stolen_vga_memory) amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, + &stolen_extended_buf); } /** -- GitLab From dd285c5df9523117e9941f9d3c56d7ed73c4ed4d Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 15:04:52 -0400 Subject: [PATCH 0230/1494] drm/amdgpu/gmc: add new helper to get the FB size used by pre-OS console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a new gmc callback to get the size reserved by the pre-OS console and provides a helper function for use by gmc IP drivers. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 43 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 5 +++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 21d2c8543f852..fc9e18aaa76e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -27,6 +27,7 @@ #include <linux/io-64-nonatomic-lo-hi.h> #include "amdgpu.h" +#include "amdgpu_gmc.h" #include "amdgpu_ras.h" #include "amdgpu_xgmi.h" @@ -431,3 +432,45 @@ void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, WREG32(reg, tmp); } } + +void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) +{ + unsigned size; + + /* + * TODO: + * Currently there is a bug where some memory client outside + * of the driver writes to first 8M of VRAM on S3 resume, + * this overrides GART which by default gets placed in first 8M and + * causes VM_FAULTS once GTT is accessed. + * Keep the stolen memory reservation until the while this is not solved. + */ + switch (adev->asic_type) { + case CHIP_VEGA10: + case CHIP_RAVEN: + case CHIP_ARCTURUS: + case CHIP_RENOIR: + adev->gmc.keep_stolen_vga_memory = true; + break; + default: + adev->gmc.keep_stolen_vga_memory = false; + break; + } + + if (!amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_DCE)) + size = 0; + else + size = amdgpu_gmc_get_vbios_fb_size(adev); + + /* set to 0 if the pre-OS buffer uses up most of vram */ + if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) + size = 0; + + if (size > AMDGPU_VBIOS_VGA_ALLOCATION) { + adev->gmc.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; + adev->gmc.stolen_extended_size = size - adev->gmc.stolen_vga_size; + } else { + adev->gmc.stolen_vga_size = size; + adev->gmc.stolen_extended_size = 0; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 8f4af955d72ce..c2a85d0b15467 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -131,6 +131,8 @@ struct amdgpu_gmc_funcs { void (*get_vm_pte)(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping, uint64_t *flags); + /* get the amount of memory used by the vbios for pre-OS console */ + unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev); }; struct amdgpu_xgmi { @@ -253,6 +255,7 @@ struct amdgpu_gmc { #define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags)) #define amdgpu_gmc_get_vm_pde(adev, level, dst, flags) (adev)->gmc.gmc_funcs->get_vm_pde((adev), (level), (dst), (flags)) #define amdgpu_gmc_get_vm_pte(adev, mapping, flags) (adev)->gmc.gmc_funcs->get_vm_pte((adev), (mapping), (flags)) +#define amdgpu_gmc_get_vbios_fb_size(adev) (adev)->gmc.gmc_funcs->get_vbios_fb_size((adev)) /** * amdgpu_gmc_vram_full_visible - Check if full VRAM is visible through the BAR @@ -307,4 +310,6 @@ extern void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, bool enable); +void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev); + #endif -- GitLab From 422fe8d27dcf180caf1e3755b9bf7c1b4de5f56a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:27:46 -0400 Subject: [PATCH 0231/1494] drm/amdgpu/gmc6: switch to using amdgpu_gmc_get_vbios_allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new helper centralizes the logic in one place. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 28ddb41a78c8d..95a9117e95640 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -812,9 +812,6 @@ static unsigned gmc_v6_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; return size; } @@ -862,7 +859,7 @@ static int gmc_v6_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v6_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); r = amdgpu_bo_init(adev); if (r) @@ -1136,6 +1133,7 @@ static const struct amdgpu_gmc_funcs gmc_v6_0_gmc_funcs = { .set_prt = gmc_v6_0_set_prt, .get_vm_pde = gmc_v6_0_get_vm_pde, .get_vm_pte = gmc_v6_0_get_vm_pte, + .get_vbios_fb_size = gmc_v6_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v6_0_irq_funcs = { -- GitLab From 71755699b564bf9b03a0d036ca94164c3b5691c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:29:20 -0400 Subject: [PATCH 0232/1494] drm/amdgpu/gmc7: switch to using amdgpu_gmc_get_vbios_allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new helper centralizes the logic in one place. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 8b8ecbb99d84d..80c146df338aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -977,9 +977,7 @@ static unsigned gmc_v7_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; + return size; } @@ -1035,7 +1033,7 @@ static int gmc_v7_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v7_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1372,7 +1370,8 @@ static const struct amdgpu_gmc_funcs gmc_v7_0_gmc_funcs = { .emit_pasid_mapping = gmc_v7_0_emit_pasid_mapping, .set_prt = gmc_v7_0_set_prt, .get_vm_pde = gmc_v7_0_get_vm_pde, - .get_vm_pte = gmc_v7_0_get_vm_pte + .get_vm_pte = gmc_v7_0_get_vm_pte, + .get_vbios_fb_size = gmc_v7_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v7_0_irq_funcs = { -- GitLab From 3853626d2cf3eca3397bc5ffbd4bf2bf0f6eff8c Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:29:39 -0400 Subject: [PATCH 0233/1494] drm/amdgpu/gmc8: switch to using amdgpu_gmc_get_vbios_allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new helper centralizes the logic in one place. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 8e3763ec268fa..9ab65ca7df777 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1094,9 +1094,7 @@ static unsigned gmc_v8_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; + return size; } @@ -1160,7 +1158,7 @@ static int gmc_v8_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v8_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1739,7 +1737,8 @@ static const struct amdgpu_gmc_funcs gmc_v8_0_gmc_funcs = { .emit_pasid_mapping = gmc_v8_0_emit_pasid_mapping, .set_prt = gmc_v8_0_set_prt, .get_vm_pde = gmc_v8_0_get_vm_pde, - .get_vm_pte = gmc_v8_0_get_vm_pte + .get_vm_pte = gmc_v8_0_get_vm_pte, + .get_vbios_fb_size = gmc_v8_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v8_0_irq_funcs = { -- GitLab From 7b885f0eb4a5185c0ca73d9f82514a611e5e6258 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:29:55 -0400 Subject: [PATCH 0234/1494] drm/amdgpu/gmc9: switch to using amdgpu_gmc_get_vbios_allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new helper centralizes the logic in one place. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 112 +++++++++----------------- 1 file changed, 38 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c5d2e4390fbab..65488ddc34c3d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -827,6 +827,41 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev, *flags |= AMDGPU_PTE_SNOOPED; } +static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) +{ + u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); + unsigned size; + + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { + u32 viewport; + + switch (adev->asic_type) { + case CHIP_RAVEN: + case CHIP_RENOIR: + viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * + REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * + 4); + break; + case CHIP_VEGA10: + case CHIP_VEGA12: + case CHIP_VEGA20: + default: + viewport = RREG32_SOC15(DCE, 0, mmSCL0_VIEWPORT_SIZE); + size = (REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT) * + REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH) * + 4); + break; + } + } + + return size; +} + static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = { .flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb, .flush_gpu_tlb_pasid = gmc_v9_0_flush_gpu_tlb_pasid, @@ -834,7 +869,8 @@ static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = { .emit_pasid_mapping = gmc_v9_0_emit_pasid_mapping, .map_mtype = gmc_v9_0_map_mtype, .get_vm_pde = gmc_v9_0_get_vm_pde, - .get_vm_pte = gmc_v9_0_get_vm_pte + .get_vm_pte = gmc_v9_0_get_vm_pte, + .get_vbios_fb_size = gmc_v9_0_get_vbios_fb_size, }; static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev) @@ -902,31 +938,6 @@ static int gmc_v9_0_early_init(void *handle) return 0; } -static bool gmc_v9_0_keep_stolen_memory(struct amdgpu_device *adev) -{ - - /* - * TODO: - * Currently there is a bug where some memory client outside - * of the driver writes to first 8M of VRAM on S3 resume, - * this overrides GART which by default gets placed in first 8M and - * causes VM_FAULTS once GTT is accessed. - * Keep the stolen memory reservation until the while this is not solved. - * Also check code in gmc_v9_0_get_vbios_fb_size and gmc_v9_0_late_init - */ - switch (adev->asic_type) { - case CHIP_VEGA10: - case CHIP_RAVEN: - case CHIP_ARCTURUS: - case CHIP_RENOIR: - return true; - case CHIP_VEGA12: - case CHIP_VEGA20: - default: - return false; - } -} - static int gmc_v9_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1066,52 +1077,6 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } -static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) -{ - u32 d1vga_control; - unsigned size; - - /* - * TODO Remove once GART corruption is resolved - * Check related code in gmc_v9_0_sw_fini - * */ - if (adev->gmc.keep_stolen_vga_memory) - return AMDGPU_VBIOS_VGA_ALLOCATION; - - d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); - if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = AMDGPU_VBIOS_VGA_ALLOCATION; - } else { - u32 viewport; - - switch (adev->asic_type) { - case CHIP_RAVEN: - case CHIP_RENOIR: - viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); - size = (REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * - REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * - 4); - break; - case CHIP_VEGA10: - case CHIP_VEGA12: - case CHIP_VEGA20: - default: - viewport = RREG32_SOC15(DCE, 0, mmSCL0_VIEWPORT_SIZE); - size = (REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT) * - REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH) * - 4); - break; - } - } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; - - return size; -} - static int gmc_v9_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -1242,8 +1207,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; - adev->gmc.keep_stolen_vga_memory = gmc_v9_0_keep_stolen_memory(adev); - adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); -- GitLab From 7348c20a4e12e8f6ccf63a3deaae898bd72cd2e9 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:30:14 -0400 Subject: [PATCH 0235/1494] drm/amdgpu/gmc10: switch to using amdgpu_gmc_get_vbios_allocations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new helper centralizes the logic in one place. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 57 +++++++++++--------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 187c108f2fde4..f0f50e785dcd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -572,6 +572,28 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev, } } +static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) +{ + u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); + unsigned size; + + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { + u32 viewport; + u32 pitch; + + viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * + REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) * + 4); + } + + return size; +} + static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = { .flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb, .flush_gpu_tlb_pasid = gmc_v10_0_flush_gpu_tlb_pasid, @@ -579,7 +601,8 @@ static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = { .emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping, .map_mtype = gmc_v10_0_map_mtype, .get_vm_pde = gmc_v10_0_get_vm_pde, - .get_vm_pte = gmc_v10_0_get_vm_pte + .get_vm_pte = gmc_v10_0_get_vm_pte, + .get_vbios_fb_size = gmc_v10_0_get_vbios_fb_size, }; static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev) @@ -741,36 +764,6 @@ static int gmc_v10_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } -static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) -{ - u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); - unsigned size; - - if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = AMDGPU_VBIOS_VGA_ALLOCATION; - } else { - u32 viewport; - u32 pitch; - - viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); - pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH); - size = (REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * - REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) * - 4); - } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) { - DRM_ERROR("Warning: pre-OS buffer uses most of vram, \ - be aware of gart table overwrite\n"); - return 0; - } - - return size; -} - - - static int gmc_v10_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -860,7 +853,7 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v10_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); -- GitLab From 14b18937cb60a4970c52cd954a643ed9c09d2eaf Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 18:34:50 -0400 Subject: [PATCH 0236/1494] drm/amdgpu: drop the CPU pointers for the stolen vga bos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We never use them. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ec975251b171c..3df9d5a537413 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1915,7 +1915,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) uint64_t gtt_size; int r; u64 vis_vram_limit; - void *stolen_vga_buf, *stolen_extended_buf; mutex_init(&adev->mman.gtt_window_lock); @@ -1982,14 +1981,14 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, &adev->gmc.stolen_vga_memory, - &stolen_vga_buf); + NULL); if (r) return r; r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, adev->gmc.stolen_extended_size, AMDGPU_GEM_DOMAIN_VRAM, &adev->gmc.stolen_extended_memory, - &stolen_extended_buf); + NULL); if (r) return r; @@ -2048,13 +2047,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) */ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { - void *stolen_vga_buf, *stolen_extended_buf; - /* return the VGA stolen memory (if any) back to VRAM */ if (!adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); - amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, - &stolen_extended_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, NULL); } /** @@ -2062,15 +2058,13 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) */ void amdgpu_ttm_fini(struct amdgpu_device *adev) { - void *stolen_vga_buf; - if (!adev->mman.initialized) return; amdgpu_ttm_training_reserve_vram_fini(adev); /* return the stolen vga memory back to VRAM */ if (adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); -- GitLab From 7438ae6e522f1c4df5f067fd82aaa4e82917b7a8 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 28 Jul 2020 15:35:56 -0400 Subject: [PATCH 0237/1494] drm/amdgpu/gmc: disable keep_stolen_vga_memory on arcturus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I suspect the only reason this was set was to avoid touching the display related registers on arcturus. Someone should double check this on arcturus with S3. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index fc9e18aaa76e1..0bd7b3797534b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -448,7 +448,6 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_VEGA10: case CHIP_RAVEN: - case CHIP_ARCTURUS: case CHIP_RENOIR: adev->gmc.keep_stolen_vga_memory = true; break; -- GitLab From cacbbe7c00655985aec37e5e4d02c66d7a1732c9 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 29 Jul 2020 12:53:56 -0400 Subject: [PATCH 0238/1494] drm/amdgpu: move stolen memory from gmc to mman MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's more related to memory management than memory controller. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 5 ----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 ++++++ 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 0bd7b3797534b..213ef090bb0e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -449,10 +449,10 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) case CHIP_VEGA10: case CHIP_RAVEN: case CHIP_RENOIR: - adev->gmc.keep_stolen_vga_memory = true; + adev->mman.keep_stolen_vga_memory = true; break; default: - adev->gmc.keep_stolen_vga_memory = false; + adev->mman.keep_stolen_vga_memory = false; break; } @@ -466,10 +466,10 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) size = 0; if (size > AMDGPU_VBIOS_VGA_ALLOCATION) { - adev->gmc.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; - adev->gmc.stolen_extended_size = size - adev->gmc.stolen_vga_size; + adev->mman.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; + adev->mman.stolen_extended_size = size - adev->mman.stolen_vga_size; } else { - adev->gmc.stolen_vga_size = size; - adev->gmc.stolen_extended_size = 0; + adev->mman.stolen_vga_size = size; + adev->mman.stolen_extended_size = 0; } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index c2a85d0b15467..d61bbde4c7d2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,11 +215,6 @@ struct amdgpu_gmc { uint8_t vram_vendor; uint32_t srbm_soft_reset; bool prt_warning; - uint64_t stolen_vga_size; - struct amdgpu_bo *stolen_vga_memory; - uint64_t stolen_extended_size; - struct amdgpu_bo *stolen_extended_memory; - bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3df9d5a537413..cc1a5b2876b68 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1978,16 +1978,16 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, + r = amdgpu_bo_create_kernel_at(adev, 0, adev->mman.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->gmc.stolen_vga_memory, + &adev->mman.stolen_vga_memory, NULL); if (r) return r; - r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, - adev->gmc.stolen_extended_size, + r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size, + adev->mman.stolen_extended_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->gmc.stolen_extended_memory, + &adev->mman.stolen_extended_memory, NULL); if (r) return r; @@ -2048,9 +2048,9 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) void amdgpu_ttm_late_init(struct amdgpu_device *adev) { /* return the VGA stolen memory (if any) back to VRAM */ - if (!adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); - amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, NULL); + if (!adev->mman.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL); } /** @@ -2063,8 +2063,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_ttm_training_reserve_vram_fini(adev); /* return the stolen vga memory back to VRAM */ - if (adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); + if (adev->mman.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 17c8d0d7bcc37..98af87f38f3e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -59,6 +59,12 @@ struct amdgpu_mman { struct mutex gtt_window_lock; /* Scheduler entity for buffer moves */ struct drm_sched_entity entity; + + uint64_t stolen_vga_size; + struct amdgpu_bo *stolen_vga_memory; + uint64_t stolen_extended_size; + struct amdgpu_bo *stolen_extended_memory; + bool keep_stolen_vga_memory; }; struct amdgpu_copy_mem { -- GitLab From 72de33f8f7ba0f43a3117efbee6d08226ac31ecb Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 29 Jul 2020 13:02:25 -0400 Subject: [PATCH 0239/1494] drm/amdgpu: move IP discovery data to mman MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's related to the memory manager so move it there. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 -- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 54 +++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 5 ++ 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index af51160bcf601..7464d6f9171d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -920,11 +920,6 @@ struct amdgpu_device { /* display related functionality */ struct amdgpu_display_manager dm; - /* discovery */ - uint8_t *discovery_bin; - uint32_t discovery_tmr_size; - struct amdgpu_bo *discovery_memory; - /* mes */ bool enable_mes; struct amdgpu_mes mes; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 79b0da3e86391..b72aeeb0a226e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1568,7 +1568,7 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) adev->firmware.gpu_info_fw = NULL; - if (adev->discovery_bin) { + if (adev->mman.discovery_bin) { amdgpu_discovery_get_gfx_info(adev); /* @@ -3428,7 +3428,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes); if (IS_ENABLED(CONFIG_PERF_EVENTS)) amdgpu_pmu_fini(adev); - if (adev->discovery_bin) + if (adev->mman.discovery_bin) amdgpu_discovery_fini(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index a50ff2306504c..bfb95143ba5e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -136,7 +136,7 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET; amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, - adev->discovery_tmr_size, false); + adev->mman.discovery_tmr_size, false); return 0; } @@ -168,18 +168,18 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) uint16_t checksum; int r; - adev->discovery_tmr_size = DISCOVERY_TMR_SIZE; - adev->discovery_bin = kzalloc(adev->discovery_tmr_size, GFP_KERNEL); - if (!adev->discovery_bin) + adev->mman.discovery_tmr_size = DISCOVERY_TMR_SIZE; + adev->mman.discovery_bin = kzalloc(adev->mman.discovery_tmr_size, GFP_KERNEL); + if (!adev->mman.discovery_bin) return -ENOMEM; - r = amdgpu_discovery_read_binary(adev, adev->discovery_bin); + r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin); if (r) { DRM_ERROR("failed to read ip discovery binary\n"); goto out; } - bhdr = (struct binary_header *)adev->discovery_bin; + bhdr = (struct binary_header *)adev->mman.discovery_bin; if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) { DRM_ERROR("invalid ip discovery binary signature\n"); @@ -192,7 +192,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) size = bhdr->binary_size - offset; checksum = bhdr->binary_checksum; - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, size, checksum)) { DRM_ERROR("invalid ip discovery binary checksum\n"); r = -EINVAL; @@ -202,7 +202,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) info = &bhdr->table_list[IP_DISCOVERY]; offset = le16_to_cpu(info->offset); checksum = le16_to_cpu(info->checksum); - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + offset); + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset); if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) { DRM_ERROR("invalid ip discovery data table signature\n"); @@ -210,7 +210,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) goto out; } - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, ihdr->size, checksum)) { DRM_ERROR("invalid ip discovery data table checksum\n"); r = -EINVAL; @@ -220,9 +220,9 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) info = &bhdr->table_list[GC]; offset = le16_to_cpu(info->offset); checksum = le16_to_cpu(info->checksum); - ghdr = (struct gpu_info_header *)(adev->discovery_bin + offset); + ghdr = (struct gpu_info_header *)(adev->mman.discovery_bin + offset); - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, ghdr->size, checksum)) { DRM_ERROR("invalid gc data table checksum\n"); r = -EINVAL; @@ -232,16 +232,16 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) return 0; out: - kfree(adev->discovery_bin); - adev->discovery_bin = NULL; + kfree(adev->mman.discovery_bin); + adev->mman.discovery_bin = NULL; return r; } void amdgpu_discovery_fini(struct amdgpu_device *adev) { - kfree(adev->discovery_bin); - adev->discovery_bin = NULL; + kfree(adev->mman.discovery_bin); + adev->mman.discovery_bin = NULL; } int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) @@ -265,8 +265,8 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) return r; } - bhdr = (struct binary_header *)adev->discovery_bin; - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset)); num_dies = le16_to_cpu(ihdr->num_dies); @@ -274,7 +274,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) for (i = 0; i < num_dies; i++) { die_offset = le16_to_cpu(ihdr->die_info[i].die_offset); - dhdr = (struct die_header *)(adev->discovery_bin + die_offset); + dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset); num_ips = le16_to_cpu(dhdr->num_ips); ip_offset = die_offset + sizeof(*dhdr); @@ -288,7 +288,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) le16_to_cpu(dhdr->die_id), num_ips); for (j = 0; j < num_ips; j++) { - ip = (struct ip *)(adev->discovery_bin + ip_offset); + ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); num_base_address = ip->num_base_address; DRM_DEBUG("%s(%d) #%d v%d.%d.%d:\n", @@ -337,24 +337,24 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, uint16_t num_ips; int i, j; - if (!adev->discovery_bin) { + if (!adev->mman.discovery_bin) { DRM_ERROR("ip discovery uninitialized\n"); return -EINVAL; } - bhdr = (struct binary_header *)adev->discovery_bin; - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset)); num_dies = le16_to_cpu(ihdr->num_dies); for (i = 0; i < num_dies; i++) { die_offset = le16_to_cpu(ihdr->die_info[i].die_offset); - dhdr = (struct die_header *)(adev->discovery_bin + die_offset); + dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset); num_ips = le16_to_cpu(dhdr->num_ips); ip_offset = die_offset + sizeof(*dhdr); for (j = 0; j < num_ips; j++) { - ip = (struct ip *)(adev->discovery_bin + ip_offset); + ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); if (le16_to_cpu(ip->hw_id) == hw_id) { if (major) @@ -377,13 +377,13 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) struct binary_header *bhdr; struct gc_info_v1_0 *gc_info; - if (!adev->discovery_bin) { + if (!adev->mman.discovery_bin) { DRM_ERROR("ip discovery uninitialized\n"); return -EINVAL; } - bhdr = (struct binary_header *)adev->discovery_bin; - gc_info = (struct gc_info_v1_0 *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + gc_info = (struct gc_info_v1_0 *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[GC].offset)); adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->gc_num_se); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index cc1a5b2876b68..ea9b5b39f6400 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1825,7 +1825,7 @@ static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev) memset(ctx, 0, sizeof(*ctx)); ctx->c2p_train_data_offset = - ALIGN((adev->gmc.mc_vram_size - adev->discovery_tmr_size - SZ_1M), SZ_1M); + ALIGN((adev->gmc.mc_vram_size - adev->mman.discovery_tmr_size - SZ_1M), SZ_1M); ctx->p2c_train_data_offset = (adev->gmc.mc_vram_size - GDDR6_MEM_TRAINING_OFFSET); ctx->train_data_size = @@ -1864,10 +1864,10 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev) * Otherwise, fallback to legacy approach to check and reserve tmr block for ip * discovery data and G6 memory training data respectively */ - adev->discovery_tmr_size = + adev->mman.discovery_tmr_size = amdgpu_atomfirmware_get_fw_reserved_fb_size(adev); - if (!adev->discovery_tmr_size) - adev->discovery_tmr_size = DISCOVERY_TMR_OFFSET; + if (!adev->mman.discovery_tmr_size) + adev->mman.discovery_tmr_size = DISCOVERY_TMR_OFFSET; if (mem_train_support) { /* reserve vram for mem train according to TMR location */ @@ -1887,14 +1887,14 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev) } ret = amdgpu_bo_create_kernel_at(adev, - adev->gmc.real_vram_size - adev->discovery_tmr_size, - adev->discovery_tmr_size, + adev->gmc.real_vram_size - adev->mman.discovery_tmr_size, + adev->mman.discovery_tmr_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->discovery_memory, + &adev->mman.discovery_memory, NULL); if (ret) { DRM_ERROR("alloc tmr failed(%d)!\n", ret); - amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL); return ret; } @@ -1968,7 +1968,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * If IP discovery enabled, a block of memory should be * reserved for IP discovey. */ - if (adev->discovery_bin) { + if (adev->mman.discovery_bin) { r = amdgpu_ttm_reserve_tmr(adev); if (r) return r; @@ -2066,7 +2066,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) if (adev->mman.keep_stolen_vga_memory) amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ - amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); if (adev->mman.aper_base_kaddr) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 98af87f38f3e7..6d7b83d967ce2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -65,6 +65,11 @@ struct amdgpu_mman { uint64_t stolen_extended_size; struct amdgpu_bo *stolen_extended_memory; bool keep_stolen_vga_memory; + + /* discovery */ + uint8_t *discovery_bin; + uint32_t discovery_tmr_size; + struct amdgpu_bo *discovery_memory; }; struct amdgpu_copy_mem { -- GitLab From 87ded5caeec3c61327e133baba1bce691ecd2ded Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 29 Jul 2020 13:14:17 -0400 Subject: [PATCH 0240/1494] drm/amdgpu: move vram usage by vbios to mman (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's related to the memory manager so move it there. v2: inline the structure Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 12 ----------- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 4 ++-- .../gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 +++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 6 +++--- 6 files changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7464d6f9171d8..a5ea70697fba9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -651,16 +651,6 @@ struct amdgpu_atcs { struct amdgpu_atcs_functions functions; }; -/* - * Firmware VRAM reservation - */ -struct amdgpu_fw_vram_usage { - u64 start_offset; - u64 size; - struct amdgpu_bo *reserved_bo; - void *va; -}; - /* * CGS */ @@ -944,8 +934,6 @@ struct amdgpu_device { struct delayed_work delayed_init_work; struct amdgpu_virt virt; - /* firmware VRAM reservation */ - struct amdgpu_fw_vram_usage fw_vram_usage; /* link all shadow bo */ struct list_head shadow_list; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 29f767e026e49..e33f63712b46f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1786,9 +1786,9 @@ static int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { /* Firmware request VRAM reservation for SR-IOV */ - adev->fw_vram_usage.start_offset = (start_addr & + adev->mman.fw_vram_usage_start_offset = (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; - adev->fw_vram_usage.size = size << 10; + adev->mman.fw_vram_usage_size = size << 10; /* Use the default scratch size */ usage_bytes = 0; } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 1279053324f99..17c010d0431fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -89,9 +89,9 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { /* Firmware request VRAM reservation for SR-IOV */ - adev->fw_vram_usage.start_offset = (start_addr & + adev->mman.fw_vram_usage_start_offset = (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; - adev->fw_vram_usage.size = size << 10; + adev->mman.fw_vram_usage_size = size << 10; /* Use the default scratch size */ usage_bytes = 0; } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ea9b5b39f6400..c7421aa32946c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1766,8 +1766,8 @@ static struct ttm_bo_driver amdgpu_bo_driver = { */ static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev) { - amdgpu_bo_free_kernel(&adev->fw_vram_usage.reserved_bo, - NULL, &adev->fw_vram_usage.va); + amdgpu_bo_free_kernel(&adev->mman.fw_vram_usage_reserved_bo, + NULL, &adev->mman.fw_vram_usage_va); } /** @@ -1781,19 +1781,19 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev) { uint64_t vram_size = adev->gmc.visible_vram_size; - adev->fw_vram_usage.va = NULL; - adev->fw_vram_usage.reserved_bo = NULL; + adev->mman.fw_vram_usage_va = NULL; + adev->mman.fw_vram_usage_reserved_bo = NULL; - if (adev->fw_vram_usage.size == 0 || - adev->fw_vram_usage.size > vram_size) + if (adev->mman.fw_vram_usage_size == 0 || + adev->mman.fw_vram_usage_size > vram_size) return 0; return amdgpu_bo_create_kernel_at(adev, - adev->fw_vram_usage.start_offset, - adev->fw_vram_usage.size, + adev->mman.fw_vram_usage_start_offset, + adev->mman.fw_vram_usage_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->fw_vram_usage.reserved_bo, - &adev->fw_vram_usage.va); + &adev->mman.fw_vram_usage_reserved_bo, + &adev->mman.fw_vram_usage_va); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 6d7b83d967ce2..de37ceff0e56b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -70,6 +70,12 @@ struct amdgpu_mman { uint8_t *discovery_bin; uint32_t discovery_tmr_size; struct amdgpu_bo *discovery_memory; + + /* firmware VRAM reservation */ + u64 fw_vram_usage_start_offset; + u64 fw_vram_usage_size; + struct amdgpu_bo *fw_vram_usage_reserved_bo; + void *fw_vram_usage_va; }; struct amdgpu_copy_mem { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 5cae39d35c044..1e211544f2dce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -401,7 +401,7 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev, if (bp_block_size) { bp_cnt = bp_block_size / sizeof(uint64_t); for (bp_idx = 0; bp_idx < bp_cnt; bp_idx++) { - retired_page = *(uint64_t *)(adev->fw_vram_usage.va + + retired_page = *(uint64_t *)(adev->mman.fw_vram_usage_va + bp_block_offset + bp_idx * sizeof(uint64_t)); bp.retired_page = retired_page; @@ -428,10 +428,10 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) adev->virt.fw_reserve.p_pf2vf = NULL; adev->virt.fw_reserve.p_vf2pf = NULL; - if (adev->fw_vram_usage.va != NULL) { + if (adev->mman.fw_vram_usage_va != NULL) { adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *)( - adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); + adev->mman.fw_vram_usage_va + AMDGIM_DATAEXCHANGE_OFFSET); AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); AMDGPU_FW_VRAM_PF2VF_READ(adev, feature_flags, &adev->virt.gim_feature); -- GitLab From 34b0c7795bb4a618a7372547c6628ed8876d02a7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Mon, 3 Aug 2020 17:35:19 +0300 Subject: [PATCH 0241/1494] drm/amd/display: Indent an if statement The if statement wasn't indented so it's confusing. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ca26714c800e6..c6b737dd84255 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -71,7 +71,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) - dc_version = DCE_VERSION_6_0; + dc_version = DCE_VERSION_6_0; else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) dc_version = DCE_VERSION_6_4; else -- GitLab From 25457a1fb76448875013625fdc10ed4e941585b4 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn <rikard.falkeborn@gmail.com> Date: Tue, 4 Aug 2020 22:06:53 +0200 Subject: [PATCH 0242/1494] drm/amd/display: Constify dcn20_res_pool_funcs The only usage of dcn20_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 790baf5526959..991eddd109522 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3320,7 +3320,7 @@ enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_stat return DC_OK; } -static struct resource_funcs dcn20_res_pool_funcs = { +static const struct resource_funcs dcn20_res_pool_funcs = { .destroy = dcn20_destroy_resource_pool, .link_enc_create = dcn20_link_encoder_create, .panel_cntl_create = dcn20_panel_cntl_create, -- GitLab From ea22cc3353eda4b275d394c2369c8ffa87753165 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn <rikard.falkeborn@gmail.com> Date: Tue, 4 Aug 2020 22:06:54 +0200 Subject: [PATCH 0243/1494] drm/amd/display: Constify dcn21_res_pool_funcs The only usage of dcn21_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 88d41a385add8..a828696668bfc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1754,7 +1754,7 @@ enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_stat return result; } -static struct resource_funcs dcn21_res_pool_funcs = { +static const struct resource_funcs dcn21_res_pool_funcs = { .destroy = dcn21_destroy_resource_pool, .link_enc_create = dcn21_link_encoder_create, .panel_cntl_create = dcn21_panel_cntl_create, -- GitLab From cc9fc1b1444f12addc1cf6aa6e653426990f1ad2 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn <rikard.falkeborn@gmail.com> Date: Tue, 4 Aug 2020 22:06:55 +0200 Subject: [PATCH 0244/1494] drm/amd/display: Constify dcn30_res_pool_funcs The only usage of dcn30_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 653a571e366d1..d474a61884454 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2412,7 +2412,7 @@ static void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30); } -static struct resource_funcs dcn30_res_pool_funcs = { +static const struct resource_funcs dcn30_res_pool_funcs = { .destroy = dcn30_destroy_resource_pool, .link_enc_create = dcn30_link_encoder_create, .panel_cntl_create = dcn30_panel_cntl_create, -- GitLab From d3dc135187b92e06019bf504739a8b527a53e740 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Tue, 4 Aug 2020 08:51:58 +0200 Subject: [PATCH 0245/1494] drm/mgag200: Set PCI option register in G200SE models The initial value of the PCI option register got lost while refactoring the driver init code. Restore the setting. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Airlie <airlied@redhat.com> Reported-by: kernel test robot <lkp@intel.com> Fixes: 2021708e0d6e ("drm/mgag200: Initialize PCI registers early during device setup") Cc: Lyude Paul <lyude@redhat.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Emil Velikov <emil.velikov@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804065158.21049-1-tzimmermann@suse.de --- drivers/gpu/drm/mgag200/mgag200_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 5c854bc7dc86f..09170d46aa53b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -74,6 +74,7 @@ static int mgag200_regs_init(struct mga_device *mdev) break; case G200_SE_A: case G200_SE_B: + option = 0x40049120; if (mgag200_has_sgram(mdev)) option |= PCI_MGA_OPTION_HARDPWMSK; option2 = 0x00008000; -- GitLab From 8e1ba47c60bcd325fdd097cd76054639155e5d2e Mon Sep 17 00:00:00 2001 From: Tom Rix <trix@redhat.com> Date: Mon, 20 Jul 2020 12:18:45 -0700 Subject: [PATCH 0246/1494] video: fbdev: pvr2fb: initialize variables clang static analysis reports this repesentative error pvr2fb.c:1049:2: warning: 1st function call argument is an uninitialized value [core.CallAndMessage] if (*cable_arg) ^~~~~~~~~~~~~~~ Problem is that cable_arg depends on the input loop to set the cable_arg[0]. If it does not, then some random value from the stack is used. A similar problem exists for output_arg. So initialize cable_arg and output_arg. Signed-off-by: Tom Rix <trix@redhat.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200720191845.20115-1-trix@redhat.com --- drivers/video/fbdev/pvr2fb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 2d9f69b93392a..f4add36cb5f4d 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -1028,6 +1028,8 @@ static int __init pvr2fb_setup(char *options) if (!options || !*options) return 0; + cable_arg[0] = output_arg[0] = 0; + while ((this_opt = strsep(&options, ","))) { if (!*this_opt) continue; -- GitLab From 56dc01f18d3d002de34f642ce92f730e5d50efa5 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:34 +1000 Subject: [PATCH 0247/1494] drm/vmwgfx: consolidate ttm object creation and populate These two functions has the same code in them, create a common helper function instead. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-2-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 ++ drivers/gpu/drm/vmwgfx/vmwgfx_mob.c | 60 ++-------------------- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 32 ++++++++++++ 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 3596f3923ea35..b7c763713b4ce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1023,6 +1023,10 @@ extern int vmw_bo_map_dma(struct ttm_buffer_object *bo); extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo); extern const struct vmw_sg_table * vmw_bo_sg_table(struct ttm_buffer_object *bo); +extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, + unsigned long bo_size, + struct ttm_buffer_object **bo_p); + extern void vmw_piter_start(struct vmw_piter *viter, const struct vmw_sg_table *vsgt, unsigned long p_offs); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index e8eb42933ca2a..7f95ed6aa2241 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -238,10 +238,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, unsigned long offset; unsigned long bo_size; struct vmw_otable *otables = batch->otables; - struct ttm_operation_ctx ctx = { - .interruptible = false, - .no_wait_gpu = false - }; SVGAOTableType i; int ret; @@ -255,24 +251,9 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, bo_size += otables[i].size; } - ret = ttm_bo_create(&dev_priv->bdev, bo_size, - ttm_bo_type_device, - &vmw_sys_ne_placement, - 0, false, &batch->otable_bo); - - if (unlikely(ret != 0)) - goto out_no_bo; - - ret = ttm_bo_reserve(batch->otable_bo, false, true, NULL); - BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(batch->otable_bo->ttm, &ctx); - if (unlikely(ret != 0)) - goto out_unreserve; - ret = vmw_bo_map_dma(batch->otable_bo); + ret = vmw_bo_create_and_populate(dev_priv, bo_size, &batch->otable_bo); if (unlikely(ret != 0)) - goto out_unreserve; - - ttm_bo_unreserve(batch->otable_bo); + return ret; offset = 0; for (i = 0; i < batch->num_otables; ++i) { @@ -289,8 +270,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, return 0; -out_unreserve: - ttm_bo_unreserve(batch->otable_bo); out_no_setup: for (i = 0; i < batch->num_otables; ++i) { if (batch->otables[i].enabled) @@ -300,7 +279,6 @@ static int vmw_otable_batch_setup(struct vmw_private *dev_priv, ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; -out_no_bo: return ret; } @@ -432,41 +410,9 @@ struct vmw_mob *vmw_mob_create(unsigned long data_pages) static int vmw_mob_pt_populate(struct vmw_private *dev_priv, struct vmw_mob *mob) { - int ret; - struct ttm_operation_ctx ctx = { - .interruptible = false, - .no_wait_gpu = false - }; - BUG_ON(mob->pt_bo != NULL); - ret = ttm_bo_create(&dev_priv->bdev, mob->num_pages * PAGE_SIZE, - ttm_bo_type_device, - &vmw_sys_ne_placement, - 0, false, &mob->pt_bo); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_bo_reserve(mob->pt_bo, false, true, NULL); - - BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(mob->pt_bo->ttm, &ctx); - if (unlikely(ret != 0)) - goto out_unreserve; - ret = vmw_bo_map_dma(mob->pt_bo); - if (unlikely(ret != 0)) - goto out_unreserve; - - ttm_bo_unreserve(mob->pt_bo); - - return 0; - -out_unreserve: - ttm_bo_unreserve(mob->pt_bo); - ttm_bo_put(mob->pt_bo); - mob->pt_bo = NULL; - - return ret; + return vmw_bo_create_and_populate(dev_priv, mob->num_pages * PAGE_SIZE, &mob->pt_bo); } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 0e28978953274..ef41d0c5e3d32 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -819,3 +819,35 @@ struct ttm_bo_driver vmw_bo_driver = { .swap_notify = vmw_swap_notify, .io_mem_reserve = &vmw_ttm_io_mem_reserve, }; + +int vmw_bo_create_and_populate(struct vmw_private *dev_priv, + unsigned long bo_size, + struct ttm_buffer_object **bo_p) +{ + struct ttm_operation_ctx ctx = { + .interruptible = false, + .no_wait_gpu = false + }; + struct ttm_buffer_object *bo; + int ret; + + ret = ttm_bo_create(&dev_priv->bdev, bo_size, + ttm_bo_type_device, + &vmw_sys_ne_placement, + 0, false, &bo); + + if (unlikely(ret != 0)) + return ret; + + ret = ttm_bo_reserve(bo, false, true, NULL); + BUG_ON(ret != 0); + ret = vmw_bo_driver.ttm_tt_populate(bo->ttm, &ctx); + if (likely(ret == 0)) + ret = vmw_bo_map_dma(bo); + + ttm_bo_unreserve(bo); + + if (likely(ret == 0)) + *bo_p = bo; + return ret; +} -- GitLab From a2d6ddc417f14570795eaf191f24ebdeb4084995 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:35 +1000 Subject: [PATCH 0248/1494] drm/vmwgfx: drop bo map/unmap dma functions. The map one was used once, just inline it, and drop them both. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-3-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 46 +++------------------- 2 files changed, 6 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index b7c763713b4ce..65c414f119c03 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1019,8 +1019,6 @@ extern struct ttm_placement vmw_mob_placement; extern struct ttm_placement vmw_mob_ne_placement; extern struct ttm_placement vmw_nonfixed_placement; extern struct ttm_bo_driver vmw_bo_driver; -extern int vmw_bo_map_dma(struct ttm_buffer_object *bo); -extern void vmw_bo_unmap_dma(struct ttm_buffer_object *bo); extern const struct vmw_sg_table * vmw_bo_sg_table(struct ttm_buffer_object *bo); extern int vmw_bo_create_and_populate(struct vmw_private *dev_priv, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index ef41d0c5e3d32..01c81e89ed7a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -519,43 +519,6 @@ static void vmw_ttm_unmap_dma(struct vmw_ttm_tt *vmw_tt) vmw_tt->mapped = false; } - -/** - * vmw_bo_map_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_map_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - * Note that the buffer object must be either pinned or reserved before - * calling this function. - */ -int vmw_bo_map_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - return vmw_ttm_map_dma(vmw_tt); -} - - -/** - * vmw_bo_unmap_dma - Make sure buffer object pages are visible to the device - * - * @bo: Pointer to a struct ttm_buffer_object - * - * Wrapper around vmw_ttm_unmap_dma, that takes a TTM buffer object pointer - * instead of a pointer to a struct vmw_ttm_backend as argument. - */ -void vmw_bo_unmap_dma(struct ttm_buffer_object *bo) -{ - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); - - vmw_ttm_unmap_dma(vmw_tt); -} - - /** * vmw_bo_sg_table - Return a struct vmw_sg_table object for a * TTM buffer object @@ -841,9 +804,12 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, ret = ttm_bo_reserve(bo, false, true, NULL); BUG_ON(ret != 0); - ret = vmw_bo_driver.ttm_tt_populate(bo->ttm, &ctx); - if (likely(ret == 0)) - ret = vmw_bo_map_dma(bo); + ret = vmw_ttm_populate(bo->ttm, &ctx); + if (likely(ret == 0)) { + struct vmw_ttm_tt *vmw_tt = + container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); + ret = vmw_ttm_map_dma(vmw_tt); + } ttm_bo_unreserve(bo); -- GitLab From bd549d35b4be065c10fbff13256c96877a4f8fac Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:36 +1000 Subject: [PATCH 0249/1494] nouveau: use ttm populate mapping functions. (v2) Instead of rolling driver copies of them. v2: cleanup return handling (Ben) Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-4-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 38 ++-------------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5efc572c14ccb..51416086e2f40 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1526,8 +1526,6 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; - int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (ttm->state != tt_unpopulated) @@ -1555,31 +1553,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) return ttm_dma_populate((void *)ttm, dev, ctx); } #endif - - r = ttm_pool_populate(ttm, ctx); - if (r) { - return r; - } - - for (i = 0; i < ttm->num_pages; i++) { - dma_addr_t addr; - - addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE, - DMA_BIDIRECTIONAL); - - if (dma_mapping_error(dev, addr)) { - while (i--) { - dma_unmap_page(dev, ttm_dma->dma_address[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); - ttm_dma->dma_address[i] = 0; - } - ttm_pool_unpopulate(ttm); - return -EFAULT; - } - - ttm_dma->dma_address[i] = addr; - } - return 0; + return ttm_populate_and_map_pages(dev, ttm_dma, ctx); } static void @@ -1588,7 +1562,6 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; struct device *dev; - unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (slave) @@ -1611,14 +1584,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) } #endif - for (i = 0; i < ttm->num_pages; i++) { - if (ttm_dma->dma_address[i]) { - dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE, - DMA_BIDIRECTIONAL); - } - } - - ttm_pool_unpopulate(ttm); + ttm_unmap_and_unpopulate_pages(dev, ttm_dma); } void -- GitLab From 9c4cbb3a66e05270caaec7bea8fd5c04a47e42ac Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:37 +1000 Subject: [PATCH 0250/1494] qxl/ttm: drop the unusued no wait flag to reserve function Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-5-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_cmd.c | 2 +- drivers/gpu/drm/qxl/qxl_ioctl.c | 2 +- drivers/gpu/drm/qxl/qxl_object.c | 4 ++-- drivers/gpu/drm/qxl/qxl_object.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 798f9dd7ad753..54e3c3a974407 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -588,7 +588,7 @@ static int qxl_reap_surf(struct qxl_device *qdev, struct qxl_bo *surf, bool stal { int ret; - ret = qxl_bo_reserve(surf, false); + ret = qxl_bo_reserve(surf); if (ret) return ret; diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 8f605d5cc149f..5cea6eea72abb 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -322,7 +322,7 @@ static int qxl_update_area_ioctl(struct drm_device *dev, void *data, qobj = gem_to_qxl_bo(gobj); - ret = qxl_bo_reserve(qobj, false); + ret = qxl_bo_reserve(qobj); if (ret) goto out; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 80e7a17aaddde..f838b6d689aad 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -284,7 +284,7 @@ int qxl_bo_pin(struct qxl_bo *bo) { int r; - r = qxl_bo_reserve(bo, false); + r = qxl_bo_reserve(bo); if (r) return r; @@ -302,7 +302,7 @@ int qxl_bo_unpin(struct qxl_bo *bo) { int r; - r = qxl_bo_reserve(bo, false); + r = qxl_bo_reserve(bo); if (r) return r; diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h index 21fa81048f4f3..6b434e5ef795a 100644 --- a/drivers/gpu/drm/qxl/qxl_object.h +++ b/drivers/gpu/drm/qxl/qxl_object.h @@ -27,11 +27,11 @@ #include "qxl_drv.h" -static inline int qxl_bo_reserve(struct qxl_bo *bo, bool no_wait) +static inline int qxl_bo_reserve(struct qxl_bo *bo) { int r; - r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL); + r = ttm_bo_reserve(&bo->tbo, true, false, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) { struct drm_device *ddev = bo->tbo.base.dev; -- GitLab From 46bca88bbdd3046db31b8b7e053a909ae79e285b Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:38 +1000 Subject: [PATCH 0251/1494] drm/ttm/amdgpu: consolidate ttm reserve paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the WARN_ON and consolidate the two paths into one. Use the consolidate slowpath in the execbuf utils code. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-6-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 12 +-- include/drm/ttm/ttm_bo_driver.h | 91 ++++------------------ 3 files changed, 20 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index afa5189dba7d0..e01e8903741e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -160,7 +160,7 @@ static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr) struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r; - r = __ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL); + r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) dev_err(adev->dev, "%p reserve failed\n", bo); diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index 1797f04c05345..8a8f1a6a83a61 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -93,7 +93,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, list_for_each_entry(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket); + ret = ttm_bo_reserve(bo, intr, (ticket == NULL), ticket); if (ret == -EALREADY && dups) { struct ttm_validate_buffer *safe = entry; entry = list_prev_entry(entry, head); @@ -119,13 +119,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, ttm_eu_backoff_reservation_reverse(list, entry); if (ret == -EDEADLK) { - if (intr) { - ret = dma_resv_lock_slow_interruptible(bo->base.resv, - ticket); - } else { - dma_resv_lock_slow(bo->base.resv, ticket); - ret = 0; - } + ret = ttm_bo_reserve_slowpath(bo, intr, ticket); } if (!ret && entry->num_shared) @@ -133,8 +127,6 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, entry->num_shared); if (unlikely(ret != 0)) { - if (ret == -EINTR) - ret = -ERESTARTSYS; if (ticket) { ww_acquire_done(ticket); ww_acquire_fini(ticket); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index f76f1332fdc5f..44b4d24e73a23 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -599,29 +599,30 @@ int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible); void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); /** - * __ttm_bo_reserve: + * ttm_bo_reserve: * * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. * @ticket: ticket used to acquire the ww_mutex. * - * Will not remove reserved buffers from the lru lists. - * Otherwise identical to ttm_bo_reserve. + * Locks a buffer object for validation. (Or prevents other processes from + * locking it for validation), while taking a number of measures to prevent + * deadlocks. * * Returns: * -EDEADLK: The reservation may cause a deadlock. * Release all buffer reservations, wait for @bo to become unreserved and - * try again. (only if use_sequence == 1). + * try again. * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by * a signal. Release all buffer reservations and return to user-space. * -EBUSY: The function needed to sleep, but @no_wait was true * -EALREADY: Bo already reserved using @ticket. This error code will only * be returned if @use_ticket is set to true. */ -static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait, - struct ww_acquire_ctx *ticket) +static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, + bool interruptible, bool no_wait, + struct ww_acquire_ctx *ticket) { int ret = 0; @@ -643,59 +644,6 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, return ret; } -/** - * ttm_bo_reserve: - * - * @bo: A pointer to a struct ttm_buffer_object. - * @interruptible: Sleep interruptible if waiting. - * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. - * @ticket: ticket used to acquire the ww_mutex. - * - * Locks a buffer object for validation. (Or prevents other processes from - * locking it for validation) and removes it from lru lists, while taking - * a number of measures to prevent deadlocks. - * - * Deadlocks may occur when two processes try to reserve multiple buffers in - * different order, either by will or as a result of a buffer being evicted - * to make room for a buffer already reserved. (Buffers are reserved before - * they are evicted). The following algorithm prevents such deadlocks from - * occurring: - * Processes attempting to reserve multiple buffers other than for eviction, - * (typically execbuf), should first obtain a unique 32-bit - * validation sequence number, - * and call this function with @use_ticket == 1 and @ticket->stamp == the unique - * sequence number. If upon call of this function, the buffer object is already - * reserved, the validation sequence is checked against the validation - * sequence of the process currently reserving the buffer, - * and if the current validation sequence is greater than that of the process - * holding the reservation, the function returns -EDEADLK. Otherwise it sleeps - * waiting for the buffer to become unreserved, after which it retries - * reserving. - * The caller should, when receiving an -EDEADLK error - * release all its buffer reservations, wait for @bo to become unreserved, and - * then rerun the validation with the same validation sequence. This procedure - * will always guarantee that the process with the lowest validation sequence - * will eventually succeed, preventing both deadlocks and starvation. - * - * Returns: - * -EDEADLK: The reservation may cause a deadlock. - * Release all buffer reservations, wait for @bo to become unreserved and - * try again. (only if use_sequence == 1). - * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by - * a signal. Release all buffer reservations and return to user-space. - * -EBUSY: The function needed to sleep, but @no_wait was true - * -EALREADY: Bo already reserved using @ticket. This error code will only - * be returned if @use_ticket is set to true. - */ -static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait, - struct ww_acquire_ctx *ticket) -{ - WARN_ON(!kref_read(&bo->kref)); - - return __ttm_bo_reserve(bo, interruptible, no_wait, ticket); -} - /** * ttm_bo_reserve_slowpath: * @bo: A pointer to a struct ttm_buffer_object. @@ -710,20 +658,15 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, bool interruptible, struct ww_acquire_ctx *ticket) { - int ret = 0; - - WARN_ON(!kref_read(&bo->kref)); - - if (interruptible) - ret = dma_resv_lock_slow_interruptible(bo->base.resv, - ticket); - else - dma_resv_lock_slow(bo->base.resv, ticket); - - if (ret == -EINTR) - ret = -ERESTARTSYS; - - return ret; + if (interruptible) { + int ret = dma_resv_lock_slow_interruptible(bo->base.resv, + ticket); + if (ret == -EINTR) + ret = -ERESTARTSYS; + return ret; + } + dma_resv_lock_slow(bo->base.resv, ticket); + return 0; } /** -- GitLab From 20784cdf4b8c81359289aff73a89f557c7bc9e76 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:39 +1000 Subject: [PATCH 0252/1494] drm/ttm: use a helper for unlocked moves to the lru tail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pattern was repeated a few times, just make an inline for it. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-7-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++------ drivers/gpu/drm/ttm/ttm_bo_vm.c | 4 +--- include/drm/ttm/ttm_bo_driver.h | 11 ++++++++--- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 6c02a336a587a..c5771a43d8ecd 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1101,9 +1101,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, error: if (bo->mem.mem_type == TTM_PL_SYSTEM && !list_empty(&bo->lru)) { - spin_lock(&ttm_bo_glob.lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail_unlocked(bo); } return ret; @@ -1318,9 +1316,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, return ret; } - spin_lock(&ttm_bo_glob.lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail_unlocked(bo); return ret; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 82b893d4249f5..1e2820b06c6af 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -306,9 +306,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, } if (bo->moving != moving) { - spin_lock(&ttm_bo_glob.lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail_unlocked(bo); } dma_fence_put(moving); } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 44b4d24e73a23..049ebf85712fc 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -669,6 +669,13 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, return 0; } +static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) +{ + spin_lock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail(bo, NULL); + spin_unlock(&ttm_bo_glob.lru_lock); +} + /** * ttm_bo_unreserve * @@ -678,9 +685,7 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, */ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) { - spin_lock(&ttm_bo_glob.lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_bo_move_to_lru_tail_unlocked(bo); dma_resv_unlock(bo->base.resv); } -- GitLab From 5977ffeaf33c7239dd0cc6c8fb4c0dc68aa591d5 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:40 +1000 Subject: [PATCH 0253/1494] drm/vram-helper: remove populate/unpopulate The default path for populate/unpopulate is already this. Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-8-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 5f03c6137ef9e..a93a00966f3ac 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1061,8 +1061,6 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, static struct ttm_bo_driver bo_driver = { .ttm_tt_create = bo_driver_ttm_tt_create, - .ttm_tt_populate = ttm_pool_populate, - .ttm_tt_unpopulate = ttm_pool_unpopulate, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bo_driver_evict_flags, .move_notify = bo_driver_move_notify, -- GitLab From a2ff1e81d04eb938a670bce206de2963d98950d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:41 +1000 Subject: [PATCH 0254/1494] drm/ttm: export memory type debug entrypoint. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As suggested on review, just export the memory type debug for drivers to use, while also making the debug callback optional (don't need to test for system as it won't init it). rename it to be more consistent with object name for now. (we may rename all the objects later.) Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-9-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 13 +++++++------ include/drm/ttm/ttm_bo_driver.h | 8 ++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c5771a43d8ecd..8cd012f6bba20 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -77,26 +77,26 @@ static inline int ttm_mem_type_from_place(const struct ttm_place *place, return 0; } -static void ttm_mem_type_debug(struct ttm_bo_device *bdev, struct drm_printer *p, - int mem_type) +void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, + struct drm_printer *p) { - struct ttm_mem_type_manager *man = &bdev->man[mem_type]; - drm_printf(p, " has_type: %d\n", man->has_type); drm_printf(p, " use_type: %d\n", man->use_type); drm_printf(p, " use_tt: %d\n", man->use_tt); drm_printf(p, " size: %llu\n", man->size); drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); drm_printf(p, " default_caching: 0x%08X\n", man->default_caching); - if (mem_type != TTM_PL_SYSTEM) + if (man->func && man->func->debug) (*man->func->debug)(man, p); } +EXPORT_SYMBOL(ttm_mem_type_manager_debug); static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, struct ttm_placement *placement) { struct drm_printer p = drm_debug_printer(TTM_PFX); int i, ret, mem_type; + struct ttm_mem_type_manager *man; drm_printf(&p, "No space for %p (%lu pages, %luK, %luM)\n", bo, bo->mem.num_pages, bo->mem.size >> 10, @@ -108,7 +108,8 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, return; drm_printf(&p, " placement[%d]=0x%08X (%d)\n", i, placement->placement[i].flags, mem_type); - ttm_mem_type_debug(bo->bdev, &p, mem_type); + man = &bo->bdev->man[mem_type]; + ttm_mem_type_manager_debug(man, &p); } } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 049ebf85712fc..ee11ae621c3b3 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -806,4 +806,12 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; +/** + * ttm_mem_type_manager_debug + * + * @man: manager type to dump. + * @p: printer to use for debug. + */ +void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, + struct drm_printer *p); #endif -- GitLab From ed165d452c2b897a70bf5a20697fa80cdbc2c151 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:42 +1000 Subject: [PATCH 0255/1494] drm/nouveau/ttm: don't fill in blank ttm debug callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-10-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index b0012021ae12d..6de762a0c229b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -49,12 +49,6 @@ nouveau_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg) nouveau_mem_del(reg); } -static void -nouveau_manager_debug(struct ttm_mem_type_manager *man, - struct drm_printer *printer) -{ -} - static int nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, @@ -86,7 +80,6 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { .takedown = nouveau_manager_fini, .get_node = nouveau_vram_manager_new, .put_node = nouveau_manager_del, - .debug = nouveau_manager_debug, }; static int @@ -112,7 +105,6 @@ const struct ttm_mem_type_manager_func nouveau_gart_manager = { .takedown = nouveau_manager_fini, .get_node = nouveau_gart_manager_new, .put_node = nouveau_manager_del, - .debug = nouveau_manager_debug }; static int @@ -147,7 +139,6 @@ const struct ttm_mem_type_manager_func nv04_gart_manager = { .takedown = nouveau_manager_fini, .get_node = nv04_gart_manager_new, .put_node = nouveau_manager_del, - .debug = nouveau_manager_debug }; int -- GitLab From a0bb77cb77e290c3d5862435a36ee9ea92cc3be1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:43 +1000 Subject: [PATCH 0256/1494] drm/vmwgfx/gmrid: don't provide pointless ttm debug callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-11-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index 4a76fc7114adc..fb1bf4dd91d19 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -137,16 +137,9 @@ static int vmw_gmrid_man_takedown(struct ttm_mem_type_manager *man) return 0; } -static void vmw_gmrid_man_debug(struct ttm_mem_type_manager *man, - struct drm_printer *printer) -{ - drm_printf(printer, "No debug info available for the GMR id manager\n"); -} - const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { .init = vmw_gmrid_man_init, .takedown = vmw_gmrid_man_takedown, .get_node = vmw_gmrid_man_get_node, .put_node = vmw_gmrid_man_put_node, - .debug = vmw_gmrid_man_debug }; -- GitLab From 00c2f6b3e8414ebea45f994dd81166a16670d231 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:44 +1000 Subject: [PATCH 0257/1494] drm/qxl/ttm: call ttm manager debug (v2) v2: use the new exported interface. This code was poking inside a struct and assuming it was a drm_mm at the start. Call the proper API. Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-12-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_ttm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 32069e4799f36..10109a3a168a3 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -280,12 +280,10 @@ void qxl_ttm_fini(struct qxl_device *qdev) static int qxl_mm_dump_table(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_mm *mm = (struct drm_mm *)node->info_ent->data; + struct ttm_mem_type_manager *man = (struct ttm_mem_type_manager *)node->info_ent->data; struct drm_printer p = drm_seq_file_printer(m); - spin_lock(&ttm_bo_glob.lru_lock); - drm_mm_print(mm, &p); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_mem_type_manager_debug(man, &p); return 0; } #endif @@ -306,9 +304,9 @@ void qxl_ttm_debugfs_init(struct qxl_device *qdev) qxl_mem_types_list[i].show = &qxl_mm_dump_table; qxl_mem_types_list[i].driver_features = 0; if (i == 0) - qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_VRAM].priv; + qxl_mem_types_list[i].data = &qdev->mman.bdev.man[TTM_PL_VRAM]; else - qxl_mem_types_list[i].data = qdev->mman.bdev.man[TTM_PL_PRIV].priv; + qxl_mem_types_list[i].data = &qdev->mman.bdev.man[TTM_PL_PRIV]; } qxl_debugfs_add_files(qdev, qxl_mem_types_list, i); -- GitLab From e22054debc079ed1c9db7561b8efda43a078fbe0 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:45 +1000 Subject: [PATCH 0258/1494] drm/vram-helper: call the ttm manager debug function This code was assuming there was a drm_mm here, don't do that call the correct API. v2: use the new exported interface. Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-13-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index a93a00966f3ac..c20aee2fddf38 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1075,12 +1075,10 @@ static int drm_vram_mm_debugfs(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_vram_mm *vmm = node->minor->dev->vram_mm; - struct drm_mm *mm = vmm->bdev.man[TTM_PL_VRAM].priv; + struct ttm_mem_type_manager *man = &vmm->bdev.man[TTM_PL_VRAM]; struct drm_printer p = drm_seq_file_printer(m); - spin_lock(&ttm_bo_glob.lru_lock); - drm_mm_print(mm, &p); - spin_unlock(&ttm_bo_glob.lru_lock); + ttm_mem_type_manager_debug(man, &p); return 0; } -- GitLab From 747074bb04b5a6be8e562d06b5a312d6ddb253d0 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:46 +1000 Subject: [PATCH 0259/1494] drm/ttm: split the mm manager init code (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow the driver to control the ordering here better. Eventually the old path will be removed. v2: add docs for new APIs. rename new path to ttm_mem_type_manager_init/set_used(for now) Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-14-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 34 +++++++++++++++++++-------------- include/drm/ttm/ttm_bo_api.h | 15 +++++++++++++++ include/drm/ttm/ttm_bo_driver.h | 15 +++++++++++++++ 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 8cd012f6bba20..ebc850ce1273f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1507,35 +1507,41 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) } EXPORT_SYMBOL(ttm_bo_evict_mm); -int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_size) +void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man, + unsigned long p_size) { - int ret; - struct ttm_mem_type_manager *man; unsigned i; - BUG_ON(type >= TTM_NUM_MEM_TYPES); - man = &bdev->man[type]; BUG_ON(man->has_type); man->use_io_reserve_lru = false; mutex_init(&man->io_reserve_mutex); spin_lock_init(&man->move_lock); INIT_LIST_HEAD(&man->io_reserve_lru); man->bdev = bdev; - - if (type != TTM_PL_SYSTEM) { - ret = (*man->func->init)(man, p_size); - if (ret) - return ret; - } - man->has_type = true; - man->use_type = true; man->size = p_size; for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) INIT_LIST_HEAD(&man->lru[i]); man->move = NULL; +} +EXPORT_SYMBOL(ttm_mem_type_manager_init); +int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, + unsigned long p_size) +{ + int ret; + struct ttm_mem_type_manager *man; + + BUG_ON(type >= TTM_NUM_MEM_TYPES); + ttm_mem_type_manager_init(bdev, &bdev->man[type], p_size); + + if (type != TTM_PL_SYSTEM) { + ret = (*man->func->init)(man, p_size); + if (ret) + return ret; + } + ttm_mem_type_manager_set_used(man, true); return 0; } EXPORT_SYMBOL(ttm_bo_init_mm); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index b1c705a935179..cc876cd3b82cb 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -54,6 +54,8 @@ struct ttm_place; struct ttm_lru_bulk_move; +struct ttm_mem_type_manager; + /** * struct ttm_bus_placement * @@ -531,6 +533,19 @@ int ttm_bo_create(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_alignment, bool interruptible, struct ttm_buffer_object **p_bo); +/** + * ttm_mem_type_manager_init + * + * @bdev: Pointer to a ttm_bo_device struct. + * @man: memory manager object to init + * @p_size: size managed area in pages. + * + * Initialise core parts of a a manager object. + */ +void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man, + unsigned long p_size); + /** * ttm_bo_init_mm * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ee11ae621c3b3..02aa1b996b3aa 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -689,6 +689,21 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) dma_resv_unlock(bo->base.resv); } +/** + * ttm_mem_type_manager_set_used + * + * @man: A memory manager object. + * @used: usage state to set. + * + * Set the manager in use flag. If disabled the manager is no longer + * used for object placement. + */ +static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *man, bool used) +{ + man->has_type = true; + man->use_type = used; +} + /* * ttm_bo_util.c */ -- GitLab From 3c90424bd7df15eb062ae9e6518886a706ed0d84 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:47 +1000 Subject: [PATCH 0260/1494] drm/ttm: provide a driver-led init path for range mm manager. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets the generic range mm manager be initialised by the driver. v2: add docs. rename api to range_man_init for now. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-15-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_manager.c | 23 ++++++++++++++++++++--- include/drm/ttm/ttm_bo_driver.h | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index facd3049c3aa2..eb86c8694f471 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -104,8 +104,8 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, } } -static int ttm_bo_man_init(struct ttm_mem_type_manager *man, - unsigned long p_size) +static int ttm_bo_man_init_private(struct ttm_mem_type_manager *man, + unsigned long p_size) { struct ttm_range_manager *rman; @@ -119,6 +119,23 @@ static int ttm_bo_man_init(struct ttm_mem_type_manager *man, return 0; } +int ttm_range_man_init(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man, + unsigned long p_size) +{ + int ret; + + man->func = &ttm_bo_manager_func; + + ttm_mem_type_manager_init(bdev, man, p_size); + ret = ttm_bo_man_init_private(man, p_size); + if (ret) + return ret; + ttm_mem_type_manager_set_used(man, true); + return 0; +} +EXPORT_SYMBOL(ttm_range_man_init); + static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) { struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; @@ -147,7 +164,7 @@ static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func ttm_bo_manager_func = { - .init = ttm_bo_man_init, + .init = ttm_bo_man_init_private, .takedown = ttm_bo_man_takedown, .get_node = ttm_bo_man_get_node, .put_node = ttm_bo_man_put_node, diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 02aa1b996b3aa..23352053df36b 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -819,6 +819,20 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); */ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); +/** + * ttm_range_man_init + * + * @bdev: ttm device + * @man: the manager to initialise with the range manager. + * @p_size: size of area to be managed in pages. + * + * Initialise a generic range manager for the selected memory type. + * The range manager is installed for this device in the type slot. + */ +int ttm_range_man_init(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man, + unsigned long p_size); + extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; /** -- GitLab From 158d20d1857fe58af6cfa8163b37f90e999c948e Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:48 +1000 Subject: [PATCH 0261/1494] drm/amdgpu/ttm: init managers from the driver side. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new init calls to unwrap manager init Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-16-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 19 ++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 37 +++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 19 ++++++---- 4 files changed, 33 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 62cf4fbd803a3..f94c6a3836a8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -76,6 +76,7 @@ static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO, static DEVICE_ATTR(mem_info_gtt_used, S_IRUGO, amdgpu_mem_info_gtt_used_show, NULL); +static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; /** * amdgpu_gtt_mgr_init - init GTT manager and DRM MM * @@ -84,14 +85,20 @@ static DEVICE_ATTR(mem_info_gtt_used, S_IRUGO, * * Allocate and initialize the GTT manager. */ -static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, - unsigned long p_size) +int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; struct amdgpu_gtt_mgr *mgr; uint64_t start, size; int ret; + man->use_tt = true; + man->func = &amdgpu_gtt_mgr_func; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + + ttm_mem_type_manager_init(&adev->mman.bdev, man, gtt_size >> PAGE_SHIFT); + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (!mgr) return -ENOMEM; @@ -100,7 +107,7 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; drm_mm_init(&mgr->mm, start, size); spin_lock_init(&mgr->lock); - atomic64_set(&mgr->available, p_size); + atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT); man->priv = mgr; ret = device_create_file(adev->dev, &dev_attr_mem_info_gtt_total); @@ -114,6 +121,7 @@ static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man, return ret; } + ttm_mem_type_manager_set_used(man, true); return 0; } @@ -300,8 +308,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, amdgpu_gtt_mgr_usage(man) >> 20); } -const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = { - .init = amdgpu_gtt_mgr_init, +static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = { .takedown = amdgpu_gtt_mgr_fini, .get_node = amdgpu_gtt_mgr_new, .put_node = amdgpu_gtt_mgr_del, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index da6434ea07f13..40583540d8553 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -62,43 +62,16 @@ #define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128 -static int amdgpu_ttm_init_vram(struct amdgpu_device *adev) -{ - - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; - - man->func = &amdgpu_vram_mgr_func; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - - return ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, - adev->gmc.real_vram_size >> PAGE_SHIFT); -} - -static int amdgpu_ttm_init_gtt(struct amdgpu_device *adev, uint64_t gtt_size) -{ - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; - - man->use_tt = true; - man->func = &amdgpu_gtt_mgr_func; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - - return ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, - gtt_size >> PAGE_SHIFT); -} - static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, - unsigned int type, - uint64_t size) + unsigned int type, + uint64_t size) { struct ttm_mem_type_manager *man = &adev->mman.bdev.man[type]; - man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_FLAG_UNCACHED; man->default_caching = TTM_PL_FLAG_UNCACHED; - return ttm_bo_init_mm(&adev->mman.bdev, type, size); + return ttm_range_man_init(&adev->mman.bdev, man, size >> PAGE_SHIFT); } /** @@ -1883,7 +1856,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) adev->mman.bdev.no_retry = true; /* Initialize VRAM pool with all of VRAM divided into pages */ - r = amdgpu_ttm_init_vram(adev); + r = amdgpu_vram_mgr_init(adev); if (r) { DRM_ERROR("Failed initializing VRAM heap.\n"); return r; @@ -1964,7 +1937,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) gtt_size = (uint64_t)amdgpu_gtt_size << 20; /* Initialize GTT memory pool */ - r = amdgpu_ttm_init_gtt(adev, gtt_size); + r = amdgpu_gtt_mgr_init(adev, gtt_size); if (r) { DRM_ERROR("Failed initializing GTT heap.\n"); return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 17c8d0d7bcc37..fb45c0a323b0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -67,8 +67,8 @@ struct amdgpu_copy_mem { unsigned long offset; }; -extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; -extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; +int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size); +int amdgpu_vram_mgr_init(struct amdgpu_device *adev); bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem); uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index d4f626d9bec18..6fcbeb06c0b6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -158,6 +158,8 @@ static const struct attribute *amdgpu_vram_mgr_attributes[] = { NULL }; +static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; + /** * amdgpu_vram_mgr_init - init VRAM manager and DRM MM * @@ -166,18 +168,23 @@ static const struct attribute *amdgpu_vram_mgr_attributes[] = { * * Allocate and initialize the VRAM manager. */ -static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man, - unsigned long p_size) +int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; struct amdgpu_vram_mgr *mgr; int ret; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + + ttm_mem_type_manager_init(&adev->mman.bdev, man, adev->gmc.real_vram_size >> PAGE_SHIFT); + + man->func = &amdgpu_vram_mgr_func; mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); if (!mgr) return -ENOMEM; - drm_mm_init(&mgr->mm, 0, p_size); + drm_mm_init(&mgr->mm, 0, man->size); spin_lock_init(&mgr->lock); man->priv = mgr; @@ -186,6 +193,7 @@ static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man, if (ret) DRM_ERROR("Failed to register sysfs\n"); + ttm_mem_type_manager_set_used(man, true); return 0; } @@ -589,8 +597,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, amdgpu_vram_mgr_vis_usage(man) >> 20); } -const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { - .init = amdgpu_vram_mgr_init, +static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { .takedown = amdgpu_vram_mgr_fini, .get_node = amdgpu_vram_mgr_new, .put_node = amdgpu_vram_mgr_del, -- GitLab From e33dc18228acdda13ecfe8c57f2a4ded9a825460 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:49 +1000 Subject: [PATCH 0262/1494] drm/radeon: use new ttm man init path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new common manager init path. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-17-airlied@gmail.com --- drivers/gpu/drm/radeon/radeon_ttm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index f499d02917ac5..40959cea4476b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -70,19 +70,17 @@ static int radeon_ttm_init_vram(struct radeon_device *rdev) { struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_VRAM]; - man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - return ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, - rdev->mc.real_vram_size >> PAGE_SHIFT); + return ttm_range_man_init(&rdev->mman.bdev, man, + rdev->mc.real_vram_size >> PAGE_SHIFT); } static int radeon_ttm_init_gtt(struct radeon_device *rdev) { struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_TT]; - man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; man->use_tt = true; @@ -98,8 +96,8 @@ static int radeon_ttm_init_gtt(struct radeon_device *rdev) } #endif - return ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, - rdev->mc.gtt_size >> PAGE_SHIFT); + return ttm_range_man_init(&rdev->mman.bdev, man, + rdev->mc.gtt_size >> PAGE_SHIFT); } static void radeon_evict_flags(struct ttm_buffer_object *bo, -- GitLab From 129ac4dcb52001c27d3573ecb361b8e6328c4135 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:50 +1000 Subject: [PATCH 0263/1494] drm/qxl/ttm: use new init path for manager Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-18-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_ttm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 10109a3a168a3..b116064bd690b 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -222,11 +222,10 @@ static int qxl_ttm_init_mem_type(struct qxl_device *qdev, { struct ttm_mem_type_manager *man = &qdev->mman.bdev.man[type]; - man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - return ttm_bo_init_mm(&qdev->mman.bdev, type, size); + return ttm_range_man_init(&qdev->mman.bdev, man, size); } int qxl_ttm_init(struct qxl_device *qdev) -- GitLab From a9136ab56ba9706aaadb33d1e2175dc80079e091 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:51 +1000 Subject: [PATCH 0264/1494] drm/vram_helper: use new ttm manager init function Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-19-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index c20aee2fddf38..d7c0fdf82eb64 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1116,10 +1116,9 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, if (ret) return ret; - man->func = &ttm_bo_manager_func; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT); + ret = ttm_range_man_init(&vmm->bdev, man, vram_size >> PAGE_SHIFT); if (ret) return ret; -- GitLab From e9172ada44606a8dfaa81be008d3c9a99d766280 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:52 +1000 Subject: [PATCH 0265/1494] drm/nouveau: use new memory manager init paths Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-20-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 43 ++++++++++++--------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 6de762a0c229b..cfcbecd332ef0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -31,12 +31,6 @@ #include <core/tegra.h> -static int -nouveau_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - return 0; -} - static int nouveau_manager_fini(struct ttm_mem_type_manager *man) { @@ -76,7 +70,6 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nouveau_vram_manager = { - .init = nouveau_manager_init, .takedown = nouveau_manager_fini, .get_node = nouveau_vram_manager_new, .put_node = nouveau_manager_del, @@ -101,7 +94,6 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nouveau_gart_manager = { - .init = nouveau_manager_init, .takedown = nouveau_manager_fini, .get_node = nouveau_gart_manager_new, .put_node = nouveau_manager_del, @@ -135,7 +127,6 @@ nv04_gart_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nv04_gart_manager = { - .init = nouveau_manager_init, .takedown = nouveau_manager_fini, .get_node = nv04_gart_manager_new, .put_node = nouveau_manager_del, @@ -191,27 +182,21 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) man->func = &nouveau_vram_manager; man->use_io_reserve_lru = true; + ttm_mem_type_manager_init(&drm->ttm.bdev, man, + drm->gem.vram_available >> PAGE_SHIFT); + ttm_mem_type_manager_set_used(man, true); + return 0; } else { - man->func = &ttm_bo_manager_func; + return ttm_range_man_init(&drm->ttm.bdev, man, + drm->gem.vram_available >> PAGE_SHIFT); } - - return ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_VRAM, - drm->gem.vram_available >> PAGE_SHIFT); } static int nouveau_ttm_init_gtt(struct nouveau_drm *drm) { struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_TT]; - - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) - man->func = &nouveau_gart_manager; - else - if (!drm->agp.bridge) - man->func = &nv04_gart_manager; - else - man->func = &ttm_bo_manager_func; - + unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; man->use_tt = true; if (drm->agp.bridge) { man->available_caching = TTM_PL_FLAG_UNCACHED | @@ -222,8 +207,18 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) man->default_caching = TTM_PL_FLAG_CACHED; } - return ttm_bo_init_mm(&drm->ttm.bdev, TTM_PL_TT, - drm->gem.gart_available >> PAGE_SHIFT); + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) + man->func = &nouveau_gart_manager; + else if (!drm->agp.bridge) + man->func = &nv04_gart_manager; + else + return ttm_range_man_init(&drm->ttm.bdev, man, + size_pages); + + ttm_mem_type_manager_init(&drm->ttm.bdev, man, + size_pages); + ttm_mem_type_manager_set_used(man, true); + return 0; } int -- GitLab From 252f8d7b917464f1f5aa51b3c7ac4867e035389a Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:53 +1000 Subject: [PATCH 0266/1494] drm/vmwgfx/ttm: convert vram mm init to new code paths Split out the vram thp init path vs the range manager init. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-21-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 25 +++++++++++++++++++------ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 +--- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 12 ++++++++---- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 8e67a29471a8c..0aecdd73133fc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -620,6 +620,23 @@ static int vmw_dma_masks(struct vmw_private *dev_priv) return ret; } +static int vmw_vram_manager_init(struct vmw_private *dev_priv) +{ + int ret; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + ret = vmw_thp_init(dev_priv); +#else + struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; + + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + + ret = ttm_range_man_init(&dev_priv->bdev, man, + dev_priv->vram_size >> PAGE_SHIFT); +#endif + dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; + return ret; +} static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { struct vmw_private *dev_priv; @@ -866,16 +883,12 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) * Enable VRAM, but initially don't use it until SVGA is enabled and * unhidden. */ - dev_priv->bdev.man[TTM_PL_VRAM].func = &vmw_thp_func; - dev_priv->bdev.man[TTM_PL_VRAM].available_caching = TTM_PL_FLAG_CACHED; - dev_priv->bdev.man[TTM_PL_VRAM].default_caching = TTM_PL_FLAG_CACHED; - ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, - (dev_priv->vram_size >> PAGE_SHIFT)); + + ret = vmw_vram_manager_init(dev_priv); if (unlikely(ret != 0)) { DRM_ERROR("Failed initializing memory manager for VRAM.\n"); goto out_no_vram; } - dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; /* * "Guest Memory Regions" is an aperture like feature with diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 65c414f119c03..10b681725a538 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1520,9 +1520,7 @@ vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, /* Transparent hugepage support - vmwgfx_thp.c */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE -extern const struct ttm_mem_type_manager_func vmw_thp_func; -#else -#define vmw_thp_func ttm_bo_manager_func +extern int vmw_thp_init(struct vmw_private *dev_priv); #endif /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index b7c816ba71663..0292c931c2651 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -115,18 +115,23 @@ static void vmw_thp_put_node(struct ttm_mem_type_manager *man, } } -static int vmw_thp_init(struct ttm_mem_type_manager *man, - unsigned long p_size) +int vmw_thp_init(struct vmw_private *dev_priv) { + struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; struct vmw_thp_manager *rman; + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + ttm_mem_type_manager_init(&dev_priv->bdev, man, + dev_priv->vram_size >> PAGE_SHIFT); rman = kzalloc(sizeof(*rman), GFP_KERNEL); if (!rman) return -ENOMEM; - drm_mm_init(&rman->mm, 0, p_size); + drm_mm_init(&rman->mm, 0, man->size); spin_lock_init(&rman->lock); man->priv = rman; + ttm_mem_type_manager_set_used(man, true); return 0; } @@ -158,7 +163,6 @@ static void vmw_thp_debug(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func vmw_thp_func = { - .init = vmw_thp_init, .takedown = vmw_thp_takedown, .get_node = vmw_thp_get_node, .put_node = vmw_thp_put_node, -- GitLab From 621617780a62ba8b748dc4fe8d72322f983d2689 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:54 +1000 Subject: [PATCH 0267/1494] drm/vmwgfx/ttm: switch gmrid allocator to new init paths. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-22-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 17 ++++----------- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 21 ++++++++++++------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0aecdd73133fc..d8a0165b5e77b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -896,14 +896,10 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) * slots as well as the bo size. */ dev_priv->has_gmr = true; - dev_priv->bdev.man[VMW_PL_GMR].func = &vmw_gmrid_manager_func; - dev_priv->bdev.man[VMW_PL_GMR].available_caching = TTM_PL_FLAG_CACHED; - dev_priv->bdev.man[VMW_PL_GMR].default_caching = TTM_PL_FLAG_CACHED; /* TODO: This is most likely not correct */ - dev_priv->bdev.man[VMW_PL_GMR].use_tt = true; if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || - refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, - VMW_PL_GMR) != 0) { + refuse_dma || + vmw_gmrid_man_init(dev_priv, VMW_PL_GMR) != 0) { DRM_INFO("No GMR memory available. " "Graphics memory resources are very limited.\n"); dev_priv->has_gmr = false; @@ -911,13 +907,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS && !refuse_dma) { dev_priv->has_mob = true; - dev_priv->bdev.man[VMW_PL_MOB].func = &vmw_gmrid_manager_func; - dev_priv->bdev.man[VMW_PL_MOB].available_caching = TTM_PL_FLAG_CACHED; - dev_priv->bdev.man[VMW_PL_MOB].default_caching = TTM_PL_FLAG_CACHED; - /* TODO: This is most likely not correct */ - dev_priv->bdev.man[VMW_PL_MOB].use_tt = true; - if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_MOB, - VMW_PL_MOB) != 0) { + + if (vmw_gmrid_man_init(dev_priv, VMW_PL_MOB) != 0) { DRM_INFO("No MOB memory available. " "3D will be disabled.\n"); dev_priv->has_mob = false; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 10b681725a538..8f319dd6cdb43 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1221,7 +1221,7 @@ int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); * GMR Id manager */ -extern const struct ttm_mem_type_manager_func vmw_gmrid_manager_func; +int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); /** * Prime - vmwgfx_prime.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index fb1bf4dd91d19..141fb14e35830 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -94,22 +94,28 @@ static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man, } } -static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man, - unsigned long p_size) +static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func; + +int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) { - struct vmw_private *dev_priv = - container_of(man->bdev, struct vmw_private, bdev); + struct ttm_mem_type_manager *man = &dev_priv->bdev.man[type]; struct vmwgfx_gmrid_man *gman = kzalloc(sizeof(*gman), GFP_KERNEL); if (unlikely(!gman)) return -ENOMEM; + man->func = &vmw_gmrid_manager_func; + man->available_caching = TTM_PL_FLAG_CACHED; + man->default_caching = TTM_PL_FLAG_CACHED; + /* TODO: This is most likely not correct */ + man->use_tt = true; + ttm_mem_type_manager_init(&dev_priv->bdev, man, 0); spin_lock_init(&gman->lock); gman->used_gmr_pages = 0; ida_init(&gman->gmr_ida); - switch (p_size) { + switch (type) { case VMW_PL_GMR: gman->max_gmr_ids = dev_priv->max_gmr_ids; gman->max_gmr_pages = dev_priv->max_gmr_pages; @@ -122,6 +128,8 @@ static int vmw_gmrid_man_init(struct ttm_mem_type_manager *man, BUG(); } man->priv = (void *) gman; + + ttm_mem_type_manager_set_used(man, true); return 0; } @@ -137,8 +145,7 @@ static int vmw_gmrid_man_takedown(struct ttm_mem_type_manager *man) return 0; } -const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { - .init = vmw_gmrid_man_init, +static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { .takedown = vmw_gmrid_man_takedown, .get_node = vmw_gmrid_man_get_node, .put_node = vmw_gmrid_man_put_node, -- GitLab From 5969793f8656e891f9b3d1542b1642536c31f2bc Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:55 +1000 Subject: [PATCH 0268/1494] drm/ttm: convert system manager init to new code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the exit path, since this can't fail now. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-23-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ebc850ce1273f..a7e66a2d89a23 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1648,6 +1648,22 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) } EXPORT_SYMBOL(ttm_bo_device_release); +static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) +{ + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_SYSTEM]; + + /* + * Initialize the system memory buffer type. + * Other types need to be driver / IOCTL initialized. + */ + man->use_tt = true; + man->available_caching = TTM_PL_MASK_CACHING; + man->default_caching = TTM_PL_FLAG_CACHED; + + ttm_mem_type_manager_init(bdev, man, 0); + ttm_mem_type_manager_set_used(man, true); +} + int ttm_bo_device_init(struct ttm_bo_device *bdev, struct ttm_bo_driver *driver, struct address_space *mapping, @@ -1668,16 +1684,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, memset(bdev->man, 0, sizeof(bdev->man)); - /* - * Initialize the system memory buffer type. - * Other types need to be driver / IOCTL initialized. - */ - bdev->man[TTM_PL_SYSTEM].use_tt = true; - bdev->man[TTM_PL_SYSTEM].available_caching = TTM_PL_MASK_CACHING; - bdev->man[TTM_PL_SYSTEM].default_caching = TTM_PL_FLAG_CACHED; - ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0); - if (unlikely(ret != 0)) - goto out_no_sys; + ttm_bo_init_sysman(bdev); bdev->vma_manager = vma_manager; INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue); @@ -1689,9 +1696,6 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, mutex_unlock(&ttm_global_mutex); return 0; -out_no_sys: - ttm_bo_global_release(); - return ret; } EXPORT_SYMBOL(ttm_bo_device_init); -- GitLab From 98399abd52b234b82457ef6c40c41543d806d3b7 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:56 +1000 Subject: [PATCH 0269/1494] drm/ttm: purge old manager init path. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-24-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 19 ------------------ drivers/gpu/drm/ttm/ttm_bo_manager.c | 29 ++++++++++------------------ include/drm/ttm/ttm_bo_api.h | 18 ----------------- include/drm/ttm/ttm_bo_driver.h | 15 -------------- 4 files changed, 10 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index a7e66a2d89a23..869ca5b3e4bfb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1527,25 +1527,6 @@ void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_mem_type_manager_init); -int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_size) -{ - int ret; - struct ttm_mem_type_manager *man; - - BUG_ON(type >= TTM_NUM_MEM_TYPES); - ttm_mem_type_manager_init(bdev, &bdev->man[type], p_size); - - if (type != TTM_PL_SYSTEM) { - ret = (*man->func->init)(man, p_size); - if (ret) - return ret; - } - ttm_mem_type_manager_set_used(man, true); - return 0; -} -EXPORT_SYMBOL(ttm_bo_init_mm); - static void ttm_bo_global_kobj_release(struct kobject *kobj) { struct ttm_bo_global *glob = diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index eb86c8694f471..b56c6961b2782 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -104,11 +104,18 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, } } -static int ttm_bo_man_init_private(struct ttm_mem_type_manager *man, - unsigned long p_size) +static const struct ttm_mem_type_manager_func ttm_bo_manager_func; + +int ttm_range_man_init(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man, + unsigned long p_size) { struct ttm_range_manager *rman; + man->func = &ttm_bo_manager_func; + + ttm_mem_type_manager_init(bdev, man, p_size); + rman = kzalloc(sizeof(*rman), GFP_KERNEL); if (!rman) return -ENOMEM; @@ -116,21 +123,7 @@ static int ttm_bo_man_init_private(struct ttm_mem_type_manager *man, drm_mm_init(&rman->mm, 0, p_size); spin_lock_init(&rman->lock); man->priv = rman; - return 0; -} -int ttm_range_man_init(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, - unsigned long p_size) -{ - int ret; - - man->func = &ttm_bo_manager_func; - - ttm_mem_type_manager_init(bdev, man, p_size); - ret = ttm_bo_man_init_private(man, p_size); - if (ret) - return ret; ttm_mem_type_manager_set_used(man, true); return 0; } @@ -163,11 +156,9 @@ static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, spin_unlock(&rman->lock); } -const struct ttm_mem_type_manager_func ttm_bo_manager_func = { - .init = ttm_bo_man_init_private, +static const struct ttm_mem_type_manager_func ttm_bo_manager_func = { .takedown = ttm_bo_man_takedown, .get_node = ttm_bo_man_get_node, .put_node = ttm_bo_man_put_node, .debug = ttm_bo_man_debug }; -EXPORT_SYMBOL(ttm_bo_manager_func); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index cc876cd3b82cb..56d207b983e98 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -546,24 +546,6 @@ void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, struct ttm_mem_type_manager *man, unsigned long p_size); -/** - * ttm_bo_init_mm - * - * @bdev: Pointer to a ttm_bo_device struct. - * @mem_type: The memory type. - * @p_size: size managed area in pages. - * - * Initialize a manager for a given memory type. - * Note: if part of driver firstopen, it must be protected from a - * potentially racing lastclose. - * Returns: - * -EINVAL: invalid size or memory type. - * -ENOMEM: Not enough memory. - * May also return driver-specified errors. - */ -int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, - unsigned long p_size); - /** * ttm_bo_clean_mm * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 23352053df36b..303014250767f 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -48,19 +48,6 @@ struct ttm_mem_type_manager; struct ttm_mem_type_manager_func { - /** - * struct ttm_mem_type_manager member init - * - * @man: Pointer to a memory type manager. - * @p_size: Implementation dependent, but typically the size of the - * range to be managed in pages. - * - * Called to initialize a private range manager. The function is - * expected to initialize the man::priv member. - * Returns 0 on success, negative error code on failure. - */ - int (*init)(struct ttm_mem_type_manager *man, unsigned long p_size); - /** * struct ttm_mem_type_manager member takedown * @@ -833,8 +820,6 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, struct ttm_mem_type_manager *man, unsigned long p_size); -extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; - /** * ttm_mem_type_manager_debug * -- GitLab From a006a3ce8efc9e8276d0f0193c04f2efb0e28135 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:57 +1000 Subject: [PATCH 0270/1494] drm/ttm: pass man around instead of mem_type in some places MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to cleanup things Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-25-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 869ca5b3e4bfb..53017cf065274 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -769,13 +769,12 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, } static int ttm_mem_evict_first(struct ttm_bo_device *bdev, - uint32_t mem_type, + struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_operation_ctx *ctx, struct ww_acquire_ctx *ticket) { struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; - struct ttm_mem_type_manager *man = &bdev->man[mem_type]; bool locked = false; unsigned i; int ret; @@ -922,7 +921,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, break; if (unlikely(ret != -ENOSPC)) return ret; - ret = ttm_mem_evict_first(bdev, mem->mem_type, place, ctx, + ret = ttm_mem_evict_first(bdev, man, place, ctx, ticket); if (unlikely(ret != 0)) return ret; @@ -1407,14 +1406,13 @@ int ttm_bo_create(struct ttm_bo_device *bdev, EXPORT_SYMBOL(ttm_bo_create); static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, - unsigned mem_type) + struct ttm_mem_type_manager *man) { struct ttm_operation_ctx ctx = { .interruptible = false, .no_wait_gpu = false, .flags = TTM_OPT_FLAG_FORCE_ALLOC }; - struct ttm_mem_type_manager *man = &bdev->man[mem_type]; struct ttm_bo_global *glob = &ttm_bo_glob; struct dma_fence *fence; int ret; @@ -1428,7 +1426,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { while (!list_empty(&man->lru[i])) { spin_unlock(&glob->lru_lock); - ret = ttm_mem_evict_first(bdev, mem_type, NULL, &ctx, + ret = ttm_mem_evict_first(bdev, man, NULL, &ctx, NULL); if (ret) return ret; @@ -1473,7 +1471,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) ret = 0; if (mem_type > 0) { - ret = ttm_bo_force_list_clean(bdev, mem_type); + ret = ttm_bo_force_list_clean(bdev, man); if (ret) { pr_err("Cleanup eviction failed\n"); return ret; @@ -1503,7 +1501,7 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) return 0; } - return ttm_bo_force_list_clean(bdev, mem_type); + return ttm_bo_force_list_clean(bdev, man); } EXPORT_SYMBOL(ttm_bo_evict_mm); -- GitLab From 4265accbfc724a68894f91737e765e2cce43fe4e Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:58 +1000 Subject: [PATCH 0271/1494] drm/ttm: make some inline helper functions for cleanup paths. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The disable path is just temporary for now, it will be dropped once has_type is gone in a later patch. v2: add docs. rename to ttm_mem_type_manager namespace Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-26-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 6 ++---- include/drm/ttm/ttm_bo_driver.h | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 53017cf065274..be0c0a01b929a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1466,8 +1466,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) return ret; } - man->use_type = false; - man->has_type = false; + ttm_mem_type_manager_disable(man); ret = 0; if (mem_type > 0) { @@ -1480,8 +1479,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) ret = (*man->func->takedown)(man); } - dma_fence_put(man->move); - man->move = NULL; + ttm_mem_type_manager_cleanup(man); return ret; } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 303014250767f..30dfb9d5f6c94 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -691,6 +691,32 @@ static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *ma man->use_type = used; } +/** + * ttm_mem_type_manager_disable. + * + * @man: A memory manager object. + * + * Indicate the manager is not to be used and deregistered. (temporary during rework). + */ +static inline void ttm_mem_type_manager_disable(struct ttm_mem_type_manager *man) +{ + man->has_type = false; + man->use_type = false; +} + +/** + * ttm_mem_type_manager_cleanup + * + * @man: A memory manager object. + * + * Cleanup the move fences from the memory manager object. + */ +static inline void ttm_mem_type_manager_cleanup(struct ttm_mem_type_manager *man) +{ + dma_fence_put(man->move); + man->move = NULL; +} + /* * ttm_bo_util.c */ -- GitLab From 56ee8b1c71ffb556b8758f2d9e3098f4f80b4d01 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:55:59 +1000 Subject: [PATCH 0272/1494] drm/ttm: start allowing drivers to use new takedown path (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the takedown path callback to be optional as well. v2: use fini for range manager Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-27-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 12 +++++++----- drivers/gpu/drm/ttm/ttm_bo_manager.c | 21 +++++++++++++++++++-- include/drm/ttm/ttm_bo_driver.h | 24 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index be0c0a01b929a..480d23fa80996 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1405,8 +1405,8 @@ int ttm_bo_create(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_bo_create); -static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man) +int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man) { struct ttm_operation_ctx ctx = { .interruptible = false, @@ -1448,6 +1448,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, return 0; } +EXPORT_SYMBOL(ttm_mem_type_manager_force_list_clean); int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) { @@ -1470,13 +1471,14 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) ret = 0; if (mem_type > 0) { - ret = ttm_bo_force_list_clean(bdev, man); + ret = ttm_mem_type_manager_force_list_clean(bdev, man); if (ret) { pr_err("Cleanup eviction failed\n"); return ret; } - ret = (*man->func->takedown)(man); + if (man->func->takedown) + ret = (*man->func->takedown)(man); } ttm_mem_type_manager_cleanup(man); @@ -1499,7 +1501,7 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) return 0; } - return ttm_bo_force_list_clean(bdev, man); + return ttm_mem_type_manager_force_list_clean(bdev, man); } EXPORT_SYMBOL(ttm_bo_evict_mm); diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index b56c6961b2782..96da22be672bb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -129,7 +129,7 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_range_man_init); -static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) +static int ttm_bo_man_takedown_private(struct ttm_mem_type_manager *man) { struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; @@ -146,6 +146,23 @@ static int ttm_bo_man_takedown(struct ttm_mem_type_manager *man) return -EBUSY; } +int ttm_range_man_fini(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man) +{ + int ret; + + ttm_mem_type_manager_disable(man); + + ret = ttm_mem_type_manager_force_list_clean(bdev, man); + if (ret) + return ret; + + ttm_bo_man_takedown_private(man); + ttm_mem_type_manager_cleanup(man); + return 0; +} +EXPORT_SYMBOL(ttm_range_man_fini); + static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, struct drm_printer *printer) { @@ -157,7 +174,7 @@ static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, } static const struct ttm_mem_type_manager_func ttm_bo_manager_func = { - .takedown = ttm_bo_man_takedown, + .takedown = ttm_bo_man_takedown_private, .get_node = ttm_bo_man_get_node, .put_node = ttm_bo_man_put_node, .debug = ttm_bo_man_debug diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 30dfb9d5f6c94..811ace1416b37 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -717,6 +717,18 @@ static inline void ttm_mem_type_manager_cleanup(struct ttm_mem_type_manager *man man->move = NULL; } +/* + * ttm_mem_type_manager_force_list_clean + * + * @bdev - device to use + * @man - manager to use + * + * Force all the objects out of a memory manager until clean. + * Part of memory manager cleanup sequence. + */ +int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man); + /* * ttm_bo_util.c */ @@ -846,6 +858,17 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, struct ttm_mem_type_manager *man, unsigned long p_size); +/** + * ttm_range_man_fini + * + * @bdev: ttm device + * @type: memory manager type + * + * Remove the generic range manager from a slot and tear it down. + */ +int ttm_range_man_fini(struct ttm_bo_device *bdev, + struct ttm_mem_type_manager *man); + /** * ttm_mem_type_manager_debug * @@ -854,4 +877,5 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, */ void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, struct drm_printer *p); + #endif -- GitLab From 6fe1c54353f926e59f03aaa11c9271aa92fd0982 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:00 +1000 Subject: [PATCH 0273/1494] drm/amdgpu/ttm: use new takedown path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-28-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 15 +++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 15 +++++++++++---- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index f94c6a3836a8c..699cb0dff3512 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -133,10 +133,18 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) * Destroy and free the GTT manager, returns -EBUSY if ranges are still * allocated inside it. */ -static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man) +void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; struct amdgpu_gtt_mgr *mgr = man->priv; + int ret; + + ttm_mem_type_manager_disable(man); + + ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); + if (ret) + return; + spin_lock(&mgr->lock); drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); @@ -146,7 +154,7 @@ static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man) device_remove_file(adev->dev, &dev_attr_mem_info_gtt_total); device_remove_file(adev->dev, &dev_attr_mem_info_gtt_used); - return 0; + ttm_mem_type_manager_cleanup(man); } /** @@ -309,7 +317,6 @@ static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, } static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = { - .takedown = amdgpu_gtt_mgr_fini, .get_node = amdgpu_gtt_mgr_new, .put_node = amdgpu_gtt_mgr_del, .debug = amdgpu_gtt_mgr_debug diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 40583540d8553..95aedfc717e58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1994,11 +1994,11 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) iounmap(adev->mman.aper_base_kaddr); adev->mman.aper_base_kaddr = NULL; - ttm_bo_clean_mm(&adev->mman.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&adev->mman.bdev, TTM_PL_TT); - ttm_bo_clean_mm(&adev->mman.bdev, AMDGPU_PL_GDS); - ttm_bo_clean_mm(&adev->mman.bdev, AMDGPU_PL_GWS); - ttm_bo_clean_mm(&adev->mman.bdev, AMDGPU_PL_OA); + amdgpu_vram_mgr_fini(adev); + amdgpu_gtt_mgr_fini(adev); + ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_GDS]); + ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_GWS]); + ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_OA]); ttm_bo_device_release(&adev->mman.bdev); adev->mman.initialized = false; DRM_INFO("amdgpu: ttm finalized\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index fb45c0a323b0e..c01fdb3f0458a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -68,7 +68,9 @@ struct amdgpu_copy_mem { }; int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size); +void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev); int amdgpu_vram_mgr_init(struct amdgpu_device *adev); +void amdgpu_vram_mgr_fini(struct amdgpu_device *adev); bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem); uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 6fcbeb06c0b6e..b33c5164ff7af 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -205,10 +205,17 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) * Destroy and free the VRAM manager, returns -EBUSY if ranges are still * allocated inside it. */ -static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man) +void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); + struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; struct amdgpu_vram_mgr *mgr = man->priv; + int ret; + + ttm_mem_type_manager_disable(man); + + ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); + if (ret) + return; spin_lock(&mgr->lock); drm_mm_takedown(&mgr->mm); @@ -216,7 +223,8 @@ static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man) kfree(mgr); man->priv = NULL; sysfs_remove_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); - return 0; + + ttm_mem_type_manager_cleanup(man); } /** @@ -598,7 +606,6 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, } static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { - .takedown = amdgpu_vram_mgr_fini, .get_node = amdgpu_vram_mgr_new, .put_node = amdgpu_vram_mgr_del, .debug = amdgpu_vram_mgr_debug -- GitLab From e0830704de7c06c72b1f83a3f67cb160b853812a Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:01 +1000 Subject: [PATCH 0274/1494] drm/vmwgfx: takedown vram manager Don't bother returning EBUSY, nobody cares enough, if the driver has a problem, it should deal with it. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-29-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 14 +++++++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 23 +++++++++++++---------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index d8a0165b5e77b..d37dbe3379689 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -637,6 +637,17 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; return ret; } + +static void vmw_vram_manager_fini(struct vmw_private *dev_priv) +{ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + vmw_thp_fini(dev_priv); +#else + ttm_bo_man_fini(&dev_priv->bdev, + &dev_priv->bdev.man[TTM_PL_VRAM]); +#endif +} + static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { struct vmw_private *dev_priv; @@ -988,7 +999,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); if (dev_priv->has_gmr) (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); - (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + vmw_vram_manager_fini(dev_priv); out_no_vram: (void)ttm_bo_device_release(&dev_priv->bdev); out_no_bdev: @@ -1042,6 +1053,7 @@ static void vmw_driver_unload(struct drm_device *dev) vmw_release_device_early(dev_priv); if (dev_priv->has_mob) (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); + vmw_vram_manager_fini(dev_priv); (void) ttm_bo_device_release(&dev_priv->bdev); drm_vma_offset_manager_destroy(&dev_priv->vma_manager); vmw_release_device_late(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 8f319dd6cdb43..c6530d7b6d513 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1521,6 +1521,7 @@ vm_fault_t vmw_bo_vm_huge_fault(struct vm_fault *vmf, /* Transparent hugepage support - vmwgfx_thp.c */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE extern int vmw_thp_init(struct vmw_private *dev_priv); +void vmw_thp_fini(struct vmw_private *dev_priv); #endif /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 0292c931c2651..548f152b99630 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -135,21 +135,25 @@ int vmw_thp_init(struct vmw_private *dev_priv) return 0; } -static int vmw_thp_takedown(struct ttm_mem_type_manager *man) +void vmw_thp_fini(struct vmw_private *dev_priv) { + struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; struct drm_mm *mm = &rman->mm; + int ret; + + ttm_mem_type_manager_disable(man); + ret = ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); + if (ret) + return; spin_lock(&rman->lock); - if (drm_mm_clean(mm)) { - drm_mm_takedown(mm); - spin_unlock(&rman->lock); - kfree(rman); - man->priv = NULL; - return 0; - } + drm_mm_clean(mm); + drm_mm_takedown(mm); spin_unlock(&rman->lock); - return -EBUSY; + kfree(rman); + man->priv = NULL; + ttm_mem_type_manager_cleanup(man); } static void vmw_thp_debug(struct ttm_mem_type_manager *man, @@ -163,7 +167,6 @@ static void vmw_thp_debug(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func vmw_thp_func = { - .takedown = vmw_thp_takedown, .get_node = vmw_thp_get_node, .put_node = vmw_thp_put_node, .debug = vmw_thp_debug -- GitLab From cff099e70cc1387f3f291c4a6c265419a9aabb6d Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:02 +1000 Subject: [PATCH 0275/1494] drm/vram_helper: call explicit mm takedown Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-30-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index d7c0fdf82eb64..2099851c017e7 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1127,6 +1127,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm) { + ttm_range_man_fini(&vmm->bdev, &vmm->bdev.man[TTM_PL_VRAM]); ttm_bo_device_release(&vmm->bdev); } -- GitLab From 058b5e34d8e62c12cd5cf56d86b2a2ebf1bcdf33 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:03 +1000 Subject: [PATCH 0276/1494] drm/nouveau: use new cleanup paths Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-31-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 41 ++++++++++++++++++++------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index cfcbecd332ef0..bb310719e3f5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -31,12 +31,6 @@ #include <core/tegra.h> -static int -nouveau_manager_fini(struct ttm_mem_type_manager *man) -{ - return 0; -} - static void nouveau_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg) { @@ -70,7 +64,6 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nouveau_vram_manager = { - .takedown = nouveau_manager_fini, .get_node = nouveau_vram_manager_new, .put_node = nouveau_manager_del, }; @@ -94,7 +87,6 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nouveau_gart_manager = { - .takedown = nouveau_manager_fini, .get_node = nouveau_gart_manager_new, .put_node = nouveau_manager_del, }; @@ -127,7 +119,6 @@ nv04_gart_manager_new(struct ttm_mem_type_manager *man, } const struct ttm_mem_type_manager_func nv04_gart_manager = { - .takedown = nouveau_manager_fini, .get_node = nv04_gart_manager_new, .put_node = nouveau_manager_del, }; @@ -192,6 +183,19 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) } } +static void +nouveau_ttm_fini_vram(struct nouveau_drm *drm) +{ + struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_VRAM]; + + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); + ttm_mem_type_manager_cleanup(man); + } else + ttm_range_man_fini(&drm->ttm.bdev, man); +} + static int nouveau_ttm_init_gtt(struct nouveau_drm *drm) { @@ -221,6 +225,21 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) return 0; } +static void +nouveau_ttm_fini_gtt(struct nouveau_drm *drm) +{ + struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_TT]; + + if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA && + drm->agp.bridge) + ttm_range_man_fini(&drm->ttm.bdev, man); + else { + ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); + ttm_mem_type_manager_cleanup(man); + } +} + int nouveau_ttm_init(struct nouveau_drm *drm) { @@ -310,8 +329,8 @@ nouveau_ttm_fini(struct nouveau_drm *drm) { struct nvkm_device *device = nvxx_device(&drm->client.device); - ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&drm->ttm.bdev, TTM_PL_TT); + nouveau_ttm_fini_vram(drm); + nouveau_ttm_fini_gtt(drm); ttm_bo_device_release(&drm->ttm.bdev); -- GitLab From f0fe3f7bc53c34aad6046c28f1380223c3127bf4 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:04 +1000 Subject: [PATCH 0277/1494] drm/radeon/ttm: use new takedown paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-32-airlied@gmail.com --- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 40959cea4476b..18e6dca9b77eb 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -827,8 +827,8 @@ void radeon_ttm_fini(struct radeon_device *rdev) } radeon_bo_unref(&rdev->stolen_vga_memory); } - ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT); + ttm_range_man_fini(&rdev->mman.bdev, &rdev->mman.bdev.man[TTM_PL_VRAM]); + ttm_range_man_fini(&rdev->mman.bdev, &rdev->mman.bdev.man[TTM_PL_TT]); ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); rdev->mman.initialized = false; -- GitLab From 06feb5df1af54195e4fd67af7d8c6ae789693e4a Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:05 +1000 Subject: [PATCH 0278/1494] drm/qxl/ttm: use new takedown path Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-33-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index b116064bd690b..3e3c7adaff91c 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -267,8 +267,8 @@ int qxl_ttm_init(struct qxl_device *qdev) void qxl_ttm_fini(struct qxl_device *qdev) { - ttm_bo_clean_mm(&qdev->mman.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&qdev->mman.bdev, TTM_PL_PRIV); + ttm_range_man_fini(&qdev->mman.bdev, &qdev->mman.bdev.man[TTM_PL_VRAM]); + ttm_range_man_fini(&qdev->mman.bdev, &qdev->mman.bdev.man[TTM_PL_PRIV]); ttm_bo_device_release(&qdev->mman.bdev); DRM_INFO("qxl: ttm finalized\n"); } -- GitLab From 6eee6675e01da7f084da70a421e487d4c6092772 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:06 +1000 Subject: [PATCH 0279/1494] drm/vmwgfx: fix gmrid takedown paths to new interface Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-34-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 9 ++++----- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 11 ++++++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index d37dbe3379689..cac83b581e400 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -996,9 +996,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) vmw_kms_close(dev_priv); out_no_kms: if (dev_priv->has_mob) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); + vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); if (dev_priv->has_gmr) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); + vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); vmw_vram_manager_fini(dev_priv); out_no_vram: (void)ttm_bo_device_release(&dev_priv->bdev); @@ -1047,12 +1047,11 @@ static void vmw_driver_unload(struct drm_device *dev) vmw_overlay_close(dev_priv); if (dev_priv->has_gmr) - (void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR); - (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); + vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR); vmw_release_device_early(dev_priv); if (dev_priv->has_mob) - (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB); + vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB); vmw_vram_manager_fini(dev_priv); (void) ttm_bo_device_release(&dev_priv->bdev); drm_vma_offset_manager_destroy(&dev_priv->vma_manager); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index c6530d7b6d513..aa763c6b11462 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1222,6 +1222,7 @@ int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); */ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); +void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); /** * Prime - vmwgfx_prime.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index 141fb14e35830..ec1b5bb01a933 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -133,20 +133,25 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) return 0; } -static int vmw_gmrid_man_takedown(struct ttm_mem_type_manager *man) +void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) { + struct ttm_mem_type_manager *man = &dev_priv->bdev.man[type]; struct vmwgfx_gmrid_man *gman = (struct vmwgfx_gmrid_man *)man->priv; + ttm_mem_type_manager_disable(man); + + ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); + if (gman) { ida_destroy(&gman->gmr_ida); kfree(gman); } - return 0; + + ttm_mem_type_manager_cleanup(man); } static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { - .takedown = vmw_gmrid_man_takedown, .get_node = vmw_gmrid_man_get_node, .put_node = vmw_gmrid_man_put_node, }; -- GitLab From 085097e5ae5e622358554ef773bccefb416b3df1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:07 +1000 Subject: [PATCH 0280/1494] drm/ttm: remove range manager legacy takedown path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now all drivers have been converted, drop the non-driver path. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-35-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_manager.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 96da22be672bb..86bf5e71e9598 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -129,26 +129,11 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_range_man_init); -static int ttm_bo_man_takedown_private(struct ttm_mem_type_manager *man) -{ - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; - struct drm_mm *mm = &rman->mm; - - spin_lock(&rman->lock); - if (drm_mm_clean(mm)) { - drm_mm_takedown(mm); - spin_unlock(&rman->lock); - kfree(rman); - man->priv = NULL; - return 0; - } - spin_unlock(&rman->lock); - return -EBUSY; -} - int ttm_range_man_fini(struct ttm_bo_device *bdev, struct ttm_mem_type_manager *man) { + struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct drm_mm *mm = &rman->mm; int ret; ttm_mem_type_manager_disable(man); @@ -157,7 +142,13 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, if (ret) return ret; - ttm_bo_man_takedown_private(man); + spin_lock(&rman->lock); + drm_mm_clean(mm); + drm_mm_takedown(mm); + spin_unlock(&rman->lock); + kfree(rman); + man->priv = NULL; + ttm_mem_type_manager_cleanup(man); return 0; } @@ -174,7 +165,6 @@ static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, } static const struct ttm_mem_type_manager_func ttm_bo_manager_func = { - .takedown = ttm_bo_man_takedown_private, .get_node = ttm_bo_man_get_node, .put_node = ttm_bo_man_put_node, .debug = ttm_bo_man_debug -- GitLab From 0cf0a7984268c64e906b63a96df3e331ca61f989 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:08 +1000 Subject: [PATCH 0281/1494] drm/ttm: make TTM responsible for cleaning system only. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers should all be cleaning up their memory managers themselves now, so let the core just clean the system one up. Remove the legacy cleaning interface. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-36-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 54 +++------------------------------ include/drm/ttm/ttm_bo_api.h | 28 ----------------- include/drm/ttm/ttm_bo_driver.h | 10 ------ 3 files changed, 4 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 480d23fa80996..400f025ce04ab 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1450,42 +1450,6 @@ int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_mem_type_manager_force_list_clean); -int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) -{ - struct ttm_mem_type_manager *man; - int ret = -EINVAL; - - if (mem_type >= TTM_NUM_MEM_TYPES) { - pr_err("Illegal memory type %d\n", mem_type); - return ret; - } - man = &bdev->man[mem_type]; - - if (!man->has_type) { - pr_err("Trying to take down uninitialized memory manager type %u\n", - mem_type); - return ret; - } - - ttm_mem_type_manager_disable(man); - - ret = 0; - if (mem_type > 0) { - ret = ttm_mem_type_manager_force_list_clean(bdev, man); - if (ret) { - pr_err("Cleanup eviction failed\n"); - return ret; - } - - if (man->func->takedown) - ret = (*man->func->takedown)(man); - } - - ttm_mem_type_manager_cleanup(man); - - return ret; -} -EXPORT_SYMBOL(ttm_bo_clean_mm); int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) { @@ -1589,21 +1553,11 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) { struct ttm_bo_global *glob = &ttm_bo_glob; int ret = 0; - unsigned i = TTM_NUM_MEM_TYPES; + unsigned i; struct ttm_mem_type_manager *man; - while (i--) { - man = &bdev->man[i]; - if (man->has_type) { - man->use_type = false; - if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) { - ret = -EBUSY; - pr_err("DRM memory manager type %d is not clean\n", - i); - } - man->has_type = false; - } - } + man = &bdev->man[TTM_PL_SYSTEM]; + ttm_mem_type_manager_disable(man); mutex_lock(&ttm_global_mutex); list_del(&bdev->device_list); @@ -1616,7 +1570,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) spin_lock(&glob->lru_lock); for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) - if (list_empty(&bdev->man[0].lru[0])) + if (list_empty(&man->lru[0])) pr_debug("Swap list %d was clean\n", i); spin_unlock(&glob->lru_lock); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 56d207b983e98..045f283d79e8f 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -546,34 +546,6 @@ void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, struct ttm_mem_type_manager *man, unsigned long p_size); -/** - * ttm_bo_clean_mm - * - * @bdev: Pointer to a ttm_bo_device struct. - * @mem_type: The memory type. - * - * Take down a manager for a given memory type after first walking - * the LRU list to evict any buffers left alive. - * - * Normally, this function is part of lastclose() or unload(), and at that - * point there shouldn't be any buffers left created by user-space, since - * there should've been removed by the file descriptor release() method. - * However, before this function is run, make sure to signal all sync objects, - * and verify that the delayed delete queue is empty. The driver must also - * make sure that there are no NO_EVICT buffers present in this memory type - * when the call is made. - * - * If this function is part of a VT switch, the caller must make sure that - * there are no appications currently validating buffers before this - * function is called. The caller can do that by first taking the - * struct ttm_bo_device::ttm_lock in write mode. - * - * Returns: - * -EINVAL: invalid or uninitialized memory type. - * -EBUSY: There are still buffers left in this memory type. - */ -int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type); - /** * ttm_bo_evict_mm * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 811ace1416b37..c76301a808ae7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -48,16 +48,6 @@ struct ttm_mem_type_manager; struct ttm_mem_type_manager_func { - /** - * struct ttm_mem_type_manager member takedown - * - * @man: Pointer to a memory type manager. - * - * Called to undo the setup done in init. All allocated resources - * should be freed. - */ - int (*takedown)(struct ttm_mem_type_manager *man); - /** * struct ttm_mem_type_manager member get_node * -- GitLab From 9eca33f4a13919bb17b8a02809a32f8299f5c9bf Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:09 +1000 Subject: [PATCH 0282/1494] drm/ttm: add wrapper to get manager from bdev. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow different abstractions later. Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-37-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 34 +++++++++++++++---------------- drivers/gpu/drm/ttm/ttm_bo_util.c | 20 +++++++++--------- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +- include/drm/ttm/ttm_bo_driver.h | 6 ++++++ 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 400f025ce04ab..7474679a2364c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -108,7 +108,7 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, return; drm_printf(&p, " placement[%d]=0x%08X (%d)\n", i, placement->placement[i].flags, mem_type); - man = &bo->bdev->man[mem_type]; + man = ttm_manager_type(bo->bdev, mem_type); ttm_mem_type_manager_debug(man, &p); } } @@ -157,7 +157,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, if (mem->placement & TTM_PL_FLAG_NO_EVICT) return; - man = &bdev->man[mem->mem_type]; + man = ttm_manager_type(bdev, mem->mem_type); list_add_tail(&bo->lru, &man->lru[bo->priority]); if (man->use_tt && bo->ttm && @@ -232,7 +232,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) dma_resv_assert_held(pos->first->base.resv); dma_resv_assert_held(pos->last->base.resv); - man = &pos->first->bdev->man[TTM_PL_TT]; + man = ttm_manager_type(pos->first->bdev, TTM_PL_TT); list_bulk_move_tail(&man->lru[i], &pos->first->lru, &pos->last->lru); } @@ -247,7 +247,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) dma_resv_assert_held(pos->first->base.resv); dma_resv_assert_held(pos->last->base.resv); - man = &pos->first->bdev->man[TTM_PL_VRAM]; + man = ttm_manager_type(pos->first->bdev, TTM_PL_VRAM); list_bulk_move_tail(&man->lru[i], &pos->first->lru, &pos->last->lru); } @@ -273,8 +273,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *old_man = &bdev->man[bo->mem.mem_type]; - struct ttm_mem_type_manager *new_man = &bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *old_man = ttm_manager_type(bdev, bo->mem.mem_type); + struct ttm_mem_type_manager *new_man = ttm_manager_type(bdev, mem->mem_type); int ret; ret = ttm_mem_io_lock(old_man, true); @@ -340,7 +340,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, return 0; out_err: - new_man = &bdev->man[bo->mem.mem_type]; + new_man = ttm_manager_type(bdev, bo->mem.mem_type); if (!new_man->use_tt) { ttm_tt_destroy(bo->ttm); bo->ttm = NULL; @@ -552,7 +552,7 @@ static void ttm_bo_release(struct kref *kref) struct ttm_buffer_object *bo = container_of(kref, struct ttm_buffer_object, kref); struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); size_t acc_size = bo->acc_size; int ret; @@ -844,7 +844,7 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); mem->mm_node = NULL; if (!man->func || !man->func->get_node) @@ -855,7 +855,7 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); if (!man->func || !man->func->put_node) return; @@ -910,7 +910,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); struct ww_acquire_ctx *ticket; int ret; @@ -1000,7 +1000,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, if (ret) return ret; - man = &bdev->man[mem_type]; + man = ttm_manager_type(bdev, mem_type); if (!man->has_type || !man->use_type) return -EBUSY; @@ -1063,7 +1063,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, if (unlikely(ret)) goto error; - man = &bdev->man[mem->mem_type]; + man = ttm_manager_type(bdev, mem->mem_type); ret = ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu); if (unlikely(ret)) { ttm_bo_mem_put(bo, mem); @@ -1453,7 +1453,7 @@ EXPORT_SYMBOL(ttm_mem_type_manager_force_list_clean); int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) { - struct ttm_mem_type_manager *man = &bdev->man[mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem_type); if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) { pr_err("Illegal memory manager memory type %u\n", mem_type); @@ -1556,7 +1556,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) unsigned i; struct ttm_mem_type_manager *man; - man = &bdev->man[TTM_PL_SYSTEM]; + man = ttm_manager_type(bdev, TTM_PL_SYSTEM); ttm_mem_type_manager_disable(man); mutex_lock(&ttm_global_mutex); @@ -1583,7 +1583,7 @@ EXPORT_SYMBOL(ttm_bo_device_release); static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) { - struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_SYSTEM]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, TTM_PL_SYSTEM); /* * Initialize the system memory buffer type. @@ -1647,7 +1647,7 @@ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); ttm_mem_io_lock(man, false); ttm_bo_unmap_virtual_locked(bo); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 1f502be0b646c..879c8ded0cd8c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -129,7 +129,7 @@ static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; if (mem->bus.io_reserved_count++) @@ -162,7 +162,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev, int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) { - struct ttm_mem_type_manager *man = &bo->bdev->man[bo->mem.mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); struct ttm_mem_reg *mem = &bo->mem; int ret; @@ -195,7 +195,7 @@ static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, void **virtual) { - struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; void *addr; @@ -232,7 +232,7 @@ static void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, { struct ttm_mem_type_manager *man; - man = &bdev->man[mem->mem_type]; + man = ttm_manager_type(bdev, mem->mem_type); if (virtual && mem->bus.addr == NULL) iounmap(virtual); @@ -303,7 +303,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, new_mem->mem_type); struct ttm_tt *ttm = bo->ttm; struct ttm_mem_reg *old_mem = &bo->mem; struct ttm_mem_reg old_copy = *old_mem; @@ -571,7 +571,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, struct ttm_bo_kmap_obj *map) { struct ttm_mem_type_manager *man = - &bo->bdev->man[bo->mem.mem_type]; + ttm_manager_type(bo->bdev, bo->mem.mem_type); unsigned long offset, size; int ret; @@ -601,7 +601,7 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) { struct ttm_buffer_object *bo = map->bo; struct ttm_mem_type_manager *man = - &bo->bdev->man[bo->mem.mem_type]; + ttm_manager_type(bo->bdev, bo->mem.mem_type); if (!map->virtual) return; @@ -634,7 +634,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, new_mem->mem_type); struct ttm_mem_reg *old_mem = &bo->mem; int ret; struct ttm_buffer_object *ghost_obj; @@ -697,8 +697,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_type_manager *from = &bdev->man[old_mem->mem_type]; - struct ttm_mem_type_manager *to = &bdev->man[new_mem->mem_type]; + struct ttm_mem_type_manager *from = ttm_manager_type(bdev, old_mem->mem_type); + struct ttm_mem_type_manager *to = ttm_manager_type(bdev, new_mem->mem_type); int ret; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 1e2820b06c6af..db4e21d11967d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -282,7 +282,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, vm_fault_t ret = VM_FAULT_NOPAGE; unsigned long address = vmf->address; struct ttm_mem_type_manager *man = - &bdev->man[bo->mem.mem_type]; + ttm_manager_type(bdev, bo->mem.mem_type); /* * Refuse to fault imported pages. This should be handled diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index c76301a808ae7..c8ea5eab719d3 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -444,6 +444,12 @@ struct ttm_bo_device { bool no_retry; }; +static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device *bdev, + int mem_type) +{ + return &bdev->man[mem_type]; +} + /** * struct ttm_lru_bulk_move_pos * -- GitLab From 6c28aed6e5b7fa9538ad1a468e3dd5a94ebe5b19 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:10 +1000 Subject: [PATCH 0283/1494] drm/amdgfx/ttm: use wrapper to get ttm memory managers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-38-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 12 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 +++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 12 +++++------ 8 files changed, 39 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index ad59ac4423b8b..ba4d11e8a960e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -517,8 +517,9 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; + struct ttm_mem_type_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - return amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + return amdgpu_vram_mgr_usage(vram_man); } uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a25fb59c127c0..5ef7b3b7c9af8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -299,7 +299,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, { s64 time_us, increment_us; u64 free_vram, total_vram, used_vram; - + struct ttm_mem_type_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); /* Allow a maximum of 200 accumulated ms. This is basically per-IB * throttling. * @@ -316,7 +316,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, } total_vram = adev->gmc.real_vram_size - atomic64_read(&adev->vram_pin_size); - used_vram = amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + used_vram = amdgpu_vram_mgr_usage(vram_man); free_vram = used_vram >= total_vram ? 0 : total_vram - used_vram; spin_lock(&adev->mm_stats.lock); @@ -363,7 +363,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, if (!amdgpu_gmc_vram_full_visible(&adev->gmc)) { u64 total_vis_vram = adev->gmc.visible_vram_size; u64 used_vis_vram = - amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + amdgpu_vram_mgr_vis_usage(vram_man); if (used_vis_vram < total_vis_vram) { u64 free_vis_vram = total_vis_vram - used_vis_vram; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index a027a8f7b2819..a93200fa30980 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3839,7 +3839,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, amdgpu_virt_init_data_exchange(adev); /* we need recover gart prior to run SMC/CP/SDMA resume */ - amdgpu_gtt_mgr_recover(&adev->mman.bdev.man[TTM_PL_TT]); + amdgpu_gtt_mgr_recover(ttm_manager_type(&adev->mman.bdev, TTM_PL_TT)); r = amdgpu_device_fw_loading(adev); if (r) @@ -4037,8 +4037,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, amdgpu_inc_vram_lost(tmp_adev); } - r = amdgpu_gtt_mgr_recover( - &tmp_adev->mman.bdev.man[TTM_PL_TT]); + r = amdgpu_gtt_mgr_recover(ttm_manager_type(&tmp_adev->mman.bdev, TTM_PL_TT)); if (r) goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 699cb0dff3512..5562ad2104d6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -48,9 +48,9 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); return snprintf(buf, PAGE_SIZE, "%llu\n", - (adev->mman.bdev.man[TTM_PL_TT].size) * PAGE_SIZE); + man->size * PAGE_SIZE); } /** @@ -66,9 +66,9 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); return snprintf(buf, PAGE_SIZE, "%llu\n", - amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT])); + amdgpu_gtt_mgr_usage(man)); } static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO, @@ -87,7 +87,7 @@ static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; */ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); struct amdgpu_gtt_mgr *mgr; uint64_t start, size; int ret; @@ -135,7 +135,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) */ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_TT]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); struct amdgpu_gtt_mgr *mgr = man->priv; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d7e17e34fee17..134cca1af7446 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -579,13 +579,13 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file ui64 = atomic64_read(&adev->num_vram_cpu_page_faults); return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; case AMDGPU_INFO_VRAM_USAGE: - ui64 = amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + ui64 = amdgpu_vram_mgr_usage(ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM)); return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; case AMDGPU_INFO_VIS_VRAM_USAGE: - ui64 = amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + ui64 = amdgpu_vram_mgr_vis_usage(ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM)); return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; case AMDGPU_INFO_GTT_USAGE: - ui64 = amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT]); + ui64 = amdgpu_gtt_mgr_usage(ttm_manager_type(&adev->mman.bdev, TTM_PL_TT)); return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; case AMDGPU_INFO_GDS_CONFIG: { struct drm_amdgpu_info_gds gds_info; @@ -608,7 +608,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file min(adev->gmc.visible_vram_size - atomic64_read(&adev->visible_pin_size), vram_gtt.vram_size); - vram_gtt.gtt_size = adev->mman.bdev.man[TTM_PL_TT].size; + vram_gtt.gtt_size = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT)->size; vram_gtt.gtt_size *= PAGE_SIZE; vram_gtt.gtt_size -= atomic64_read(&adev->gart_pin_size); return copy_to_user(out, &vram_gtt, @@ -616,14 +616,17 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file } case AMDGPU_INFO_MEMORY: { struct drm_amdgpu_memory_info mem; - + struct ttm_mem_type_manager *vram_man = + ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_mem_type_manager *gtt_man = + ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); memset(&mem, 0, sizeof(mem)); mem.vram.total_heap_size = adev->gmc.real_vram_size; mem.vram.usable_heap_size = adev->gmc.real_vram_size - atomic64_read(&adev->vram_pin_size) - AMDGPU_VM_RESERVED_VRAM; mem.vram.heap_usage = - amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + amdgpu_vram_mgr_usage(vram_man); mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4; mem.cpu_accessible_vram.total_heap_size = @@ -633,16 +636,16 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file atomic64_read(&adev->visible_pin_size), mem.vram.usable_heap_size); mem.cpu_accessible_vram.heap_usage = - amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]); + amdgpu_vram_mgr_vis_usage(vram_man); mem.cpu_accessible_vram.max_allocation = mem.cpu_accessible_vram.usable_heap_size * 3 / 4; - mem.gtt.total_heap_size = adev->mman.bdev.man[TTM_PL_TT].size; + mem.gtt.total_heap_size = gtt_man->size; mem.gtt.total_heap_size *= PAGE_SIZE; mem.gtt.usable_heap_size = mem.gtt.total_heap_size - atomic64_read(&adev->gart_pin_size); mem.gtt.heap_usage = - amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT]); + amdgpu_gtt_mgr_usage(gtt_man); mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4; return copy_to_user(out, &mem, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5ac7b55614750..ced418cba2f73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -449,7 +449,7 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, * allow fall back to GTT */ if (domain & AMDGPU_GEM_DOMAIN_GTT) { - man = &adev->mman.bdev.man[TTM_PL_TT]; + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); if (size < (man->size << PAGE_SHIFT)) return true; @@ -458,7 +458,7 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, } if (domain & AMDGPU_GEM_DOMAIN_VRAM) { - man = &adev->mman.bdev.man[TTM_PL_VRAM]; + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); if (size < (man->size << PAGE_SHIFT)) return true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 95aedfc717e58..207ba70a7a394 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -66,7 +66,7 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, unsigned int type, uint64_t size) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[type]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, type); man->available_caching = TTM_PL_FLAG_UNCACHED; man->default_caching = TTM_PL_FLAG_UNCACHED; @@ -1996,9 +1996,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_vram_mgr_fini(adev); amdgpu_gtt_mgr_fini(adev); - ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_GDS]); - ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_GWS]); - ttm_range_man_fini(&adev->mman.bdev, &adev->mman.bdev.man[AMDGPU_PL_OA]); + ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_GDS)); + ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_GWS)); + ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_OA)); ttm_bo_device_release(&adev->mman.bdev); adev->mman.initialized = false; DRM_INFO("amdgpu: ttm finalized\n"); @@ -2015,7 +2015,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) */ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); uint64_t size; int r; @@ -2237,7 +2237,7 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data) unsigned ttm_pl = (uintptr_t)node->info_ent->data; struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = dev->dev_private; - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[ttm_pl]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, ttm_pl); struct drm_printer p = drm_seq_file_printer(m); man->func->debug(man, &p); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index b33c5164ff7af..d9818cee973a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -82,9 +82,9 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); return snprintf(buf, PAGE_SIZE, "%llu\n", - amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); + amdgpu_vram_mgr_usage(man)); } /** @@ -100,9 +100,9 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); return snprintf(buf, PAGE_SIZE, "%llu\n", - amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); + amdgpu_vram_mgr_vis_usage(man)); } static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, @@ -170,7 +170,7 @@ static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; */ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); struct amdgpu_vram_mgr *mgr; int ret; @@ -207,7 +207,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) */ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = &adev->mman.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); struct amdgpu_vram_mgr *mgr = man->priv; int ret; -- GitLab From 3004add06d1c99ea36bf6120b9ff9427e301ad95 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:11 +1000 Subject: [PATCH 0284/1494] drm/vram-helper: use wrapper to access memory managers Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-39-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 2099851c017e7..a01768adb96dd 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1075,7 +1075,7 @@ static int drm_vram_mm_debugfs(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_vram_mm *vmm = node->minor->dev->vram_mm; - struct ttm_mem_type_manager *man = &vmm->bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM); struct drm_printer p = drm_seq_file_printer(m); ttm_mem_type_manager_debug(man, &p); @@ -1103,7 +1103,7 @@ EXPORT_SYMBOL(drm_vram_mm_debugfs_init); static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, uint64_t vram_base, size_t vram_size) { - struct ttm_mem_type_manager *man = &vmm->bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM); int ret; vmm->vram_base = vram_base; @@ -1127,7 +1127,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm) { - ttm_range_man_fini(&vmm->bdev, &vmm->bdev.man[TTM_PL_VRAM]); + ttm_range_man_fini(&vmm->bdev, ttm_manager_type(&vmm->bdev, TTM_PL_VRAM)); ttm_bo_device_release(&vmm->bdev); } -- GitLab From f301da74a417a77b3a8ff96e87c219d5288a939f Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:12 +1000 Subject: [PATCH 0285/1494] drm/nouveau/ttm: use wrapper to access memory managers Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-40-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index bb310719e3f5a..cc6cf04553dd9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -156,7 +156,7 @@ nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind) static int nouveau_ttm_init_vram(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); struct nvif_mmu *mmu = &drm->client.mmu; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; @@ -186,7 +186,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) static void nouveau_ttm_fini_vram(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { ttm_mem_type_manager_disable(man); @@ -199,7 +199,7 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) static int nouveau_ttm_init_gtt(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_TT]; + struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_TT); unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; man->use_tt = true; if (drm->agp.bridge) { @@ -228,7 +228,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) static void nouveau_ttm_fini_gtt(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = &drm->ttm.bdev.man[TTM_PL_TT]; + struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_TT); if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA && drm->agp.bridge) -- GitLab From 3d3b4fb9aab3b718d8d16e621379ea402b7444a1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:13 +1000 Subject: [PATCH 0286/1494] drm/qxl/ttm: use wrapper to access memory manager Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-41-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_ttm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 3e3c7adaff91c..a0c91bce1d2e4 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -220,7 +220,7 @@ static int qxl_ttm_init_mem_type(struct qxl_device *qdev, unsigned int type, uint64_t size) { - struct ttm_mem_type_manager *man = &qdev->mman.bdev.man[type]; + struct ttm_mem_type_manager *man = ttm_manager_type(&qdev->mman.bdev, type); man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; @@ -267,8 +267,8 @@ int qxl_ttm_init(struct qxl_device *qdev) void qxl_ttm_fini(struct qxl_device *qdev) { - ttm_range_man_fini(&qdev->mman.bdev, &qdev->mman.bdev.man[TTM_PL_VRAM]); - ttm_range_man_fini(&qdev->mman.bdev, &qdev->mman.bdev.man[TTM_PL_PRIV]); + ttm_range_man_fini(&qdev->mman.bdev, ttm_manager_type(&qdev->mman.bdev, TTM_PL_VRAM)); + ttm_range_man_fini(&qdev->mman.bdev, ttm_manager_type(&qdev->mman.bdev, TTM_PL_PRIV)); ttm_bo_device_release(&qdev->mman.bdev); DRM_INFO("qxl: ttm finalized\n"); } @@ -303,9 +303,9 @@ void qxl_ttm_debugfs_init(struct qxl_device *qdev) qxl_mem_types_list[i].show = &qxl_mm_dump_table; qxl_mem_types_list[i].driver_features = 0; if (i == 0) - qxl_mem_types_list[i].data = &qdev->mman.bdev.man[TTM_PL_VRAM]; + qxl_mem_types_list[i].data = ttm_manager_type(&qdev->mman.bdev, TTM_PL_VRAM); else - qxl_mem_types_list[i].data = &qdev->mman.bdev.man[TTM_PL_PRIV]; + qxl_mem_types_list[i].data = ttm_manager_type(&qdev->mman.bdev, TTM_PL_PRIV); } qxl_debugfs_add_files(qdev, qxl_mem_types_list, i); -- GitLab From 47c0550f5ebd06d714475b9b722b08a6a7ab907b Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:14 +1000 Subject: [PATCH 0287/1494] drm/radeon/ttm: use wrapper to access memory manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-42-airlied@gmail.com --- drivers/gpu/drm/radeon/radeon_gem.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 44157ada9b0ea..3ec028dba7390 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -226,7 +226,7 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, struct drm_radeon_gem_info *args = data; struct ttm_mem_type_manager *man; - man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM); args->vram_size = (u64)man->size << PAGE_SHIFT; args->vram_visible = rdev->mc.visible_vram_size; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 18e6dca9b77eb..671ca63d420c4 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -68,7 +68,7 @@ struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) static int radeon_ttm_init_vram(struct radeon_device *rdev) { - struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM); man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -79,7 +79,7 @@ static int radeon_ttm_init_vram(struct radeon_device *rdev) static int radeon_ttm_init_gtt(struct radeon_device *rdev) { - struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[TTM_PL_TT]; + struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_TT); man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; @@ -827,8 +827,8 @@ void radeon_ttm_fini(struct radeon_device *rdev) } radeon_bo_unref(&rdev->stolen_vga_memory); } - ttm_range_man_fini(&rdev->mman.bdev, &rdev->mman.bdev.man[TTM_PL_VRAM]); - ttm_range_man_fini(&rdev->mman.bdev, &rdev->mman.bdev.man[TTM_PL_TT]); + ttm_range_man_fini(&rdev->mman.bdev, ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM)); + ttm_range_man_fini(&rdev->mman.bdev, ttm_manager_type(&rdev->mman.bdev, TTM_PL_TT)); ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); rdev->mman.initialized = false; @@ -844,7 +844,7 @@ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) if (!rdev->mman.initialized) return; - man = &rdev->mman.bdev.man[TTM_PL_VRAM]; + man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM); /* this just adjusts TTM size idea, which sets lpfn to the correct value */ man->size = size >> PAGE_SHIFT; } @@ -898,7 +898,7 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) unsigned ttm_pl = *(int*)node->info_ent->data; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - struct ttm_mem_type_manager *man = &rdev->mman.bdev.man[ttm_pl]; + struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, ttm_pl); struct drm_printer p = drm_seq_file_printer(m); man->func->debug(man, &p); -- GitLab From 089cafc198ecaa6cf031e3de8377d106e569c767 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:15 +1000 Subject: [PATCH 0288/1494] drm/vmwgfx/ttm: use wrapper to access memory manager Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-43-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 23 +++++++++++-------- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index cac83b581e400..c30021d0215ce 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -634,7 +634,7 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) ret = ttm_range_man_init(&dev_priv->bdev, man, dev_priv->vram_size >> PAGE_SHIFT); #endif - dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; + ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM)->use_type = false; return ret; } @@ -644,7 +644,7 @@ static void vmw_vram_manager_fini(struct vmw_private *dev_priv) vmw_thp_fini(dev_priv); #else ttm_bo_man_fini(&dev_priv->bdev, - &dev_priv->bdev.man[TTM_PL_VRAM]); + ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM)); #endif } @@ -887,7 +887,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) DRM_ERROR("Failed initializing TTM buffer object driver.\n"); goto out_no_bdev; } - dev_priv->bdev.man[TTM_PL_SYSTEM].available_caching = + ttm_manager_type(&dev_priv->bdev, TTM_PL_SYSTEM)->available_caching = TTM_PL_FLAG_CACHED; /* @@ -1194,10 +1194,12 @@ static void vmw_master_drop(struct drm_device *dev, */ static void __vmw_svga_enable(struct vmw_private *dev_priv) { + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + spin_lock(&dev_priv->svga_lock); - if (!dev_priv->bdev.man[TTM_PL_VRAM].use_type) { + if (!man->use_type) { vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE); - dev_priv->bdev.man[TTM_PL_VRAM].use_type = true; + man->use_type = true; } spin_unlock(&dev_priv->svga_lock); } @@ -1223,9 +1225,11 @@ void vmw_svga_enable(struct vmw_private *dev_priv) */ static void __vmw_svga_disable(struct vmw_private *dev_priv) { + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + spin_lock(&dev_priv->svga_lock); - if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { - dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; + if (man->use_type) { + man->use_type = false; vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_HIDE | SVGA_REG_ENABLE_ENABLE); @@ -1242,6 +1246,7 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) */ void vmw_svga_disable(struct vmw_private *dev_priv) { + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); /* * Disabling SVGA will turn off device modesetting capabilities, so * notify KMS about that so that it doesn't cache atomic state that @@ -1257,8 +1262,8 @@ void vmw_svga_disable(struct vmw_private *dev_priv) vmw_kms_lost_device(dev_priv->dev); ttm_write_lock(&dev_priv->reservation_sem, false); spin_lock(&dev_priv->svga_lock); - if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { - dev_priv->bdev.man[TTM_PL_VRAM].use_type = false; + if (man->use_type) { + man->use_type = false; spin_unlock(&dev_priv->svga_lock); if (ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM)) DRM_ERROR("Failed evicting VRAM buffers.\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index ec1b5bb01a933..54c85a59dd8b1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -98,7 +98,7 @@ static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func; int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) { - struct ttm_mem_type_manager *man = &dev_priv->bdev.man[type]; + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); struct vmwgfx_gmrid_man *gman = kzalloc(sizeof(*gman), GFP_KERNEL); @@ -135,7 +135,7 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) { - struct ttm_mem_type_manager *man = &dev_priv->bdev.man[type]; + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); struct vmwgfx_gmrid_man *gman = (struct vmwgfx_gmrid_man *)man->priv; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 548f152b99630..720a24214c744 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -117,7 +117,7 @@ static void vmw_thp_put_node(struct ttm_mem_type_manager *man, int vmw_thp_init(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); struct vmw_thp_manager *rman; man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; @@ -137,7 +137,7 @@ int vmw_thp_init(struct vmw_private *dev_priv) void vmw_thp_fini(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; + struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; struct drm_mm *mm = &rman->mm; int ret; -- GitLab From 01057278bc68610389e32ffe3a8335aff38a84ce Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:16 +1000 Subject: [PATCH 0289/1494] drm/ttm: rename manager variable to make sure wrapper is used. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other users of this should notice this change and switch to wrapper. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-44-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- include/drm/ttm/ttm_bo_driver.h | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 7474679a2364c..4d87ee98467fe 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1615,7 +1615,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, bdev->driver = driver; - memset(bdev->man, 0, sizeof(bdev->man)); + memset(bdev->man_priv, 0, sizeof(bdev->man_priv)); ttm_bo_init_sysman(bdev); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index c8ea5eab719d3..f97c047b6a3a9 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -415,7 +415,10 @@ struct ttm_bo_device { */ struct list_head device_list; struct ttm_bo_driver *driver; - struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES]; + /* + * access via ttm_manager_type. + */ + struct ttm_mem_type_manager man_priv[TTM_NUM_MEM_TYPES]; /* * Protected by internal locks. @@ -447,7 +450,7 @@ struct ttm_bo_device { static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device *bdev, int mem_type) { - return &bdev->man[mem_type]; + return &bdev->man_priv[mem_type]; } /** -- GitLab From d398811ebfa80329269932803a6e78dc01c79bf1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:17 +1000 Subject: [PATCH 0290/1494] drm/ttm: allow drivers to provide their own manager subclasses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will get removed eventually and all drivers will use this. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-45-airlied@gmail.com --- include/drm/ttm/ttm_bo_driver.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index f97c047b6a3a9..ce15eb075241d 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -419,7 +419,7 @@ struct ttm_bo_device { * access via ttm_manager_type. */ struct ttm_mem_type_manager man_priv[TTM_NUM_MEM_TYPES]; - + struct ttm_mem_type_manager *man_drv[TTM_NUM_MEM_TYPES]; /* * Protected by internal locks. */ @@ -450,9 +450,18 @@ struct ttm_bo_device { static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device *bdev, int mem_type) { + if (bdev->man_drv[mem_type]) + return bdev->man_drv[mem_type]; return &bdev->man_priv[mem_type]; } +static inline void ttm_set_driver_manager(struct ttm_bo_device *bdev, + int type, + struct ttm_mem_type_manager *manager) +{ + bdev->man_drv[type] = manager; +} + /** * struct ttm_lru_bulk_move_pos * -- GitLab From 0af135b892bf06c1a56cb0cd9632feb34511f9ee Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:18 +1000 Subject: [PATCH 0291/1494] drm/amdgpu/ttm: use bo manager subclassing for vram/gtt mgrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-46-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 35 +++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 36 +++++++++++++------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 5562ad2104d6f..a74c6987ac140 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -25,11 +25,17 @@ #include "amdgpu.h" struct amdgpu_gtt_mgr { + struct ttm_mem_type_manager manager; struct drm_mm mm; spinlock_t lock; atomic64_t available; }; +static inline struct amdgpu_gtt_mgr *to_gtt_mgr(struct ttm_mem_type_manager *man) +{ + return container_of(man, struct amdgpu_gtt_mgr, manager); +} + struct amdgpu_gtt_node { struct drm_mm_node node; struct ttm_buffer_object *tbo; @@ -87,11 +93,16 @@ static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; */ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + struct ttm_mem_type_manager *man; struct amdgpu_gtt_mgr *mgr; uint64_t start, size; int ret; + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return -ENOMEM; + + man = &mgr->manager; man->use_tt = true; man->func = &amdgpu_gtt_mgr_func; man->available_caching = TTM_PL_MASK_CACHING; @@ -99,16 +110,11 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) ttm_mem_type_manager_init(&adev->mman.bdev, man, gtt_size >> PAGE_SHIFT); - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (!mgr) - return -ENOMEM; - start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; drm_mm_init(&mgr->mm, start, size); spin_lock_init(&mgr->lock); atomic64_set(&mgr->available, gtt_size >> PAGE_SHIFT); - man->priv = mgr; ret = device_create_file(adev->dev, &dev_attr_mem_info_gtt_total); if (ret) { @@ -121,6 +127,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) return ret; } + ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); ttm_mem_type_manager_set_used(man, true); return 0; } @@ -136,7 +143,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) { struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); int ret; ttm_mem_type_manager_disable(man); @@ -148,13 +155,13 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) spin_lock(&mgr->lock); drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); - kfree(mgr); - man->priv = NULL; device_remove_file(adev->dev, &dev_attr_mem_info_gtt_total); device_remove_file(adev->dev, &dev_attr_mem_info_gtt_used); ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, NULL); + kfree(mgr); } /** @@ -184,7 +191,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node; int r; @@ -247,7 +254,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node = mem->mm_node; if (node) { @@ -269,7 +276,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man, */ uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man) { - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); s64 result = man->size - atomic64_read(&mgr->available); return (result > 0 ? result : 0) * PAGE_SIZE; @@ -277,7 +284,7 @@ uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man) int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man) { - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node; struct drm_mm_node *mm_node; int r = 0; @@ -305,7 +312,7 @@ int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man) static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, struct drm_printer *printer) { - struct amdgpu_gtt_mgr *mgr = man->priv; + struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); spin_lock(&mgr->lock); drm_mm_print(&mgr->mm, printer); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index d9818cee973a4..04436ce6c7454 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -29,12 +29,18 @@ #include "atom.h" struct amdgpu_vram_mgr { + struct ttm_mem_type_manager manager; struct drm_mm mm; spinlock_t lock; atomic64_t usage; atomic64_t vis_usage; }; +static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_mem_type_manager *man) +{ + return container_of(man, struct amdgpu_vram_mgr, manager); +} + /** * DOC: mem_info_vram_total * @@ -170,29 +176,32 @@ static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; */ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_mem_type_manager *man; struct amdgpu_vram_mgr *mgr; int ret; + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return -ENOMEM; + + man = &mgr->manager; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; ttm_mem_type_manager_init(&adev->mman.bdev, man, adev->gmc.real_vram_size >> PAGE_SHIFT); man->func = &amdgpu_vram_mgr_func; - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (!mgr) - return -ENOMEM; drm_mm_init(&mgr->mm, 0, man->size); spin_lock_init(&mgr->lock); - man->priv = mgr; /* Add the two VRAM-related sysfs files */ ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); if (ret) DRM_ERROR("Failed to register sysfs\n"); + ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, &mgr->manager); ttm_mem_type_manager_set_used(man, true); return 0; } @@ -208,7 +217,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); int ret; ttm_mem_type_manager_disable(man); @@ -220,11 +229,12 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) spin_lock(&mgr->lock); drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); - kfree(mgr); - man->priv = NULL; + sysfs_remove_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, NULL); + kfree(mgr); } /** @@ -314,7 +324,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); struct drm_mm *mm = &mgr->mm; struct drm_mm_node *nodes; enum drm_mm_insert_mode mode; @@ -432,7 +442,7 @@ static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); struct drm_mm_node *nodes = mem->mm_node; uint64_t usage = 0, vis_usage = 0; unsigned pages = mem->num_pages; @@ -564,7 +574,7 @@ void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, */ uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man) { - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); return atomic64_read(&mgr->usage); } @@ -578,7 +588,7 @@ uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man) */ uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man) { - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); return atomic64_read(&mgr->vis_usage); } @@ -594,7 +604,7 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man) static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, struct drm_printer *printer) { - struct amdgpu_vram_mgr *mgr = man->priv; + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); spin_lock(&mgr->lock); drm_mm_print(&mgr->mm, printer); -- GitLab From 37205891d84f9269de61d6e85c24607209478a85 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:19 +1000 Subject: [PATCH 0292/1494] drm/ttm: make ttm_range_man_init/takedown take type + args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to move these to a driver allocated system Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-47-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 15 +++++------- drivers/gpu/drm/drm_gem_vram_helper.c | 10 ++++---- drivers/gpu/drm/nouveau/nouveau_ttm.c | 22 +++++++++++------- drivers/gpu/drm/qxl/qxl_ttm.c | 12 ++++------ drivers/gpu/drm/radeon/radeon_ttm.c | 31 ++++++++++++------------- drivers/gpu/drm/ttm/ttm_bo_manager.c | 19 +++++++++++---- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 13 ++++------- include/drm/ttm/ttm_bo_driver.h | 12 +++++++--- 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 207ba70a7a394..5556958540760 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -66,12 +66,9 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, unsigned int type, uint64_t size) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, type); - - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - - return ttm_range_man_init(&adev->mman.bdev, man, size >> PAGE_SHIFT); + return ttm_range_man_init(&adev->mman.bdev, type, + TTM_PL_FLAG_UNCACHED, TTM_PL_FLAG_UNCACHED, + false, size >> PAGE_SHIFT); } /** @@ -1996,9 +1993,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_vram_mgr_fini(adev); amdgpu_gtt_mgr_fini(adev); - ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_GDS)); - ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_GWS)); - ttm_range_man_fini(&adev->mman.bdev, ttm_manager_type(&adev->mman.bdev, AMDGPU_PL_OA)); + ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_GDS); + ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_GWS); + ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_OA); ttm_bo_device_release(&adev->mman.bdev); adev->mman.initialized = false; DRM_INFO("amdgpu: ttm finalized\n"); diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index a01768adb96dd..2187787f397e6 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1103,7 +1103,6 @@ EXPORT_SYMBOL(drm_vram_mm_debugfs_init); static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, uint64_t vram_base, size_t vram_size) { - struct ttm_mem_type_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM); int ret; vmm->vram_base = vram_base; @@ -1116,9 +1115,10 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, if (ret) return ret; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - ret = ttm_range_man_init(&vmm->bdev, man, vram_size >> PAGE_SHIFT); + ret = ttm_range_man_init(&vmm->bdev, TTM_PL_VRAM, + TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, + TTM_PL_FLAG_WC, false, + vram_size >> PAGE_SHIFT); if (ret) return ret; @@ -1127,7 +1127,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm) { - ttm_range_man_fini(&vmm->bdev, ttm_manager_type(&vmm->bdev, TTM_PL_VRAM)); + ttm_range_man_fini(&vmm->bdev, TTM_PL_VRAM); ttm_bo_device_release(&vmm->bdev); } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index cc6cf04553dd9..1c636723823c4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -156,16 +156,17 @@ nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind) static int nouveau_ttm_init_vram(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); struct nvif_mmu *mmu = &drm->client.mmu; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); + /* Some BARs do not support being ioremapped WC */ const u8 type = mmu->type[drm->ttm.type_vram].type; + man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; + if (type & NVIF_MEM_UNCACHED) { man->available_caching = TTM_PL_FLAG_UNCACHED; man->default_caching = TTM_PL_FLAG_UNCACHED; @@ -178,7 +179,9 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) ttm_mem_type_manager_set_used(man, true); return 0; } else { - return ttm_range_man_init(&drm->ttm.bdev, man, + return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_VRAM, + TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, + TTM_PL_FLAG_WC, false, drm->gem.vram_available >> PAGE_SHIFT); } } @@ -193,7 +196,7 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); ttm_mem_type_manager_cleanup(man); } else - ttm_range_man_fini(&drm->ttm.bdev, man); + ttm_range_man_fini(&drm->ttm.bdev, TTM_PL_VRAM); } static int @@ -216,9 +219,10 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) else if (!drm->agp.bridge) man->func = &nv04_gart_manager; else - return ttm_range_man_init(&drm->ttm.bdev, man, + return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, + TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, + TTM_PL_FLAG_WC, true, size_pages); - ttm_mem_type_manager_init(&drm->ttm.bdev, man, size_pages); ttm_mem_type_manager_set_used(man, true); @@ -232,7 +236,7 @@ nouveau_ttm_fini_gtt(struct nouveau_drm *drm) if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA && drm->agp.bridge) - ttm_range_man_fini(&drm->ttm.bdev, man); + ttm_range_man_fini(&drm->ttm.bdev, TTM_PL_TT); else { ttm_mem_type_manager_disable(man); ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index a0c91bce1d2e4..7b9f7a94332a6 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -220,12 +220,8 @@ static int qxl_ttm_init_mem_type(struct qxl_device *qdev, unsigned int type, uint64_t size) { - struct ttm_mem_type_manager *man = ttm_manager_type(&qdev->mman.bdev, type); - - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - - return ttm_range_man_init(&qdev->mman.bdev, man, size); + return ttm_range_man_init(&qdev->mman.bdev, type, TTM_PL_MASK_CACHING, + TTM_PL_FLAG_CACHED, false, size); } int qxl_ttm_init(struct qxl_device *qdev) @@ -267,8 +263,8 @@ int qxl_ttm_init(struct qxl_device *qdev) void qxl_ttm_fini(struct qxl_device *qdev) { - ttm_range_man_fini(&qdev->mman.bdev, ttm_manager_type(&qdev->mman.bdev, TTM_PL_VRAM)); - ttm_range_man_fini(&qdev->mman.bdev, ttm_manager_type(&qdev->mman.bdev, TTM_PL_PRIV)); + ttm_range_man_fini(&qdev->mman.bdev, TTM_PL_VRAM); + ttm_range_man_fini(&qdev->mman.bdev, TTM_PL_PRIV); ttm_bo_device_release(&qdev->mman.bdev); DRM_INFO("qxl: ttm finalized\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 671ca63d420c4..5f536de3986d1 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -68,35 +68,34 @@ struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) static int radeon_ttm_init_vram(struct radeon_device *rdev) { - struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM); - - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - - return ttm_range_man_init(&rdev->mman.bdev, man, + return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_VRAM, + TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, + TTM_PL_FLAG_WC, false, rdev->mc.real_vram_size >> PAGE_SHIFT); } static int radeon_ttm_init_gtt(struct radeon_device *rdev) { - struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_TT); + uint32_t available_caching, default_caching; + + available_caching = TTM_PL_MASK_CACHING; + default_caching = TTM_PL_FLAG_CACHED; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; - man->use_tt = true; #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { if (!rdev->ddev->agp) { DRM_ERROR("AGP is not enabled\n"); return -EINVAL; } - man->available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; + available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + default_caching = TTM_PL_FLAG_WC; } #endif - return ttm_range_man_init(&rdev->mman.bdev, man, + return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_TT, + available_caching, + default_caching, true, rdev->mc.gtt_size >> PAGE_SHIFT); } @@ -827,8 +826,8 @@ void radeon_ttm_fini(struct radeon_device *rdev) } radeon_bo_unref(&rdev->stolen_vga_memory); } - ttm_range_man_fini(&rdev->mman.bdev, ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM)); - ttm_range_man_fini(&rdev->mman.bdev, ttm_manager_type(&rdev->mman.bdev, TTM_PL_TT)); + ttm_range_man_fini(&rdev->mman.bdev, TTM_PL_VRAM); + ttm_range_man_fini(&rdev->mman.bdev, TTM_PL_TT); ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); rdev->mman.initialized = false; diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 86bf5e71e9598..d83cb967a1070 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -107,19 +107,27 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, static const struct ttm_mem_type_manager_func ttm_bo_manager_func; int ttm_range_man_init(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, + unsigned type, + uint32_t available_caching, + uint32_t default_caching, + bool use_tt, unsigned long p_size) { + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, type); struct ttm_range_manager *rman; - man->func = &ttm_bo_manager_func; - - ttm_mem_type_manager_init(bdev, man, p_size); + man->available_caching = available_caching; + man->default_caching = default_caching; + man->use_tt = use_tt; rman = kzalloc(sizeof(*rman), GFP_KERNEL); if (!rman) return -ENOMEM; + man->func = &ttm_bo_manager_func; + + ttm_mem_type_manager_init(bdev, man, p_size); + drm_mm_init(&rman->mm, 0, p_size); spin_lock_init(&rman->lock); man->priv = rman; @@ -130,8 +138,9 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, EXPORT_SYMBOL(ttm_range_man_init); int ttm_range_man_fini(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man) + unsigned type) { + struct ttm_mem_type_manager *man = ttm_manager_type(bdev, type); struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; struct drm_mm *mm = &rman->mm; int ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index c30021d0215ce..f4b8de57a7614 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -626,13 +626,9 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) #ifdef CONFIG_TRANSPARENT_HUGEPAGE ret = vmw_thp_init(dev_priv); #else - struct ttm_mem_type_manager *man = &dev_priv->bdev.man[TTM_PL_VRAM]; - - man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; - - ret = ttm_range_man_init(&dev_priv->bdev, man, - dev_priv->vram_size >> PAGE_SHIFT); + ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, + TTM_PL_FLAG_CACHED, TTM_PL_FLAG_CACHED, + false, dev_priv->vram_size >> PAGE_SHIFT); #endif ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM)->use_type = false; return ret; @@ -643,8 +639,7 @@ static void vmw_vram_manager_fini(struct vmw_private *dev_priv) #ifdef CONFIG_TRANSPARENT_HUGEPAGE vmw_thp_fini(dev_priv); #else - ttm_bo_man_fini(&dev_priv->bdev, - ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM)); + ttm_bo_man_fini(&dev_priv->bdev, TTM_PL_VRAM); #endif } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ce15eb075241d..7490de8f53afc 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -856,14 +856,20 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); * ttm_range_man_init * * @bdev: ttm device - * @man: the manager to initialise with the range manager. + * @type: memory manager type + * @available_caching: TTM_PL_FLAG_* for allowed caching modes + * @default_caching: default caching mode + * @use_tt: if the memory manager uses tt * @p_size: size of area to be managed in pages. * * Initialise a generic range manager for the selected memory type. * The range manager is installed for this device in the type slot. */ int ttm_range_man_init(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, + unsigned type, + uint32_t available_caching, + uint32_t default_caching, + bool use_tt, unsigned long p_size); /** @@ -875,7 +881,7 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, * Remove the generic range manager from a slot and tear it down. */ int ttm_range_man_fini(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man); + unsigned type); /** * ttm_mem_type_manager_debug -- GitLab From 3a1fc38edac75d19dffa5d5b0f1ffc872f8798d9 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:20 +1000 Subject: [PATCH 0293/1494] drm/ttm: move range manager to subclassed driver allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-48-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_manager.c | 31 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index d83cb967a1070..01d41c6f2f7ba 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -44,16 +44,22 @@ */ struct ttm_range_manager { + struct ttm_mem_type_manager manager; struct drm_mm mm; spinlock_t lock; }; +static inline struct ttm_range_manager *to_range_manager(struct ttm_mem_type_manager *man) +{ + return container_of(man, struct ttm_range_manager, manager); +} + static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; struct drm_mm_node *node; enum drm_mm_insert_mode mode; @@ -92,7 +98,7 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_range_manager *rman = to_range_manager(man); if (mem->mm_node) { spin_lock(&rman->lock); @@ -113,25 +119,26 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, bool use_tt, unsigned long p_size) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, type); + struct ttm_mem_type_manager *man; struct ttm_range_manager *rman; - man->available_caching = available_caching; - man->default_caching = default_caching; - man->use_tt = use_tt; - rman = kzalloc(sizeof(*rman), GFP_KERNEL); if (!rman) return -ENOMEM; + man = &rman->manager; + man->available_caching = available_caching; + man->default_caching = default_caching; + man->use_tt = use_tt; + man->func = &ttm_bo_manager_func; ttm_mem_type_manager_init(bdev, man, p_size); drm_mm_init(&rman->mm, 0, p_size); spin_lock_init(&rman->lock); - man->priv = rman; + ttm_set_driver_manager(bdev, type, &rman->manager); ttm_mem_type_manager_set_used(man, true); return 0; } @@ -141,7 +148,7 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, unsigned type) { struct ttm_mem_type_manager *man = ttm_manager_type(bdev, type); - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; int ret; @@ -155,10 +162,10 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, drm_mm_clean(mm); drm_mm_takedown(mm); spin_unlock(&rman->lock); - kfree(rman); - man->priv = NULL; ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(bdev, type, NULL); + kfree(rman); return 0; } EXPORT_SYMBOL(ttm_range_man_fini); @@ -166,7 +173,7 @@ EXPORT_SYMBOL(ttm_range_man_fini); static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, struct drm_printer *printer) { - struct ttm_range_manager *rman = (struct ttm_range_manager *) man->priv; + struct ttm_range_manager *rman = to_range_manager(man); spin_lock(&rman->lock); drm_mm_print(&rman->mm, printer); -- GitLab From d575a891e69e6f61d444f6f6e2749d9fa787c3ba Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:21 +1000 Subject: [PATCH 0294/1494] drm/vmwgfx/ttm: move thp to driver managed Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-49-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 720a24214c744..1cefd9c1e8ea6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -16,10 +16,16 @@ * @lock: Manager lock. */ struct vmw_thp_manager { + struct ttm_mem_type_manager manager; struct drm_mm mm; spinlock_t lock; }; +static struct vmw_thp_manager *to_thp_manager(struct ttm_mem_type_manager *man) +{ + return container_of(man, struct vmw_thp_manager, manager); +} + static int vmw_thp_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node, unsigned long align_pages, const struct ttm_place *place, @@ -43,7 +49,7 @@ static int vmw_thp_get_node(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; + struct vmw_thp_manager *rman = to_thp_manager(man); struct drm_mm *mm = &rman->mm; struct drm_mm_node *node; unsigned long align_pages; @@ -103,7 +109,7 @@ static int vmw_thp_get_node(struct ttm_mem_type_manager *man, static void vmw_thp_put_node(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; + struct vmw_thp_manager *rman = to_thp_manager(man); if (mem->mm_node) { spin_lock(&rman->lock); @@ -117,20 +123,24 @@ static void vmw_thp_put_node(struct ttm_mem_type_manager *man, int vmw_thp_init(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + struct ttm_mem_type_manager *man; struct vmw_thp_manager *rman; + + rman = kzalloc(sizeof(*rman), GFP_KERNEL); + if (!rman) + return -ENOMEM; + + man = &rman->manager; man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; ttm_mem_type_manager_init(&dev_priv->bdev, man, dev_priv->vram_size >> PAGE_SHIFT); - rman = kzalloc(sizeof(*rman), GFP_KERNEL); - if (!rman) - return -ENOMEM; drm_mm_init(&rman->mm, 0, man->size); spin_lock_init(&rman->lock); - man->priv = rman; + + ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, &rman->manager); ttm_mem_type_manager_set_used(man, true); return 0; } @@ -138,7 +148,7 @@ int vmw_thp_init(struct vmw_private *dev_priv) void vmw_thp_fini(struct vmw_private *dev_priv) { struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); - struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; + struct vmw_thp_manager *rman = to_thp_manager(man); struct drm_mm *mm = &rman->mm; int ret; @@ -151,15 +161,15 @@ void vmw_thp_fini(struct vmw_private *dev_priv) drm_mm_clean(mm); drm_mm_takedown(mm); spin_unlock(&rman->lock); - kfree(rman); - man->priv = NULL; ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, NULL); + kfree(rman); } static void vmw_thp_debug(struct ttm_mem_type_manager *man, struct drm_printer *printer) { - struct vmw_thp_manager *rman = (struct vmw_thp_manager *) man->priv; + struct vmw_thp_manager *rman = to_thp_manager(man); spin_lock(&rman->lock); drm_mm_print(&rman->mm, printer); -- GitLab From 9488e46a4f89e45244bfa2c8ea70869adcb501dc Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:22 +1000 Subject: [PATCH 0295/1494] drm/vmwgfx/gmrid: convert to driver controlled allocation. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-50-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index 54c85a59dd8b1..bc51b77730845 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -37,6 +37,7 @@ #include <linux/kernel.h> struct vmwgfx_gmrid_man { + struct ttm_mem_type_manager manager; spinlock_t lock; struct ida gmr_ida; uint32_t max_gmr_ids; @@ -44,13 +45,17 @@ struct vmwgfx_gmrid_man { uint32_t used_gmr_pages; }; +static struct vmwgfx_gmrid_man *to_gmrid_manager(struct ttm_mem_type_manager *man) +{ + return container_of(man, struct vmwgfx_gmrid_man, manager); +} + static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct vmwgfx_gmrid_man *gman = - (struct vmwgfx_gmrid_man *)man->priv; + struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); int id; id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL); @@ -82,8 +87,7 @@ static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man, static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct vmwgfx_gmrid_man *gman = - (struct vmwgfx_gmrid_man *)man->priv; + struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); if (mem->mm_node) { ida_free(&gman->gmr_ida, mem->start); @@ -98,13 +102,15 @@ static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func; int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); + struct ttm_mem_type_manager *man; struct vmwgfx_gmrid_man *gman = kzalloc(sizeof(*gman), GFP_KERNEL); if (unlikely(!gman)) return -ENOMEM; + man = &gman->manager; + man->func = &vmw_gmrid_manager_func; man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; @@ -127,8 +133,7 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) default: BUG(); } - man->priv = (void *) gman; - + ttm_set_driver_manager(&dev_priv->bdev, type, &gman->manager); ttm_mem_type_manager_set_used(man, true); return 0; } @@ -136,19 +141,18 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) { struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); - struct vmwgfx_gmrid_man *gman = - (struct vmwgfx_gmrid_man *)man->priv; + struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); ttm_mem_type_manager_disable(man); ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); - if (gman) { - ida_destroy(&gman->gmr_ida); - kfree(gman); - } - ttm_mem_type_manager_cleanup(man); + + ttm_set_driver_manager(&dev_priv->bdev, type, NULL); + ida_destroy(&gman->gmr_ida); + kfree(gman); + } static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { -- GitLab From b6fad57e5903c0cc37a504300fff64b1d5d4dd8a Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:23 +1000 Subject: [PATCH 0296/1494] drm/nouveau/ttm: move to driver allocated manager Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-51-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 45 +++++++++++++++++++-------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 1c636723823c4..2680bdc97c1c5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -157,12 +157,12 @@ static int nouveau_ttm_init_vram(struct nouveau_drm *drm) { struct nvif_mmu *mmu = &drm->client.mmu; - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); - /* Some BARs do not support being ioremapped WC */ const u8 type = mmu->type[drm->ttm.type_vram].type; + struct ttm_mem_type_manager *man = kzalloc(sizeof(*man), GFP_KERNEL); + if (!man) + return -ENOMEM; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -174,8 +174,10 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) man->func = &nouveau_vram_manager; man->use_io_reserve_lru = true; + ttm_mem_type_manager_init(&drm->ttm.bdev, man, drm->gem.vram_available >> PAGE_SHIFT); + ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, man); ttm_mem_type_manager_set_used(man, true); return 0; } else { @@ -195,6 +197,8 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) ttm_mem_type_manager_disable(man); ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, NULL); + kfree(man); } else ttm_range_man_fini(&drm->ttm.bdev, TTM_PL_VRAM); } @@ -202,30 +206,43 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) static int nouveau_ttm_init_gtt(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_TT); + struct ttm_mem_type_manager *man; unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; - man->use_tt = true; + unsigned available_caching, default_caching; + const struct ttm_mem_type_manager_func *func = NULL; if (drm->agp.bridge) { - man->available_caching = TTM_PL_FLAG_UNCACHED | + available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; + default_caching = TTM_PL_FLAG_WC; } else { - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; + available_caching = TTM_PL_MASK_CACHING; + default_caching = TTM_PL_FLAG_CACHED; } if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) - man->func = &nouveau_gart_manager; + func = &nouveau_gart_manager; else if (!drm->agp.bridge) - man->func = &nv04_gart_manager; + func = &nv04_gart_manager; else return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, - TTM_PL_FLAG_WC, true, + available_caching, default_caching, + true, size_pages); + + man = kzalloc(sizeof(*man), GFP_KERNEL); + if (!man) + return -ENOMEM; + + man->func = func; + man->available_caching = available_caching; + man->default_caching = default_caching; + man->use_tt = true; ttm_mem_type_manager_init(&drm->ttm.bdev, man, size_pages); + + ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); ttm_mem_type_manager_set_used(man, true); + return 0; } @@ -241,6 +258,8 @@ nouveau_ttm_fini_gtt(struct nouveau_drm *drm) ttm_mem_type_manager_disable(man); ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); ttm_mem_type_manager_cleanup(man); + ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, NULL); + kfree(man); } } -- GitLab From 7ee6c95e05e9b06741d347107cff13559e9f81d9 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:24 +1000 Subject: [PATCH 0297/1494] drm/ttm: drop priv pointer in memory manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This isn't needed anymore by any drivers. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-52-airlied@gmail.com --- include/drm/ttm/ttm_bo_driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 7490de8f53afc..8c39901d8717c 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -123,7 +123,6 @@ struct ttm_mem_type_manager_func { * @default_caching: The default caching policy used for a buffer object * placed in this memory type if the user doesn't provide one. * @func: structure pointer implementing the range manager. See above - * @priv: Driver private closure for @func. * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions * reserved by the TTM vm system. @@ -152,7 +151,6 @@ struct ttm_mem_type_manager { uint32_t available_caching; uint32_t default_caching; const struct ttm_mem_type_manager_func *func; - void *priv; struct mutex io_reserve_mutex; bool use_io_reserve_lru; spinlock_t move_lock; -- GitLab From a29050c4cd7f411e6bc0b9eb4232c4ef5a76aa32 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:25 +1000 Subject: [PATCH 0298/1494] drm/amdgpu/ttm: remove man->bdev references. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just store the device in the private so the link can be removed from the manager Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-53-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 04436ce6c7454..87c6a1e1aa82c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -34,6 +34,7 @@ struct amdgpu_vram_mgr { spinlock_t lock; atomic64_t usage; atomic64_t vis_usage; + struct amdgpu_device *adev; }; static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_mem_type_manager *man) @@ -196,6 +197,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) drm_mm_init(&mgr->mm, 0, man->size); spin_lock_init(&mgr->lock); + mgr->adev = adev; + /* Add the two VRAM-related sysfs files */ ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); if (ret) @@ -323,8 +326,8 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); + struct amdgpu_device *adev = mgr->adev; struct drm_mm *mm = &mgr->mm; struct drm_mm_node *nodes; enum drm_mm_insert_mode mode; @@ -441,8 +444,8 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *mem) { - struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); + struct amdgpu_device *adev = mgr->adev; struct drm_mm_node *nodes = mem->mm_node; uint64_t usage = 0, vis_usage = 0; unsigned pages = mem->num_pages; -- GitLab From 7541ce1a6f2be9ab056a5b5105e08aef8d3287b1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:26 +1000 Subject: [PATCH 0299/1494] drm/ttm: drop man->bdev link. This link isn't needed anymore, drop it from the init interface. Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-54-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 6 ++---- drivers/gpu/drm/ttm/ttm_bo.c | 6 ++---- drivers/gpu/drm/ttm/ttm_bo_manager.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 2 +- include/drm/ttm/ttm_bo_api.h | 6 ++---- include/drm/ttm/ttm_bo_driver.h | 2 -- 9 files changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index a74c6987ac140..a6a99e66b871a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -108,7 +108,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(&adev->mman.bdev, man, gtt_size >> PAGE_SHIFT); + ttm_mem_type_manager_init(man, gtt_size >> PAGE_SHIFT); start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 87c6a1e1aa82c..785c073d71eba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -190,7 +190,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - ttm_mem_type_manager_init(&adev->mman.bdev, man, adev->gmc.real_vram_size >> PAGE_SHIFT); + ttm_mem_type_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT); man->func = &amdgpu_vram_mgr_func; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 2680bdc97c1c5..a79691374f60c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -175,7 +175,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) man->func = &nouveau_vram_manager; man->use_io_reserve_lru = true; - ttm_mem_type_manager_init(&drm->ttm.bdev, man, + ttm_mem_type_manager_init(man, drm->gem.vram_available >> PAGE_SHIFT); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, man); ttm_mem_type_manager_set_used(man, true); @@ -237,9 +237,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) man->available_caching = available_caching; man->default_caching = default_caching; man->use_tt = true; - ttm_mem_type_manager_init(&drm->ttm.bdev, man, - size_pages); - + ttm_mem_type_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); ttm_mem_type_manager_set_used(man, true); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4d87ee98467fe..aec7e40f9f546 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1469,8 +1469,7 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) } EXPORT_SYMBOL(ttm_bo_evict_mm); -void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, +void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) { unsigned i; @@ -1480,7 +1479,6 @@ void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, mutex_init(&man->io_reserve_mutex); spin_lock_init(&man->move_lock); INIT_LIST_HEAD(&man->io_reserve_lru); - man->bdev = bdev; man->size = p_size; for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) @@ -1593,7 +1591,7 @@ static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(bdev, man, 0); + ttm_mem_type_manager_init(man, 0); ttm_mem_type_manager_set_used(man, true); } diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 01d41c6f2f7ba..1b7245ce3356b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -133,7 +133,7 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, man->func = &ttm_bo_manager_func; - ttm_mem_type_manager_init(bdev, man, p_size); + ttm_mem_type_manager_init(man, p_size); drm_mm_init(&rman->mm, 0, p_size); spin_lock_init(&rman->lock); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index bc51b77730845..c3fa25161fd0a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -116,7 +116,7 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) man->default_caching = TTM_PL_FLAG_CACHED; /* TODO: This is most likely not correct */ man->use_tt = true; - ttm_mem_type_manager_init(&dev_priv->bdev, man, 0); + ttm_mem_type_manager_init(man, 0); spin_lock_init(&gman->lock); gman->used_gmr_pages = 0; ida_init(&gman->gmr_ida); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 1cefd9c1e8ea6..0b9c29249393a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -134,7 +134,7 @@ int vmw_thp_init(struct vmw_private *dev_priv) man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(&dev_priv->bdev, man, + ttm_mem_type_manager_init(man, dev_priv->vram_size >> PAGE_SHIFT); drm_mm_init(&rman->mm, 0, man->size); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 045f283d79e8f..95d6c648d5c67 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -536,14 +536,12 @@ int ttm_bo_create(struct ttm_bo_device *bdev, unsigned long size, /** * ttm_mem_type_manager_init * - * @bdev: Pointer to a ttm_bo_device struct. * @man: memory manager object to init * @p_size: size managed area in pages. * - * Initialise core parts of a a manager object. + * Initialise core parts of a manager object. */ -void ttm_mem_type_manager_init(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, +void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size); /** diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 8c39901d8717c..e17975466b7f7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -138,8 +138,6 @@ struct ttm_mem_type_manager_func { struct ttm_mem_type_manager { - struct ttm_bo_device *bdev; - /* * No protection. Constant from start. */ -- GitLab From a751612d4cb77779669da0a6d19fbc4f7e72ba6f Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:27 +1000 Subject: [PATCH 0300/1494] drm/ttm: drop list of memory managers from device. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver now controls these, the core just controls the system memory one. v2: init sysman explicitly and assign it as a driver manager to simplify the lookup sequence. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-55-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 6 +++--- include/drm/ttm/ttm_bo_driver.h | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index aec7e40f9f546..6f02c7fa180a3 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1556,6 +1556,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) man = ttm_manager_type(bdev, TTM_PL_SYSTEM); ttm_mem_type_manager_disable(man); + ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, NULL); mutex_lock(&ttm_global_mutex); list_del(&bdev->device_list); @@ -1581,7 +1582,7 @@ EXPORT_SYMBOL(ttm_bo_device_release); static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, TTM_PL_SYSTEM); + struct ttm_mem_type_manager *man = &bdev->sysman; /* * Initialize the system memory buffer type. @@ -1592,6 +1593,7 @@ static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) man->default_caching = TTM_PL_FLAG_CACHED; ttm_mem_type_manager_init(man, 0); + ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man); ttm_mem_type_manager_set_used(man, true); } @@ -1613,8 +1615,6 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, bdev->driver = driver; - memset(bdev->man_priv, 0, sizeof(bdev->man_priv)); - ttm_bo_init_sysman(bdev); bdev->vma_manager = vma_manager; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index e17975466b7f7..2cb8721398eed 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -414,7 +414,7 @@ struct ttm_bo_device { /* * access via ttm_manager_type. */ - struct ttm_mem_type_manager man_priv[TTM_NUM_MEM_TYPES]; + struct ttm_mem_type_manager sysman; struct ttm_mem_type_manager *man_drv[TTM_NUM_MEM_TYPES]; /* * Protected by internal locks. @@ -446,9 +446,7 @@ struct ttm_bo_device { static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device *bdev, int mem_type) { - if (bdev->man_drv[mem_type]) - return bdev->man_drv[mem_type]; - return &bdev->man_priv[mem_type]; + return bdev->man_drv[mem_type]; } static inline void ttm_set_driver_manager(struct ttm_bo_device *bdev, -- GitLab From 90a0489a718b87bc0674792f9eafac007e0ea3d6 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:28 +1000 Subject: [PATCH 0301/1494] drm/ttm: drop type manager has_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit under driver control, this flag isn't needed anymore, remove the API that used to access it, and consoldiate with the used api. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-56-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 4 ++-- drivers/gpu/drm/ttm/ttm_bo.c | 8 +++----- drivers/gpu/drm/ttm/ttm_bo_manager.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 2 +- include/drm/ttm/ttm_bo_driver.h | 17 ----------------- 8 files changed, 10 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index a6a99e66b871a..e9de6f9538c02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -146,7 +146,7 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); int ret; - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 785c073d71eba..03a6248f0c4e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -223,7 +223,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); int ret; - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index a79691374f60c..38d9ea73ac8b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -194,7 +194,7 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); ttm_mem_type_manager_cleanup(man); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, NULL); @@ -253,7 +253,7 @@ nouveau_ttm_fini_gtt(struct nouveau_drm *drm) drm->agp.bridge) ttm_range_man_fini(&drm->ttm.bdev, TTM_PL_TT); else { - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); ttm_mem_type_manager_cleanup(man); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, NULL); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 6f02c7fa180a3..c1644a0e05862 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -80,7 +80,6 @@ static inline int ttm_mem_type_from_place(const struct ttm_place *place, void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, struct drm_printer *p) { - drm_printf(p, " has_type: %d\n", man->has_type); drm_printf(p, " use_type: %d\n", man->use_type); drm_printf(p, " use_tt: %d\n", man->use_tt); drm_printf(p, " size: %llu\n", man->size); @@ -1001,7 +1000,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, return ret; man = ttm_manager_type(bdev, mem_type); - if (!man->has_type || !man->use_type) + if (!man || !man->use_type) return -EBUSY; if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags)) @@ -1460,7 +1459,7 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) return -EINVAL; } - if (!man->has_type) { + if (!man) { pr_err("Memory type %u has not been initialized\n", mem_type); return 0; } @@ -1474,7 +1473,6 @@ void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, { unsigned i; - BUG_ON(man->has_type); man->use_io_reserve_lru = false; mutex_init(&man->io_reserve_mutex); spin_lock_init(&man->move_lock); @@ -1555,7 +1553,7 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) struct ttm_mem_type_manager *man; man = ttm_manager_type(bdev, TTM_PL_SYSTEM); - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, NULL); mutex_lock(&ttm_global_mutex); diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_bo_manager.c index 1b7245ce3356b..6679dc11934fd 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_bo_manager.c @@ -152,7 +152,7 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, struct drm_mm *mm = &rman->mm; int ret; - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ret = ttm_mem_type_manager_force_list_clean(bdev, man); if (ret) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index c3fa25161fd0a..ca5037184814c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -143,7 +143,7 @@ void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 0b9c29249393a..4110e83091880 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -152,7 +152,7 @@ void vmw_thp_fini(struct vmw_private *dev_priv) struct drm_mm *mm = &rman->mm; int ret; - ttm_mem_type_manager_disable(man); + ttm_mem_type_manager_set_used(man, false); ret = ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); if (ret) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 2cb8721398eed..a6076ab89a519 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -111,7 +111,6 @@ struct ttm_mem_type_manager_func { /** * struct ttm_mem_type_manager * - * @has_type: The memory type has been initialized. * @use_type: The memory type is enabled. * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory * managed by this memory type. @@ -141,8 +140,6 @@ struct ttm_mem_type_manager { /* * No protection. Constant from start. */ - - bool has_type; bool use_type; bool use_tt; uint64_t size; @@ -689,23 +686,9 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) */ static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *man, bool used) { - man->has_type = true; man->use_type = used; } -/** - * ttm_mem_type_manager_disable. - * - * @man: A memory manager object. - * - * Indicate the manager is not to be used and deregistered. (temporary during rework). - */ -static inline void ttm_mem_type_manager_disable(struct ttm_mem_type_manager *man) -{ - man->has_type = false; - man->use_type = false; -} - /** * ttm_mem_type_manager_cleanup * -- GitLab From 3f48f938ad21a1ab1cec5631af3e468baabe41c8 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:29 +1000 Subject: [PATCH 0302/1494] drm/ttm: add a wrapper for checking if manager is in use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This converts vmwgfx over to using an interface to set the in use and check the in use flag. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-57-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 1 - drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 14 +++++++------- include/drm/ttm/ttm_bo_driver.h | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 38d9ea73ac8b8..84387c810540e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -240,7 +240,6 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) ttm_mem_type_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); ttm_mem_type_manager_set_used(man, true); - return 0; } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c1644a0e05862..e0188250b6ec2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1000,7 +1000,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, return ret; man = ttm_manager_type(bdev, mem_type); - if (!man || !man->use_type) + if (!man || !ttm_mem_type_manager_used(man)) return -EBUSY; if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags)) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f4b8de57a7614..a7b3c8ee7f211 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -630,7 +630,7 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) TTM_PL_FLAG_CACHED, TTM_PL_FLAG_CACHED, false, dev_priv->vram_size >> PAGE_SHIFT); #endif - ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM)->use_type = false; + ttm_mem_type_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); return ret; } @@ -1192,9 +1192,9 @@ static void __vmw_svga_enable(struct vmw_private *dev_priv) struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); spin_lock(&dev_priv->svga_lock); - if (!man->use_type) { + if (!ttm_mem_type_manager_used(man)) { vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE); - man->use_type = true; + ttm_mem_type_manager_set_used(man, true); } spin_unlock(&dev_priv->svga_lock); } @@ -1223,8 +1223,8 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); spin_lock(&dev_priv->svga_lock); - if (man->use_type) { - man->use_type = false; + if (ttm_mem_type_manager_used(man)) { + ttm_mem_type_manager_set_used(man, false); vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_HIDE | SVGA_REG_ENABLE_ENABLE); @@ -1257,8 +1257,8 @@ void vmw_svga_disable(struct vmw_private *dev_priv) vmw_kms_lost_device(dev_priv->dev); ttm_write_lock(&dev_priv->reservation_sem, false); spin_lock(&dev_priv->svga_lock); - if (man->use_type) { - man->use_type = false; + if (ttm_mem_type_manager_used(man)) { + ttm_mem_type_manager_set_used(man, false); spin_unlock(&dev_priv->svga_lock); if (ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM)) DRM_ERROR("Failed evicting VRAM buffers.\n"); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index a6076ab89a519..31264a09ec63d 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -689,6 +689,20 @@ static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *ma man->use_type = used; } +/** + * ttm_mem_type_manager_used + * + * @man: Manager to get used state for + * + * Get the in use flag for a manager. + * Returns: + * true is used, false if not. + */ +static inline bool ttm_mem_type_manager_used(struct ttm_mem_type_manager *man) +{ + return man->use_type; +} + /** * ttm_mem_type_manager_cleanup * -- GitLab From 80938c28ee67bad05b2982410440b5a2d200a2f5 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:30 +1000 Subject: [PATCH 0303/1494] drm/ttm: rename bo manager to range manager. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generic manager is called the range manager now, rename the file and some internals. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-58-airlied@gmail.com --- drivers/gpu/drm/ttm/Makefile | 2 +- .../{ttm_bo_manager.c => ttm_range_manager.c} | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) rename drivers/gpu/drm/ttm/{ttm_bo_manager.c => ttm_range_manager.c} (87%) diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index caea2a0994966..e54326e6cea4a 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile @@ -4,7 +4,7 @@ ttm-y := ttm_memory.o ttm_tt.o ttm_bo.o \ ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ - ttm_execbuf_util.o ttm_page_alloc.o ttm_bo_manager.o + ttm_execbuf_util.o ttm_page_alloc.o ttm_range_manager.o ttm-$(CONFIG_AGP) += ttm_agp_backend.o ttm-$(CONFIG_DRM_TTM_DMA_PAGE_POOL) += ttm_page_alloc_dma.o diff --git a/drivers/gpu/drm/ttm/ttm_bo_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c similarity index 87% rename from drivers/gpu/drm/ttm/ttm_bo_manager.c rename to drivers/gpu/drm/ttm/ttm_range_manager.c index 6679dc11934fd..7fddc74b3827a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -54,10 +54,10 @@ static inline struct ttm_range_manager *to_range_manager(struct ttm_mem_type_man return container_of(man, struct ttm_range_manager, manager); } -static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, - struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_mem_reg *mem) +static int ttm_range_man_get_node(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_mem_reg *mem) { struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; @@ -95,8 +95,8 @@ static int ttm_bo_man_get_node(struct ttm_mem_type_manager *man, return ret; } -static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *mem) +static void ttm_range_man_put_node(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) { struct ttm_range_manager *rman = to_range_manager(man); @@ -110,7 +110,7 @@ static void ttm_bo_man_put_node(struct ttm_mem_type_manager *man, } } -static const struct ttm_mem_type_manager_func ttm_bo_manager_func; +static const struct ttm_mem_type_manager_func ttm_range_manager_func; int ttm_range_man_init(struct ttm_bo_device *bdev, unsigned type, @@ -131,7 +131,7 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, man->default_caching = default_caching; man->use_tt = use_tt; - man->func = &ttm_bo_manager_func; + man->func = &ttm_range_manager_func; ttm_mem_type_manager_init(man, p_size); @@ -170,8 +170,8 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_range_man_fini); -static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, - struct drm_printer *printer) +static void ttm_range_man_debug(struct ttm_mem_type_manager *man, + struct drm_printer *printer) { struct ttm_range_manager *rman = to_range_manager(man); @@ -180,8 +180,8 @@ static void ttm_bo_man_debug(struct ttm_mem_type_manager *man, spin_unlock(&rman->lock); } -static const struct ttm_mem_type_manager_func ttm_bo_manager_func = { - .get_node = ttm_bo_man_get_node, - .put_node = ttm_bo_man_put_node, - .debug = ttm_bo_man_debug +static const struct ttm_mem_type_manager_func ttm_range_manager_func = { + .get_node = ttm_range_man_get_node, + .put_node = ttm_range_man_put_node, + .debug = ttm_range_man_debug }; -- GitLab From 9de59bc201496f28bb8835c2bcbae3ddb186b548 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:31 +1000 Subject: [PATCH 0304/1494] drm/ttm: rename ttm_mem_type_manager -> ttm_resource_manager. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This name makes a lot more sense, since these are about managing driver resources rather than just memory ranges. Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-59-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 36 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 8 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 36 +++++----- drivers/gpu/drm/drm_gem_vram_helper.c | 4 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 44 ++++++------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 6 +- drivers/gpu/drm/qxl/qxl_ttm.c | 4 +- drivers/gpu/drm/radeon/radeon_gem.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 4 +- drivers/gpu/drm/ttm/ttm_bo.c | 66 +++++++++---------- drivers/gpu/drm/ttm/ttm_bo_util.c | 26 ++++---- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +- drivers/gpu/drm/ttm/ttm_range_manager.c | 28 ++++---- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 20 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 26 ++++---- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 26 ++++---- include/drm/ttm/ttm_bo_api.h | 6 +- include/drm/ttm/ttm_bo_driver.h | 60 ++++++++--------- 23 files changed, 209 insertions(+), 209 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index ba4d11e8a960e..e2b4d3fc601df 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -517,7 +517,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; - struct ttm_mem_type_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); return amdgpu_vram_mgr_usage(vram_man); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 5ef7b3b7c9af8..65b67c82a4b9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -299,7 +299,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev, { s64 time_us, increment_us; u64 free_vram, total_vram, used_vram; - struct ttm_mem_type_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); /* Allow a maximum of 200 accumulated ms. This is basically per-IB * throttling. * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index e9de6f9538c02..b9050b7221d5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -25,13 +25,13 @@ #include "amdgpu.h" struct amdgpu_gtt_mgr { - struct ttm_mem_type_manager manager; + struct ttm_resource_manager manager; struct drm_mm mm; spinlock_t lock; atomic64_t available; }; -static inline struct amdgpu_gtt_mgr *to_gtt_mgr(struct ttm_mem_type_manager *man) +static inline struct amdgpu_gtt_mgr *to_gtt_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_gtt_mgr, manager); } @@ -54,7 +54,7 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); return snprintf(buf, PAGE_SIZE, "%llu\n", man->size * PAGE_SIZE); } @@ -72,7 +72,7 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_gtt_mgr_usage(man)); } @@ -82,7 +82,7 @@ static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO, static DEVICE_ATTR(mem_info_gtt_used, S_IRUGO, amdgpu_mem_info_gtt_used_show, NULL); -static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; +static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func; /** * amdgpu_gtt_mgr_init - init GTT manager and DRM MM * @@ -93,7 +93,7 @@ static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; */ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; struct amdgpu_gtt_mgr *mgr; uint64_t start, size; int ret; @@ -108,7 +108,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(man, gtt_size >> PAGE_SHIFT); + ttm_resource_manager_init(man, gtt_size >> PAGE_SHIFT); start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS; size = (adev->gmc.gart_size >> PAGE_SHIFT) - start; @@ -128,7 +128,7 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) } ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, &mgr->manager); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } @@ -142,13 +142,13 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) */ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); int ret; - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); - ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); + ret = ttm_resource_manager_force_list_clean(&adev->mman.bdev, man); if (ret) return; @@ -159,7 +159,7 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) device_remove_file(adev->dev, &dev_attr_mem_info_gtt_total); device_remove_file(adev->dev, &dev_attr_mem_info_gtt_used); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, NULL); kfree(mgr); } @@ -186,7 +186,7 @@ bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem) * * Dummy, allocate the node but no space for it yet. */ -static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, +static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, struct ttm_mem_reg *mem) @@ -251,7 +251,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, * * Free the allocated GTT again. */ -static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man, +static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, struct ttm_mem_reg *mem) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); @@ -274,7 +274,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man, * * Return how many bytes are used in the GTT domain */ -uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man) +uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); s64 result = man->size - atomic64_read(&mgr->available); @@ -282,7 +282,7 @@ uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man) return (result > 0 ? result : 0) * PAGE_SIZE; } -int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man) +int amdgpu_gtt_mgr_recover(struct ttm_resource_manager *man) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node; @@ -309,7 +309,7 @@ int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man) * * Dump the table content using printk. */ -static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, +static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); @@ -323,7 +323,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, amdgpu_gtt_mgr_usage(man) >> 20); } -static const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = { +static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { .get_node = amdgpu_gtt_mgr_new, .put_node = amdgpu_gtt_mgr_del, .debug = amdgpu_gtt_mgr_debug diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 134cca1af7446..fff9c013f3378 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -616,9 +616,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file } case AMDGPU_INFO_MEMORY: { struct drm_amdgpu_memory_info mem; - struct ttm_mem_type_manager *vram_man = + struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - struct ttm_mem_type_manager *gtt_man = + struct ttm_resource_manager *gtt_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); memset(&mem, 0, sizeof(mem)); mem.vram.total_heap_size = adev->gmc.real_vram_size; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index ced418cba2f73..ce98df5b0c219 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -442,7 +442,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, unsigned long size, u32 domain) { - struct ttm_mem_type_manager *man = NULL; + struct ttm_resource_manager *man = NULL; /* * If GTT is part of requested domains the check must succeed to diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5556958540760..2fc0214d9a95c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2012,7 +2012,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) */ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); uint64_t size; int r; @@ -2234,7 +2234,7 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data) unsigned ttm_pl = (uintptr_t)node->info_ent->data; struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = dev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, ttm_pl); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, ttm_pl); struct drm_printer p = drm_seq_file_printer(m); man->func->debug(man, &p); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index c01fdb3f0458a..3db29ae1f8028 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -73,8 +73,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev); void amdgpu_vram_mgr_fini(struct amdgpu_device *adev); bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem); -uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man); -int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man); +uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man); +int amdgpu_gtt_mgr_recover(struct ttm_resource_manager *man); u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo); int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, @@ -86,8 +86,8 @@ void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, struct device *dev, enum dma_data_direction dir, struct sg_table *sgt); -uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man); -uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man); +uint64_t amdgpu_vram_mgr_usage(struct ttm_resource_manager *man); +uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_resource_manager *man); int amdgpu_ttm_init(struct amdgpu_device *adev); void amdgpu_ttm_late_init(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 03a6248f0c4e1..6f888a63f22d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -29,7 +29,7 @@ #include "atom.h" struct amdgpu_vram_mgr { - struct ttm_mem_type_manager manager; + struct ttm_resource_manager manager; struct drm_mm mm; spinlock_t lock; atomic64_t usage; @@ -37,7 +37,7 @@ struct amdgpu_vram_mgr { struct amdgpu_device *adev; }; -static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_mem_type_manager *man) +static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_vram_mgr, manager); } @@ -89,7 +89,7 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_usage(man)); } @@ -107,7 +107,7 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_vis_usage(man)); } @@ -165,7 +165,7 @@ static const struct attribute *amdgpu_vram_mgr_attributes[] = { NULL }; -static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; +static const struct ttm_resource_manager_func amdgpu_vram_mgr_func; /** * amdgpu_vram_mgr_init - init VRAM manager and DRM MM @@ -177,7 +177,7 @@ static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; */ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; struct amdgpu_vram_mgr *mgr; int ret; @@ -190,7 +190,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - ttm_mem_type_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT); + ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT); man->func = &amdgpu_vram_mgr_func; @@ -205,7 +205,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) DRM_ERROR("Failed to register sysfs\n"); ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, &mgr->manager); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } @@ -219,13 +219,13 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) */ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { - struct ttm_mem_type_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); int ret; - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); - ret = ttm_mem_type_manager_force_list_clean(&adev->mman.bdev, man); + ret = ttm_resource_manager_force_list_clean(&adev->mman.bdev, man); if (ret) return; @@ -235,7 +235,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) sysfs_remove_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, NULL); kfree(mgr); } @@ -321,7 +321,7 @@ static void amdgpu_vram_mgr_virt_start(struct ttm_mem_reg *mem, * * Allocate VRAM for the given BO. */ -static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, +static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, struct ttm_mem_reg *mem) @@ -441,7 +441,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, * * Free the allocated VRAM again. */ -static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man, +static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, struct ttm_mem_reg *mem) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); @@ -575,7 +575,7 @@ void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, * * Returns how many bytes are used in this domain. */ -uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man) +uint64_t amdgpu_vram_mgr_usage(struct ttm_resource_manager *man) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); @@ -589,7 +589,7 @@ uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man) * * Returns how many bytes are used in the visible part of VRAM */ -uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man) +uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_resource_manager *man) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); @@ -604,7 +604,7 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man) * * Dump the table content using printk. */ -static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, +static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); @@ -618,7 +618,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, amdgpu_vram_mgr_vis_usage(man) >> 20); } -static const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { +static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = { .get_node = amdgpu_vram_mgr_new, .put_node = amdgpu_vram_mgr_del, .debug = amdgpu_vram_mgr_debug diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 2187787f397e6..e3660d00987d9 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1075,10 +1075,10 @@ static int drm_vram_mm_debugfs(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_vram_mm *vmm = node->minor->dev->vram_mm; - struct ttm_mem_type_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM); struct drm_printer p = drm_seq_file_printer(m); - ttm_mem_type_manager_debug(man, &p); + ttm_resource_manager_debug(man, &p); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 84387c810540e..78b5a87b98553 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -32,13 +32,13 @@ #include <core/tegra.h> static void -nouveau_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg) +nouveau_manager_del(struct ttm_resource_manager *man, struct ttm_mem_reg *reg) { nouveau_mem_del(reg); } static int -nouveau_vram_manager_new(struct ttm_mem_type_manager *man, +nouveau_vram_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *reg) @@ -63,13 +63,13 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, return 0; } -const struct ttm_mem_type_manager_func nouveau_vram_manager = { +const struct ttm_resource_manager_func nouveau_vram_manager = { .get_node = nouveau_vram_manager_new, .put_node = nouveau_manager_del, }; static int -nouveau_gart_manager_new(struct ttm_mem_type_manager *man, +nouveau_gart_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *reg) @@ -86,13 +86,13 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man, return 0; } -const struct ttm_mem_type_manager_func nouveau_gart_manager = { +const struct ttm_resource_manager_func nouveau_gart_manager = { .get_node = nouveau_gart_manager_new, .put_node = nouveau_manager_del, }; static int -nv04_gart_manager_new(struct ttm_mem_type_manager *man, +nv04_gart_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *reg) @@ -118,7 +118,7 @@ nv04_gart_manager_new(struct ttm_mem_type_manager *man, return 0; } -const struct ttm_mem_type_manager_func nv04_gart_manager = { +const struct ttm_resource_manager_func nv04_gart_manager = { .get_node = nv04_gart_manager_new, .put_node = nouveau_manager_del, }; @@ -160,7 +160,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { /* Some BARs do not support being ioremapped WC */ const u8 type = mmu->type[drm->ttm.type_vram].type; - struct ttm_mem_type_manager *man = kzalloc(sizeof(*man), GFP_KERNEL); + struct ttm_resource_manager *man = kzalloc(sizeof(*man), GFP_KERNEL); if (!man) return -ENOMEM; @@ -175,10 +175,10 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) man->func = &nouveau_vram_manager; man->use_io_reserve_lru = true; - ttm_mem_type_manager_init(man, + ttm_resource_manager_init(man, drm->gem.vram_available >> PAGE_SHIFT); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, man); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } else { return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_VRAM, @@ -191,12 +191,12 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) static void nouveau_ttm_fini_vram(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_VRAM); if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - ttm_mem_type_manager_set_used(man, false); - ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_set_used(man, false); + ttm_resource_manager_force_list_clean(&drm->ttm.bdev, man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_VRAM, NULL); kfree(man); } else @@ -206,10 +206,10 @@ nouveau_ttm_fini_vram(struct nouveau_drm *drm) static int nouveau_ttm_init_gtt(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; unsigned available_caching, default_caching; - const struct ttm_mem_type_manager_func *func = NULL; + const struct ttm_resource_manager_func *func = NULL; if (drm->agp.bridge) { available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; @@ -237,24 +237,24 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) man->available_caching = available_caching; man->default_caching = default_caching; man->use_tt = true; - ttm_mem_type_manager_init(man, size_pages); + ttm_resource_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } static void nouveau_ttm_fini_gtt(struct nouveau_drm *drm) { - struct ttm_mem_type_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_TT); + struct ttm_resource_manager *man = ttm_manager_type(&drm->ttm.bdev, TTM_PL_TT); if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA && drm->agp.bridge) ttm_range_man_fini(&drm->ttm.bdev, TTM_PL_TT); else { - ttm_mem_type_manager_set_used(man, false); - ttm_mem_type_manager_force_list_clean(&drm->ttm.bdev, man); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_set_used(man, false); + ttm_resource_manager_force_list_clean(&drm->ttm.bdev, man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, NULL); kfree(man); } diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h index 085280754b3eb..eaf25461cd917 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.h +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h @@ -8,9 +8,9 @@ nouveau_bdev(struct ttm_bo_device *bd) return container_of(bd, struct nouveau_drm, ttm.bdev); } -extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -extern const struct ttm_mem_type_manager_func nouveau_gart_manager; -extern const struct ttm_mem_type_manager_func nv04_gart_manager; +extern const struct ttm_resource_manager_func nouveau_vram_manager; +extern const struct ttm_resource_manager_func nouveau_gart_manager; +extern const struct ttm_resource_manager_func nv04_gart_manager; struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, u32 page_flags); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 7b9f7a94332a6..7270490460143 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -275,10 +275,10 @@ void qxl_ttm_fini(struct qxl_device *qdev) static int qxl_mm_dump_table(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; - struct ttm_mem_type_manager *man = (struct ttm_mem_type_manager *)node->info_ent->data; + struct ttm_resource_manager *man = (struct ttm_resource_manager *)node->info_ent->data; struct drm_printer p = drm_seq_file_printer(m); - ttm_mem_type_manager_debug(man, &p); + ttm_resource_manager_debug(man, &p); return 0; } #endif diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 3ec028dba7390..7f5dfe04789ea 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -224,7 +224,7 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, { struct radeon_device *rdev = dev->dev_private; struct drm_radeon_gem_info *args = data; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; man = ttm_manager_type(&rdev->mman.bdev, TTM_PL_VRAM); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 5f536de3986d1..21a01737b1bed 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -838,7 +838,7 @@ void radeon_ttm_fini(struct radeon_device *rdev) * isn't running */ void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; if (!rdev->mman.initialized) return; @@ -897,7 +897,7 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) unsigned ttm_pl = *(int*)node->info_ent->data; struct drm_device *dev = node->minor->dev; struct radeon_device *rdev = dev->dev_private; - struct ttm_mem_type_manager *man = ttm_manager_type(&rdev->mman.bdev, ttm_pl); + struct ttm_resource_manager *man = ttm_manager_type(&rdev->mman.bdev, ttm_pl); struct drm_printer p = drm_seq_file_printer(m); man->func->debug(man, &p); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e0188250b6ec2..ff68f25ddbd48 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -77,7 +77,7 @@ static inline int ttm_mem_type_from_place(const struct ttm_place *place, return 0; } -void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, +void ttm_resource_manager_debug(struct ttm_resource_manager *man, struct drm_printer *p) { drm_printf(p, " use_type: %d\n", man->use_type); @@ -88,14 +88,14 @@ void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, if (man->func && man->func->debug) (*man->func->debug)(man, p); } -EXPORT_SYMBOL(ttm_mem_type_manager_debug); +EXPORT_SYMBOL(ttm_resource_manager_debug); static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, struct ttm_placement *placement) { struct drm_printer p = drm_debug_printer(TTM_PFX); int i, ret, mem_type; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; drm_printf(&p, "No space for %p (%lu pages, %luK, %luM)\n", bo, bo->mem.num_pages, bo->mem.size >> 10, @@ -108,7 +108,7 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, drm_printf(&p, " placement[%d]=0x%08X (%d)\n", i, placement->placement[i].flags, mem_type); man = ttm_manager_type(bo->bdev, mem_type); - ttm_mem_type_manager_debug(man, &p); + ttm_resource_manager_debug(man, &p); } } @@ -148,7 +148,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; if (!list_empty(&bo->lru)) return; @@ -223,7 +223,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { struct ttm_lru_bulk_move_pos *pos = &bulk->tt[i]; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; if (!pos->first) continue; @@ -238,7 +238,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { struct ttm_lru_bulk_move_pos *pos = &bulk->vram[i]; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; if (!pos->first) continue; @@ -272,8 +272,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *old_man = ttm_manager_type(bdev, bo->mem.mem_type); - struct ttm_mem_type_manager *new_man = ttm_manager_type(bdev, mem->mem_type); + struct ttm_resource_manager *old_man = ttm_manager_type(bdev, bo->mem.mem_type); + struct ttm_resource_manager *new_man = ttm_manager_type(bdev, mem->mem_type); int ret; ret = ttm_mem_io_lock(old_man, true); @@ -551,7 +551,7 @@ static void ttm_bo_release(struct kref *kref) struct ttm_buffer_object *bo = container_of(kref, struct ttm_buffer_object, kref); struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); size_t acc_size = bo->acc_size; int ret; @@ -768,7 +768,7 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, } static int ttm_mem_evict_first(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man, + struct ttm_resource_manager *man, const struct ttm_place *place, struct ttm_operation_ctx *ctx, struct ww_acquire_ctx *ticket) @@ -843,7 +843,7 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); mem->mm_node = NULL; if (!man->func || !man->func->get_node) @@ -854,7 +854,7 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); if (!man->func || !man->func->put_node) return; @@ -869,7 +869,7 @@ EXPORT_SYMBOL(ttm_bo_mem_put); * Add the last move fence to the BO and reserve a new shared slot. */ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, - struct ttm_mem_type_manager *man, + struct ttm_resource_manager *man, struct ttm_mem_reg *mem, bool no_wait_gpu) { @@ -909,7 +909,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); struct ww_acquire_ctx *ticket; int ret; @@ -929,7 +929,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, return ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu); } -static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, +static uint32_t ttm_bo_select_caching(struct ttm_resource_manager *man, uint32_t cur_placement, uint32_t proposed_placement) { @@ -954,7 +954,7 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, return result; } -static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, +static bool ttm_bo_mt_compatible(struct ttm_resource_manager *man, uint32_t mem_type, const struct ttm_place *place, uint32_t *masked_placement) @@ -991,7 +991,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, { struct ttm_bo_device *bdev = bo->bdev; uint32_t mem_type = TTM_PL_SYSTEM; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; uint32_t cur_flags = 0; int ret; @@ -1000,7 +1000,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, return ret; man = ttm_manager_type(bdev, mem_type); - if (!man || !ttm_mem_type_manager_used(man)) + if (!man || !ttm_resource_manager_used(man)) return -EBUSY; if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags)) @@ -1047,7 +1047,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, for (i = 0; i < placement->num_placement; ++i) { const struct ttm_place *place = &placement->placement[i]; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; ret = ttm_bo_mem_placement(bo, place, mem, ctx); if (ret == -EBUSY) @@ -1404,8 +1404,8 @@ int ttm_bo_create(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_bo_create); -int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man) +int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man) { struct ttm_operation_ctx ctx = { .interruptible = false, @@ -1447,12 +1447,12 @@ int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, return 0; } -EXPORT_SYMBOL(ttm_mem_type_manager_force_list_clean); +EXPORT_SYMBOL(ttm_resource_manager_force_list_clean); int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, mem_type); if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) { pr_err("Illegal memory manager memory type %u\n", mem_type); @@ -1464,11 +1464,11 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) return 0; } - return ttm_mem_type_manager_force_list_clean(bdev, man); + return ttm_resource_manager_force_list_clean(bdev, man); } EXPORT_SYMBOL(ttm_bo_evict_mm); -void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, +void ttm_resource_manager_init(struct ttm_resource_manager *man, unsigned long p_size) { unsigned i; @@ -1483,7 +1483,7 @@ void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, INIT_LIST_HEAD(&man->lru[i]); man->move = NULL; } -EXPORT_SYMBOL(ttm_mem_type_manager_init); +EXPORT_SYMBOL(ttm_resource_manager_init); static void ttm_bo_global_kobj_release(struct kobject *kobj) { @@ -1550,10 +1550,10 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev) struct ttm_bo_global *glob = &ttm_bo_glob; int ret = 0; unsigned i; - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; man = ttm_manager_type(bdev, TTM_PL_SYSTEM); - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, NULL); mutex_lock(&ttm_global_mutex); @@ -1580,7 +1580,7 @@ EXPORT_SYMBOL(ttm_bo_device_release); static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) { - struct ttm_mem_type_manager *man = &bdev->sysman; + struct ttm_resource_manager *man = &bdev->sysman; /* * Initialize the system memory buffer type. @@ -1590,9 +1590,9 @@ static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(man, 0); + ttm_resource_manager_init(man, 0); ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); } int ttm_bo_device_init(struct ttm_bo_device *bdev, @@ -1643,7 +1643,7 @@ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); ttm_mem_io_lock(man, false); ttm_bo_unmap_virtual_locked(bo); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 879c8ded0cd8c..8ef0de8e36c50 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -91,7 +91,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_move_ttm); -int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible) +int ttm_mem_io_lock(struct ttm_resource_manager *man, bool interruptible) { if (likely(!man->use_io_reserve_lru)) return 0; @@ -103,7 +103,7 @@ int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible) return 0; } -void ttm_mem_io_unlock(struct ttm_mem_type_manager *man) +void ttm_mem_io_unlock(struct ttm_resource_manager *man) { if (likely(!man->use_io_reserve_lru)) return; @@ -111,7 +111,7 @@ void ttm_mem_io_unlock(struct ttm_mem_type_manager *man) mutex_unlock(&man->io_reserve_mutex); } -static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) +static int ttm_mem_io_evict(struct ttm_resource_manager *man) { struct ttm_buffer_object *bo; @@ -129,7 +129,7 @@ static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; if (mem->bus.io_reserved_count++) @@ -162,7 +162,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev, int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) { - struct ttm_mem_type_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); struct ttm_mem_reg *mem = &bo->mem; int ret; @@ -195,7 +195,7 @@ static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, void **virtual) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; void *addr; @@ -230,7 +230,7 @@ static void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, void *virtual) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; man = ttm_manager_type(bdev, mem->mem_type); @@ -303,7 +303,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, new_mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); struct ttm_tt *ttm = bo->ttm; struct ttm_mem_reg *old_mem = &bo->mem; struct ttm_mem_reg old_copy = *old_mem; @@ -570,7 +570,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, unsigned long num_pages, struct ttm_bo_kmap_obj *map) { - struct ttm_mem_type_manager *man = + struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); unsigned long offset, size; int ret; @@ -600,7 +600,7 @@ EXPORT_SYMBOL(ttm_bo_kmap); void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) { struct ttm_buffer_object *bo = map->bo; - struct ttm_mem_type_manager *man = + struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); if (!map->virtual) @@ -634,7 +634,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, new_mem->mem_type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); struct ttm_mem_reg *old_mem = &bo->mem; int ret; struct ttm_buffer_object *ghost_obj; @@ -697,8 +697,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_type_manager *from = ttm_manager_type(bdev, old_mem->mem_type); - struct ttm_mem_type_manager *to = ttm_manager_type(bdev, new_mem->mem_type); + struct ttm_resource_manager *from = ttm_manager_type(bdev, old_mem->mem_type); + struct ttm_resource_manager *to = ttm_manager_type(bdev, new_mem->mem_type); int ret; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index db4e21d11967d..ba2e8bd198ad9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -281,7 +281,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, pgoff_t i; vm_fault_t ret = VM_FAULT_NOPAGE; unsigned long address = vmf->address; - struct ttm_mem_type_manager *man = + struct ttm_resource_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); /* diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index 7fddc74b3827a..df62177cd913e 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -44,17 +44,17 @@ */ struct ttm_range_manager { - struct ttm_mem_type_manager manager; + struct ttm_resource_manager manager; struct drm_mm mm; spinlock_t lock; }; -static inline struct ttm_range_manager *to_range_manager(struct ttm_mem_type_manager *man) +static inline struct ttm_range_manager *to_range_manager(struct ttm_resource_manager *man) { return container_of(man, struct ttm_range_manager, manager); } -static int ttm_range_man_get_node(struct ttm_mem_type_manager *man, +static int ttm_range_man_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) @@ -95,7 +95,7 @@ static int ttm_range_man_get_node(struct ttm_mem_type_manager *man, return ret; } -static void ttm_range_man_put_node(struct ttm_mem_type_manager *man, +static void ttm_range_man_put_node(struct ttm_resource_manager *man, struct ttm_mem_reg *mem) { struct ttm_range_manager *rman = to_range_manager(man); @@ -110,7 +110,7 @@ static void ttm_range_man_put_node(struct ttm_mem_type_manager *man, } } -static const struct ttm_mem_type_manager_func ttm_range_manager_func; +static const struct ttm_resource_manager_func ttm_range_manager_func; int ttm_range_man_init(struct ttm_bo_device *bdev, unsigned type, @@ -119,7 +119,7 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, bool use_tt, unsigned long p_size) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; struct ttm_range_manager *rman; rman = kzalloc(sizeof(*rman), GFP_KERNEL); @@ -133,13 +133,13 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, man->func = &ttm_range_manager_func; - ttm_mem_type_manager_init(man, p_size); + ttm_resource_manager_init(man, p_size); drm_mm_init(&rman->mm, 0, p_size); spin_lock_init(&rman->lock); ttm_set_driver_manager(bdev, type, &rman->manager); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } EXPORT_SYMBOL(ttm_range_man_init); @@ -147,14 +147,14 @@ EXPORT_SYMBOL(ttm_range_man_init); int ttm_range_man_fini(struct ttm_bo_device *bdev, unsigned type) { - struct ttm_mem_type_manager *man = ttm_manager_type(bdev, type); + struct ttm_resource_manager *man = ttm_manager_type(bdev, type); struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; int ret; - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); - ret = ttm_mem_type_manager_force_list_clean(bdev, man); + ret = ttm_resource_manager_force_list_clean(bdev, man); if (ret) return ret; @@ -163,14 +163,14 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, drm_mm_takedown(mm); spin_unlock(&rman->lock); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(bdev, type, NULL); kfree(rman); return 0; } EXPORT_SYMBOL(ttm_range_man_fini); -static void ttm_range_man_debug(struct ttm_mem_type_manager *man, +static void ttm_range_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { struct ttm_range_manager *rman = to_range_manager(man); @@ -180,7 +180,7 @@ static void ttm_range_man_debug(struct ttm_mem_type_manager *man, spin_unlock(&rman->lock); } -static const struct ttm_mem_type_manager_func ttm_range_manager_func = { +static const struct ttm_resource_manager_func ttm_range_manager_func = { .get_node = ttm_range_man_get_node, .put_node = ttm_range_man_put_node, .debug = ttm_range_man_debug diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index a7b3c8ee7f211..a68ae0204bf52 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -630,7 +630,7 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) TTM_PL_FLAG_CACHED, TTM_PL_FLAG_CACHED, false, dev_priv->vram_size >> PAGE_SHIFT); #endif - ttm_mem_type_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); + ttm_resource_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); return ret; } @@ -1189,12 +1189,12 @@ static void vmw_master_drop(struct drm_device *dev, */ static void __vmw_svga_enable(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); spin_lock(&dev_priv->svga_lock); - if (!ttm_mem_type_manager_used(man)) { + if (!ttm_resource_manager_used(man)) { vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); } spin_unlock(&dev_priv->svga_lock); } @@ -1220,11 +1220,11 @@ void vmw_svga_enable(struct vmw_private *dev_priv) */ static void __vmw_svga_disable(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); spin_lock(&dev_priv->svga_lock); - if (ttm_mem_type_manager_used(man)) { - ttm_mem_type_manager_set_used(man, false); + if (ttm_resource_manager_used(man)) { + ttm_resource_manager_set_used(man, false); vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_HIDE | SVGA_REG_ENABLE_ENABLE); @@ -1241,7 +1241,7 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) */ void vmw_svga_disable(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); /* * Disabling SVGA will turn off device modesetting capabilities, so * notify KMS about that so that it doesn't cache atomic state that @@ -1257,8 +1257,8 @@ void vmw_svga_disable(struct vmw_private *dev_priv) vmw_kms_lost_device(dev_priv->dev); ttm_write_lock(&dev_priv->reservation_sem, false); spin_lock(&dev_priv->svga_lock); - if (ttm_mem_type_manager_used(man)) { - ttm_mem_type_manager_set_used(man, false); + if (ttm_resource_manager_used(man)) { + ttm_resource_manager_set_used(man, false); spin_unlock(&dev_priv->svga_lock); if (ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM)) DRM_ERROR("Failed evicting VRAM buffers.\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index ca5037184814c..c8fe6e9cf0921 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -37,7 +37,7 @@ #include <linux/kernel.h> struct vmwgfx_gmrid_man { - struct ttm_mem_type_manager manager; + struct ttm_resource_manager manager; spinlock_t lock; struct ida gmr_ida; uint32_t max_gmr_ids; @@ -45,12 +45,12 @@ struct vmwgfx_gmrid_man { uint32_t used_gmr_pages; }; -static struct vmwgfx_gmrid_man *to_gmrid_manager(struct ttm_mem_type_manager *man) +static struct vmwgfx_gmrid_man *to_gmrid_manager(struct ttm_resource_manager *man) { return container_of(man, struct vmwgfx_gmrid_man, manager); } -static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man, +static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) @@ -84,7 +84,7 @@ static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man, return -ENOSPC; } -static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man, +static void vmw_gmrid_man_put_node(struct ttm_resource_manager *man, struct ttm_mem_reg *mem) { struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); @@ -98,11 +98,11 @@ static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man, } } -static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func; +static const struct ttm_resource_manager_func vmw_gmrid_manager_func; int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; struct vmwgfx_gmrid_man *gman = kzalloc(sizeof(*gman), GFP_KERNEL); @@ -116,7 +116,7 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) man->default_caching = TTM_PL_FLAG_CACHED; /* TODO: This is most likely not correct */ man->use_tt = true; - ttm_mem_type_manager_init(man, 0); + ttm_resource_manager_init(man, 0); spin_lock_init(&gman->lock); gman->used_gmr_pages = 0; ida_init(&gman->gmr_ida); @@ -134,20 +134,20 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) BUG(); } ttm_set_driver_manager(&dev_priv->bdev, type, &gman->manager); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, type); + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, type); struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); - ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); + ttm_resource_manager_force_list_clean(&dev_priv->bdev, man); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&dev_priv->bdev, type, NULL); ida_destroy(&gman->gmr_ida); @@ -155,7 +155,7 @@ void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) } -static const struct ttm_mem_type_manager_func vmw_gmrid_manager_func = { +static const struct ttm_resource_manager_func vmw_gmrid_manager_func = { .get_node = vmw_gmrid_man_get_node, .put_node = vmw_gmrid_man_put_node, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 4110e83091880..6cac7b091205f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -16,12 +16,12 @@ * @lock: Manager lock. */ struct vmw_thp_manager { - struct ttm_mem_type_manager manager; + struct ttm_resource_manager manager; struct drm_mm mm; spinlock_t lock; }; -static struct vmw_thp_manager *to_thp_manager(struct ttm_mem_type_manager *man) +static struct vmw_thp_manager *to_thp_manager(struct ttm_resource_manager *man) { return container_of(man, struct vmw_thp_manager, manager); } @@ -44,7 +44,7 @@ static int vmw_thp_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node, return -ENOSPC; } -static int vmw_thp_get_node(struct ttm_mem_type_manager *man, +static int vmw_thp_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem) @@ -106,7 +106,7 @@ static int vmw_thp_get_node(struct ttm_mem_type_manager *man, -static void vmw_thp_put_node(struct ttm_mem_type_manager *man, +static void vmw_thp_put_node(struct ttm_resource_manager *man, struct ttm_mem_reg *mem) { struct vmw_thp_manager *rman = to_thp_manager(man); @@ -123,7 +123,7 @@ static void vmw_thp_put_node(struct ttm_mem_type_manager *man, int vmw_thp_init(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man; + struct ttm_resource_manager *man; struct vmw_thp_manager *rman; rman = kzalloc(sizeof(*rman), GFP_KERNEL); @@ -134,39 +134,39 @@ int vmw_thp_init(struct vmw_private *dev_priv) man->available_caching = TTM_PL_FLAG_CACHED; man->default_caching = TTM_PL_FLAG_CACHED; - ttm_mem_type_manager_init(man, + ttm_resource_manager_init(man, dev_priv->vram_size >> PAGE_SHIFT); drm_mm_init(&rman->mm, 0, man->size); spin_lock_init(&rman->lock); ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, &rman->manager); - ttm_mem_type_manager_set_used(man, true); + ttm_resource_manager_set_used(man, true); return 0; } void vmw_thp_fini(struct vmw_private *dev_priv) { - struct ttm_mem_type_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); + struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); struct vmw_thp_manager *rman = to_thp_manager(man); struct drm_mm *mm = &rman->mm; int ret; - ttm_mem_type_manager_set_used(man, false); + ttm_resource_manager_set_used(man, false); - ret = ttm_mem_type_manager_force_list_clean(&dev_priv->bdev, man); + ret = ttm_resource_manager_force_list_clean(&dev_priv->bdev, man); if (ret) return; spin_lock(&rman->lock); drm_mm_clean(mm); drm_mm_takedown(mm); spin_unlock(&rman->lock); - ttm_mem_type_manager_cleanup(man); + ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, NULL); kfree(rman); } -static void vmw_thp_debug(struct ttm_mem_type_manager *man, +static void vmw_thp_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { struct vmw_thp_manager *rman = to_thp_manager(man); @@ -176,7 +176,7 @@ static void vmw_thp_debug(struct ttm_mem_type_manager *man, spin_unlock(&rman->lock); } -const struct ttm_mem_type_manager_func vmw_thp_func = { +const struct ttm_resource_manager_func vmw_thp_func = { .get_node = vmw_thp_get_node, .put_node = vmw_thp_put_node, .debug = vmw_thp_debug diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 95d6c648d5c67..7b0655bc13dab 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -54,7 +54,7 @@ struct ttm_place; struct ttm_lru_bulk_move; -struct ttm_mem_type_manager; +struct ttm_resource_manager; /** * struct ttm_bus_placement @@ -534,14 +534,14 @@ int ttm_bo_create(struct ttm_bo_device *bdev, unsigned long size, struct ttm_buffer_object **p_bo); /** - * ttm_mem_type_manager_init + * ttm_resource_manager_init * * @man: memory manager object to init * @p_size: size managed area in pages. * * Initialise core parts of a manager object. */ -void ttm_mem_type_manager_init(struct ttm_mem_type_manager *man, +void ttm_resource_manager_init(struct ttm_resource_manager *man, unsigned long p_size); /** diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 31264a09ec63d..d17e25ba80d44 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -45,11 +45,11 @@ #define TTM_MAX_BO_PRIORITY 4U -struct ttm_mem_type_manager; +struct ttm_resource_manager; -struct ttm_mem_type_manager_func { +struct ttm_resource_manager_func { /** - * struct ttm_mem_type_manager member get_node + * struct ttm_resource_manager member get_node * * @man: Pointer to a memory type manager. * @bo: Pointer to the buffer object we're allocating space for. @@ -69,20 +69,20 @@ struct ttm_mem_type_manager_func { * the function should return a negative error code. * * Note that @mem::mm_node will only be dereferenced by - * struct ttm_mem_type_manager functions and optionally by the driver, + * struct ttm_resource_manager functions and optionally by the driver, * which has knowledge of the underlying type. * * This function may not be called from within atomic context, so * an implementation can and must use either a mutex or a spinlock to * protect any data structures managing the space. */ - int (*get_node)(struct ttm_mem_type_manager *man, + int (*get_node)(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *mem); /** - * struct ttm_mem_type_manager member put_node + * struct ttm_resource_manager member put_node * * @man: Pointer to a memory type manager. * @mem: Pointer to a struct ttm_mem_reg to be filled in. @@ -91,11 +91,11 @@ struct ttm_mem_type_manager_func { * and that are identified by @mem::mm_node and @mem::start. May not * be called from within atomic context. */ - void (*put_node)(struct ttm_mem_type_manager *man, + void (*put_node)(struct ttm_resource_manager *man, struct ttm_mem_reg *mem); /** - * struct ttm_mem_type_manager member debug + * struct ttm_resource_manager member debug * * @man: Pointer to a memory type manager. * @printer: Prefix to be used in printout to identify the caller. @@ -104,12 +104,12 @@ struct ttm_mem_type_manager_func { * type manager to aid debugging of out-of-memory conditions. * It may not be called from within atomic context. */ - void (*debug)(struct ttm_mem_type_manager *man, + void (*debug)(struct ttm_resource_manager *man, struct drm_printer *printer); }; /** - * struct ttm_mem_type_manager + * struct ttm_resource_manager * * @use_type: The memory type is enabled. * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory @@ -136,7 +136,7 @@ struct ttm_mem_type_manager_func { -struct ttm_mem_type_manager { +struct ttm_resource_manager { /* * No protection. Constant from start. */ @@ -145,7 +145,7 @@ struct ttm_mem_type_manager { uint64_t size; uint32_t available_caching; uint32_t default_caching; - const struct ttm_mem_type_manager_func *func; + const struct ttm_resource_manager_func *func; struct mutex io_reserve_mutex; bool use_io_reserve_lru; spinlock_t move_lock; @@ -390,7 +390,7 @@ extern struct ttm_bo_global { * struct ttm_bo_device - Buffer object driver device-specific data. * * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver. - * @man: An array of mem_type_managers. + * @man: An array of resource_managers. * @vma_manager: Address space manager (pointer) * lru_lock: Spinlock that protects the buffer+device lru lists and * ddestroy lists. @@ -411,8 +411,8 @@ struct ttm_bo_device { /* * access via ttm_manager_type. */ - struct ttm_mem_type_manager sysman; - struct ttm_mem_type_manager *man_drv[TTM_NUM_MEM_TYPES]; + struct ttm_resource_manager sysman; + struct ttm_resource_manager *man_drv[TTM_NUM_MEM_TYPES]; /* * Protected by internal locks. */ @@ -440,7 +440,7 @@ struct ttm_bo_device { bool no_retry; }; -static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device *bdev, +static inline struct ttm_resource_manager *ttm_manager_type(struct ttm_bo_device *bdev, int mem_type) { return bdev->man_drv[mem_type]; @@ -448,7 +448,7 @@ static inline struct ttm_mem_type_manager *ttm_manager_type(struct ttm_bo_device static inline void ttm_set_driver_manager(struct ttm_bo_device *bdev, int type, - struct ttm_mem_type_manager *manager) + struct ttm_resource_manager *manager) { bdev->man_drv[type] = manager; } @@ -581,8 +581,8 @@ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo); int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo); void ttm_mem_io_free_vm(struct ttm_buffer_object *bo); -int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible); -void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); +int ttm_mem_io_lock(struct ttm_resource_manager *man, bool interruptible); +void ttm_mem_io_unlock(struct ttm_resource_manager *man); /** * ttm_bo_reserve: @@ -676,7 +676,7 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) } /** - * ttm_mem_type_manager_set_used + * ttm_resource_manager_set_used * * @man: A memory manager object. * @used: usage state to set. @@ -684,13 +684,13 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) * Set the manager in use flag. If disabled the manager is no longer * used for object placement. */ -static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *man, bool used) +static inline void ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) { man->use_type = used; } /** - * ttm_mem_type_manager_used + * ttm_resource_manager_used * * @man: Manager to get used state for * @@ -698,26 +698,26 @@ static inline void ttm_mem_type_manager_set_used(struct ttm_mem_type_manager *ma * Returns: * true is used, false if not. */ -static inline bool ttm_mem_type_manager_used(struct ttm_mem_type_manager *man) +static inline bool ttm_resource_manager_used(struct ttm_resource_manager *man) { return man->use_type; } /** - * ttm_mem_type_manager_cleanup + * ttm_resource_manager_cleanup * * @man: A memory manager object. * * Cleanup the move fences from the memory manager object. */ -static inline void ttm_mem_type_manager_cleanup(struct ttm_mem_type_manager *man) +static inline void ttm_resource_manager_cleanup(struct ttm_resource_manager *man) { dma_fence_put(man->move); man->move = NULL; } /* - * ttm_mem_type_manager_force_list_clean + * ttm_resource_manager_force_list_clean * * @bdev - device to use * @man - manager to use @@ -725,8 +725,8 @@ static inline void ttm_mem_type_manager_cleanup(struct ttm_mem_type_manager *man * Force all the objects out of a memory manager until clean. * Part of memory manager cleanup sequence. */ -int ttm_mem_type_manager_force_list_clean(struct ttm_bo_device *bdev, - struct ttm_mem_type_manager *man); +int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man); /* * ttm_bo_util.c @@ -875,12 +875,12 @@ int ttm_range_man_fini(struct ttm_bo_device *bdev, unsigned type); /** - * ttm_mem_type_manager_debug + * ttm_resource_manager_debug * * @man: manager type to dump. * @p: printer to use for debug. */ -void ttm_mem_type_manager_debug(struct ttm_mem_type_manager *man, +void ttm_resource_manager_debug(struct ttm_resource_manager *man, struct drm_printer *p); #endif -- GitLab From 2966141ad2dda23d1b37997de6a4389b7864c169 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 4 Aug 2020 12:56:32 +1000 Subject: [PATCH 0305/1494] drm/ttm: rename ttm_mem_reg to ttm_resource. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This name better reflects what the object does. I didn't rename all the pointers it seemed too messy. Signed-off-by: Dave Airlie <airlied@redhat.com> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804025632.3868079-60-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 6 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 46 +++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 10 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 12 ++--- drivers/gpu/drm/drm_gem_vram_helper.c | 6 +-- drivers/gpu/drm/nouveau/nouveau_bo.c | 46 +++++++++--------- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 +- drivers/gpu/drm/nouveau/nouveau_mem.c | 8 ++-- drivers/gpu/drm/nouveau/nouveau_mem.h | 10 ++-- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 4 +- drivers/gpu/drm/nouveau/nouveau_ttm.c | 8 ++-- drivers/gpu/drm/nouveau/nv17_fence.c | 2 +- drivers/gpu/drm/nouveau/nv50_fence.c | 2 +- drivers/gpu/drm/qxl/qxl_drv.h | 2 +- drivers/gpu/drm/qxl/qxl_ttm.c | 14 +++--- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 2 +- drivers/gpu/drm/radeon/radeon_object.h | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 28 +++++------ drivers/gpu/drm/radeon/radeon_vm.c | 2 +- drivers/gpu/drm/ttm/ttm_agp_backend.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 26 +++++----- drivers/gpu/drm/ttm/ttm_bo_util.c | 46 +++++++++--------- drivers/gpu/drm/ttm/ttm_range_manager.c | 4 +- drivers/gpu/drm/ttm/ttm_tt.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 6 +-- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 8 ++-- include/drm/ttm/ttm_bo_api.h | 10 ++-- include/drm/ttm/ttm_bo_driver.h | 48 +++++++++---------- include/drm/ttm/ttm_tt.h | 10 ++-- 37 files changed, 199 insertions(+), 199 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index b9050b7221d5e..c847a5fe94c92 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -171,7 +171,7 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) * * Check if a mem object has already address space allocated. */ -bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem) +bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_resource *mem) { return mem->mm_node != NULL; } @@ -189,7 +189,7 @@ bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem) static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node; @@ -252,7 +252,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, * Free the allocated GTT again. */ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); struct amdgpu_gtt_node *node = mem->mm_node; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index ce98df5b0c219..43f4966331dd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1268,11 +1268,11 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, */ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; if (!amdgpu_bo_is_amdgpu_bo(bo)) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index e01e8903741e3..5ddb6cf960301 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -283,7 +283,7 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, uint64_t *flags); void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); void amdgpu_bo_release_notify(struct ttm_buffer_object *bo); int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 2fc0214d9a95c..28557839f1329 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -182,9 +182,9 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) * Assign the memory from new_mem to the memory of the buffer object bo. */ static void amdgpu_move_null(struct ttm_buffer_object *bo, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; BUG_ON(old_mem->mm_node != NULL); *old_mem = *new_mem; @@ -201,7 +201,7 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, */ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, struct drm_mm_node *mm_node, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { uint64_t addr = 0; @@ -221,7 +221,7 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, * @offset: The offset that drm_mm_node is used for finding. * */ -static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, +static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_resource *mem, uint64_t *offset) { struct drm_mm_node *mm_node = mem->mm_node; @@ -249,7 +249,7 @@ static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, * the physical address for local memory. */ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct drm_mm_node *mm_node, unsigned num_pages, uint64_t offset, unsigned window, struct amdgpu_ring *ring, @@ -473,8 +473,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, */ static int amdgpu_move_blit(struct ttm_buffer_object *bo, bool evict, bool no_wait_gpu, - struct ttm_mem_reg *new_mem, - struct ttm_mem_reg *old_mem) + struct ttm_resource *new_mem, + struct ttm_resource *old_mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); @@ -533,10 +533,10 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, */ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg tmp_mem; + struct ttm_resource *old_mem = &bo->mem; + struct ttm_resource tmp_mem; struct ttm_place placements; struct ttm_placement placement; int r; @@ -589,10 +589,10 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, */ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg tmp_mem; + struct ttm_resource *old_mem = &bo->mem; + struct ttm_resource tmp_mem; struct ttm_placement placement; struct ttm_place placements; int r; @@ -635,7 +635,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, * Called by amdgpu_bo_move() */ static bool amdgpu_mem_visible(struct amdgpu_device *adev, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct drm_mm_node *nodes = mem->mm_node; @@ -645,7 +645,7 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev, if (mem->mem_type != TTM_PL_VRAM) return false; - /* ttm_mem_reg_ioremap only supports contiguous memory */ + /* ttm_resource_ioremap only supports contiguous memory */ if (nodes->size != mem->num_pages) return false; @@ -660,11 +660,11 @@ static bool amdgpu_mem_visible(struct amdgpu_device *adev, */ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct amdgpu_device *adev; struct amdgpu_bo *abo; - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; int r; /* Can't move a pinned BO */ @@ -746,7 +746,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, * * Called by ttm_mem_io_reserve() ultimately via ttm_bo_vm_fault() */ -static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct drm_mm_node *mm_node = mem->mm_node; @@ -770,7 +770,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_ return -EINVAL; /* Only physically contiguous buffers apply. In a contiguous * buffer, size of the first mm_node would match the number of - * pages in ttm_mem_reg. + * pages in ttm_resource. */ if (adev->mman.aper_base_kaddr && (mm_node->size == mem->num_pages)) @@ -1115,7 +1115,7 @@ int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, * This handles binding GTT memory to the device address space. */ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, - struct ttm_mem_reg *bo_mem) + struct ttm_resource *bo_mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void*)ttm; @@ -1166,7 +1166,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct ttm_operation_ctx ctx = { false, false }; struct amdgpu_ttm_tt *gtt = (void*)bo->ttm; - struct ttm_mem_reg tmp; + struct ttm_resource tmp; struct ttm_placement placement; struct ttm_place placements; uint64_t addr, flags; @@ -1507,7 +1507,7 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) * * Figure out the flags to use for a VM PDE (Page Directory Entry). */ -uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_mem_reg *mem) +uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem) { uint64_t flags = 0; @@ -1533,7 +1533,7 @@ uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_mem_reg *mem) * Figure out the flags to use for a VM PTE (Page Table Entry). */ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { uint64_t flags = amdgpu_ttm_tt_pde_flags(ttm, mem); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 3db29ae1f8028..36b024fd077e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -63,7 +63,7 @@ struct amdgpu_mman { struct amdgpu_copy_mem { struct ttm_buffer_object *bo; - struct ttm_mem_reg *mem; + struct ttm_resource *mem; unsigned long offset; }; @@ -72,13 +72,13 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev); int amdgpu_vram_mgr_init(struct amdgpu_device *adev); void amdgpu_vram_mgr_fini(struct amdgpu_device *adev); -bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem); +bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_resource *mem); uint64_t amdgpu_gtt_mgr_usage(struct ttm_resource_manager *man); int amdgpu_gtt_mgr_recover(struct ttm_resource_manager *man); u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo); int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct device *dev, enum dma_data_direction dir, struct sg_table **sgt); @@ -142,9 +142,9 @@ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, int *last_invalidated); bool amdgpu_ttm_tt_is_userptr(struct ttm_tt *ttm); bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm); -uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_mem_reg *mem); +uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem); uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 7417754e9141b..920a0553e1727 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1765,7 +1765,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, struct amdgpu_vm *vm = bo_va->base.vm; struct amdgpu_bo_va_mapping *mapping; dma_addr_t *pages_addr = NULL; - struct ttm_mem_reg *mem; + struct ttm_resource *mem; struct drm_mm_node *nodes; struct dma_fence **last_update; struct dma_resv *resv; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 6f888a63f22d0..895634cbf999c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -272,7 +272,7 @@ static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev, u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct ttm_mem_reg *mem = &bo->tbo.mem; + struct ttm_resource *mem = &bo->tbo.mem; struct drm_mm_node *nodes = mem->mm_node; unsigned pages = mem->num_pages; u64 usage; @@ -292,13 +292,13 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo) /** * amdgpu_vram_mgr_virt_start - update virtual start address * - * @mem: ttm_mem_reg to update + * @mem: ttm_resource to update * @node: just allocated node * * Calculate a virtual BO start address to easily check if everything is CPU * accessible. */ -static void amdgpu_vram_mgr_virt_start(struct ttm_mem_reg *mem, +static void amdgpu_vram_mgr_virt_start(struct ttm_resource *mem, struct drm_mm_node *node) { unsigned long start; @@ -324,7 +324,7 @@ static void amdgpu_vram_mgr_virt_start(struct ttm_mem_reg *mem, static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, struct ttm_buffer_object *tbo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); struct amdgpu_device *adev = mgr->adev; @@ -442,7 +442,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, * Free the allocated VRAM again. */ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); struct amdgpu_device *adev = mgr->adev; @@ -482,7 +482,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, * Allocate and fill a sg table from a VRAM allocation. */ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct device *dev, enum dma_data_direction dir, struct sg_table **sgt) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index e3660d00987d9..b410930d94a09 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -653,7 +653,7 @@ static void drm_gem_vram_bo_driver_evict_flags(struct drm_gem_vram_object *gbo, static void drm_gem_vram_bo_driver_move_notify(struct drm_gem_vram_object *gbo, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_bo_kmap_obj *kmap = &gbo->kmap; @@ -1020,7 +1020,7 @@ static void bo_driver_evict_flags(struct ttm_buffer_object *bo, static void bo_driver_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct drm_gem_vram_object *gbo; @@ -1034,7 +1034,7 @@ static void bo_driver_move_notify(struct ttm_buffer_object *bo, } static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 51416086e2f40..604a743236964 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -679,7 +679,7 @@ nve0_bo_move_init(struct nouveau_channel *chan, u32 handle) static int nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 10); @@ -711,7 +711,7 @@ nvc0_bo_move_init(struct nouveau_channel *chan, u32 handle) static int nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); u64 src_offset = mem->vma[0].addr; @@ -749,7 +749,7 @@ nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); u64 src_offset = mem->vma[0].addr; @@ -788,7 +788,7 @@ nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); u64 src_offset = mem->vma[0].addr; @@ -826,7 +826,7 @@ nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 7); @@ -844,7 +844,7 @@ nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 7); @@ -878,7 +878,7 @@ nv50_bo_move_init(struct nouveau_channel *chan, u32 handle) static int nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { struct nouveau_mem *mem = nouveau_mem(old_reg); u64 length = (new_reg->num_pages << PAGE_SHIFT); @@ -965,7 +965,7 @@ nv04_bo_move_init(struct nouveau_channel *chan, u32 handle) static inline uint32_t nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, - struct nouveau_channel *chan, struct ttm_mem_reg *reg) + struct nouveau_channel *chan, struct ttm_resource *reg) { if (reg->mem_type == TTM_PL_TT) return NvDmaTT; @@ -974,7 +974,7 @@ nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, static int nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) + struct ttm_resource *old_reg, struct ttm_resource *new_reg) { u32 src_offset = old_reg->start << PAGE_SHIFT; u32 dst_offset = new_reg->start << PAGE_SHIFT; @@ -1020,7 +1020,7 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, static int nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, - struct ttm_mem_reg *reg) + struct ttm_resource *reg) { struct nouveau_mem *old_mem = nouveau_mem(&bo->mem); struct nouveau_mem *new_mem = nouveau_mem(reg); @@ -1052,7 +1052,7 @@ nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, static int nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, - bool no_wait_gpu, struct ttm_mem_reg *new_reg) + bool no_wait_gpu, struct ttm_resource *new_reg) { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_channel *chan = drm->ttm.chan; @@ -1062,7 +1062,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, /* create temporary vmas for the transfer and attach them to the * old nvkm_mem node, these will get cleaned up after ttm has - * destroyed the ttm_mem_reg + * destroyed the ttm_resource */ if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { ret = nouveau_bo_move_prep(drm, bo, new_reg); @@ -1098,7 +1098,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm) s32 oclass; int (*exec)(struct nouveau_channel *, struct ttm_buffer_object *, - struct ttm_mem_reg *, struct ttm_mem_reg *); + struct ttm_resource *, struct ttm_resource *); int (*init)(struct nouveau_channel *, u32 handle); } _methods[] = { { "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init }, @@ -1160,7 +1160,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm) static int nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, - bool no_wait_gpu, struct ttm_mem_reg *new_reg) + bool no_wait_gpu, struct ttm_resource *new_reg) { struct ttm_operation_ctx ctx = { intr, no_wait_gpu }; struct ttm_place placement_memtype = { @@ -1169,7 +1169,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, .flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING }; struct ttm_placement placement; - struct ttm_mem_reg tmp_reg; + struct ttm_resource tmp_reg; int ret; placement.num_placement = placement.num_busy_placement = 1; @@ -1197,7 +1197,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, static int nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, - bool no_wait_gpu, struct ttm_mem_reg *new_reg) + bool no_wait_gpu, struct ttm_resource *new_reg) { struct ttm_operation_ctx ctx = { intr, no_wait_gpu }; struct ttm_place placement_memtype = { @@ -1206,7 +1206,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, .flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING }; struct ttm_placement placement; - struct ttm_mem_reg tmp_reg; + struct ttm_resource tmp_reg; int ret; placement.num_placement = placement.num_busy_placement = 1; @@ -1233,7 +1233,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_reg) + struct ttm_resource *new_reg) { struct nouveau_mem *mem = new_reg ? nouveau_mem(new_reg) : NULL; struct nouveau_bo *nvbo = nouveau_bo(bo); @@ -1265,7 +1265,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, } static int -nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_reg, +nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_resource *new_reg, struct nouveau_drm_tile **new_tile) { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); @@ -1301,11 +1301,11 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, static int nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_reg) + struct ttm_resource *new_reg) { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); - struct ttm_mem_reg *old_reg = &bo->mem; + struct ttm_resource *old_reg = &bo->mem; struct nouveau_drm_tile *new_tile = NULL; int ret = 0; @@ -1374,7 +1374,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) } static int -nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) +nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) { struct nouveau_drm *drm = nouveau_bdev(bdev); struct nvkm_device *device = nvxx_device(&drm->client.device); @@ -1454,7 +1454,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) } static void -nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) +nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_resource *reg) { struct nouveau_drm *drm = nouveau_bdev(bdev); struct nouveau_mem *mem = nouveau_mem(reg); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2a6519737800c..b4314c01e3132 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -155,7 +155,7 @@ struct nouveau_drm { atomic_t validate_sequence; int (*move)(struct nouveau_channel *, struct ttm_buffer_object *, - struct ttm_mem_reg *, struct ttm_mem_reg *); + struct ttm_resource *, struct ttm_resource *); struct nouveau_channel *chan; struct nvif_object copy; int mtrr; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index c002f89685073..9559f925bb539 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -92,7 +92,7 @@ nouveau_mem_fini(struct nouveau_mem *mem) } int -nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt) +nouveau_mem_host(struct ttm_resource *reg, struct ttm_dma_tt *tt) { struct nouveau_mem *mem = nouveau_mem(reg); struct nouveau_cli *cli = mem->cli; @@ -130,7 +130,7 @@ nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt) } int -nouveau_mem_vram(struct ttm_mem_reg *reg, bool contig, u8 page) +nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page) { struct nouveau_mem *mem = nouveau_mem(reg); struct nouveau_cli *cli = mem->cli; @@ -173,7 +173,7 @@ nouveau_mem_vram(struct ttm_mem_reg *reg, bool contig, u8 page) } void -nouveau_mem_del(struct ttm_mem_reg *reg) +nouveau_mem_del(struct ttm_resource *reg) { struct nouveau_mem *mem = nouveau_mem(reg); nouveau_mem_fini(mem); @@ -183,7 +183,7 @@ nouveau_mem_del(struct ttm_mem_reg *reg) int nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, - struct ttm_mem_reg *reg) + struct ttm_resource *reg) { struct nouveau_mem *mem; diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index f6d039e738121..3fe1cfed57a11 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -7,7 +7,7 @@ struct ttm_dma_tt; #include <nvif/vmm.h> static inline struct nouveau_mem * -nouveau_mem(struct ttm_mem_reg *reg) +nouveau_mem(struct ttm_resource *reg) { return reg->mm_node; } @@ -21,10 +21,10 @@ struct nouveau_mem { }; int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, - struct ttm_mem_reg *); -void nouveau_mem_del(struct ttm_mem_reg *); -int nouveau_mem_vram(struct ttm_mem_reg *, bool contig, u8 page); -int nouveau_mem_host(struct ttm_mem_reg *, struct ttm_dma_tt *); + struct ttm_resource *); +void nouveau_mem_del(struct ttm_resource *); +int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page); +int nouveau_mem_host(struct ttm_resource *, struct ttm_dma_tt *); void nouveau_mem_fini(struct nouveau_mem *); int nouveau_mem_map(struct nouveau_mem *, struct nvif_vmm *, struct nvif_vma *); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index feaac908efed3..1ec97f5c3cf5c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -26,7 +26,7 @@ nouveau_sgdma_destroy(struct ttm_tt *ttm) } static int -nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) +nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct nouveau_mem *mem = nouveau_mem(reg); @@ -61,7 +61,7 @@ static struct ttm_backend_func nv04_sgdma_backend = { }; static int -nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) +nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct nouveau_mem *mem = nouveau_mem(reg); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 78b5a87b98553..e6a30865a00bb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -32,7 +32,7 @@ #include <core/tegra.h> static void -nouveau_manager_del(struct ttm_resource_manager *man, struct ttm_mem_reg *reg) +nouveau_manager_del(struct ttm_resource_manager *man, struct ttm_resource *reg) { nouveau_mem_del(reg); } @@ -41,7 +41,7 @@ static int nouveau_vram_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *reg) + struct ttm_resource *reg) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_drm *drm = nouveau_bdev(bo->bdev); @@ -72,7 +72,7 @@ static int nouveau_gart_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *reg) + struct ttm_resource *reg) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_drm *drm = nouveau_bdev(bo->bdev); @@ -95,7 +95,7 @@ static int nv04_gart_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *reg) + struct ttm_resource *reg) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_drm *drm = nouveau_bdev(bo->bdev); diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 5d613d43b84d2..5121124267ffd 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -76,7 +76,7 @@ nv17_fence_context_new(struct nouveau_channel *chan) { struct nv10_fence_priv *priv = chan->drm->fence; struct nv10_fence_chan *fctx; - struct ttm_mem_reg *reg = &priv->bo->bo.mem; + struct ttm_resource *reg = &priv->bo->bo.mem; u32 start = reg->start * PAGE_SIZE; u32 limit = start + reg->size - 1; int ret = 0; diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index a00ecc3de0535..d7288691a874c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -37,7 +37,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) { struct nv10_fence_priv *priv = chan->drm->fence; struct nv10_fence_chan *fctx; - struct ttm_mem_reg *reg = &priv->bo->bo.mem; + struct ttm_resource *reg = &priv->bo->bo.mem; u32 start = reg->start * PAGE_SIZE; u32 limit = start + reg->size - 1; int ret; diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 9691449aefdb4..aae90a9ee1dbc 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -350,7 +350,7 @@ int qxl_mode_dumb_mmap(struct drm_file *filp, int qxl_ttm_init(struct qxl_device *qdev); void qxl_ttm_fini(struct qxl_device *qdev); int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /* qxl image */ diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 7270490460143..b1ea984f143a7 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -71,7 +71,7 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo, } int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct qxl_device *qdev = qxl_get_qdev(bdev); @@ -111,7 +111,7 @@ struct qxl_ttm_tt { }; static int qxl_ttm_backend_bind(struct ttm_tt *ttm, - struct ttm_mem_reg *bo_mem) + struct ttm_resource *bo_mem) { struct qxl_ttm_tt *gtt = (void *)ttm; @@ -164,9 +164,9 @@ static struct ttm_tt *qxl_ttm_tt_create(struct ttm_buffer_object *bo, } static void qxl_move_null(struct ttm_buffer_object *bo, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; BUG_ON(old_mem->mm_node != NULL); *old_mem = *new_mem; @@ -175,9 +175,9 @@ static void qxl_move_null(struct ttm_buffer_object *bo, static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; int ret; ret = ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu); @@ -193,7 +193,7 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, static void qxl_bo_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct qxl_bo *qbo; struct qxl_device *qdev; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b7c3fb2bfb547..cc4f58d165896 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2857,7 +2857,7 @@ int radeon_vm_clear_invalids(struct radeon_device *rdev, struct radeon_vm *vm); int radeon_vm_bo_update(struct radeon_device *rdev, struct radeon_bo_va *bo_va, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); void radeon_vm_bo_invalidate(struct radeon_device *rdev, struct radeon_bo *bo); struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm, diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index f3dee01250dab..bb7582afd803e 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -775,7 +775,7 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, void radeon_bo_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct radeon_bo *rbo; diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 60275b822f79e..44b47241ee42b 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -165,7 +165,7 @@ extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop); extern void radeon_bo_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); extern int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo); extern int radeon_bo_get_surface_reg(struct radeon_bo *bo); extern void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 21a01737b1bed..3355b69b13d14 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -166,9 +166,9 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) } static void radeon_move_null(struct ttm_buffer_object *bo, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; BUG_ON(old_mem->mm_node != NULL); *old_mem = *new_mem; @@ -177,8 +177,8 @@ static void radeon_move_null(struct ttm_buffer_object *bo, static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict, bool no_wait_gpu, - struct ttm_mem_reg *new_mem, - struct ttm_mem_reg *old_mem) + struct ttm_resource *new_mem, + struct ttm_resource *old_mem) { struct radeon_device *rdev; uint64_t old_start, new_start; @@ -233,11 +233,11 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, static int radeon_move_vram_ram(struct ttm_buffer_object *bo, bool evict, bool interruptible, bool no_wait_gpu, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_operation_ctx ctx = { interruptible, no_wait_gpu }; - struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg tmp_mem; + struct ttm_resource *old_mem = &bo->mem; + struct ttm_resource tmp_mem; struct ttm_place placements; struct ttm_placement placement; int r; @@ -278,11 +278,11 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, static int radeon_move_ram_vram(struct ttm_buffer_object *bo, bool evict, bool interruptible, bool no_wait_gpu, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_operation_ctx ctx = { interruptible, no_wait_gpu }; - struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg tmp_mem; + struct ttm_resource *old_mem = &bo->mem; + struct ttm_resource tmp_mem; struct ttm_placement placement; struct ttm_place placements; int r; @@ -315,11 +315,11 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct radeon_device *rdev; struct radeon_bo *rbo; - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; int r; r = ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu); @@ -376,7 +376,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, return 0; } -static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { struct radeon_device *rdev = radeon_get_rdev(bdev); @@ -544,7 +544,7 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm) } static int radeon_ttm_backend_bind(struct ttm_tt *ttm, - struct ttm_mem_reg *bo_mem) + struct ttm_resource *bo_mem) { struct radeon_ttm_tt *gtt = (void*)ttm; uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ | diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index f60fae0aed11b..71e2c3785ab9d 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -911,7 +911,7 @@ static void radeon_vm_fence_pts(struct radeon_vm *vm, */ int radeon_vm_bo_update(struct radeon_device *rdev, struct radeon_bo_va *bo_va, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct radeon_vm *vm = bo_va->vm; struct radeon_ib ib; diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 6050dc8468942..8f24663c3df34 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -48,7 +48,7 @@ struct ttm_agp_backend { struct agp_bridge_data *bridge; }; -static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) +static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); struct page *dummy_read_page = ttm_bo_glob.dummy_read_page; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ff68f25ddbd48..ad09329b62d30 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -145,7 +145,7 @@ static inline uint32_t ttm_bo_type_flags(unsigned type) } static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct ttm_bo_device *bdev = bo->bdev; struct ttm_resource_manager *man; @@ -268,7 +268,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) EXPORT_SYMBOL(ttm_bo_bulk_move_lru_tail); static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem, bool evict, + struct ttm_resource *mem, bool evict, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; @@ -642,7 +642,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_reg evict_mem; + struct ttm_resource evict_mem; struct ttm_placement placement; int ret = 0; @@ -841,7 +841,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, static int ttm_bo_mem_get(struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); @@ -852,7 +852,7 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, return man->func->get_node(man, bo, place, mem); } -void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) +void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_resource *mem) { struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); @@ -870,7 +870,7 @@ EXPORT_SYMBOL(ttm_bo_mem_put); */ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, struct ttm_resource_manager *man, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, bool no_wait_gpu) { struct dma_fence *fence; @@ -905,7 +905,7 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, */ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; @@ -986,7 +986,7 @@ static bool ttm_bo_mt_compatible(struct ttm_resource_manager *man, */ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; @@ -1034,7 +1034,7 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, */ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_placement *placement, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; @@ -1112,7 +1112,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { int ret = 0; - struct ttm_mem_reg mem; + struct ttm_resource mem; dma_resv_assert_held(bo->base.resv); @@ -1138,7 +1138,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, static bool ttm_bo_places_compat(const struct ttm_place *places, unsigned num_placement, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, uint32_t *new_flags) { unsigned i; @@ -1161,7 +1161,7 @@ static bool ttm_bo_places_compat(const struct ttm_place *places, } bool ttm_bo_mem_compat(struct ttm_placement *placement, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, uint32_t *new_flags) { if (ttm_bo_places_compat(placement->placement, placement->num_placement, @@ -1730,7 +1730,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) if (bo->mem.mem_type != TTM_PL_SYSTEM || bo->ttm->caching_state != tt_cached) { struct ttm_operation_ctx ctx = { false, false }; - struct ttm_mem_reg evict_mem; + struct ttm_resource evict_mem; evict_mem = bo->mem; evict_mem.mm_node = NULL; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 8ef0de8e36c50..496158acd5b95 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -52,10 +52,10 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo) int ttm_bo_move_ttm(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_tt *ttm = bo->ttm; - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; int ret; if (old_mem->mem_type != TTM_PL_SYSTEM) { @@ -127,7 +127,7 @@ static int ttm_mem_io_evict(struct ttm_resource_manager *man) } int ttm_mem_io_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; @@ -149,7 +149,7 @@ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, } void ttm_mem_io_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { if (--mem->bus.io_reserved_count) return; @@ -163,7 +163,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev, int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) { struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); - struct ttm_mem_reg *mem = &bo->mem; + struct ttm_resource *mem = &bo->mem; int ret; if (mem->bus.io_reserved_vm) @@ -181,7 +181,7 @@ int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) { - struct ttm_mem_reg *mem = &bo->mem; + struct ttm_resource *mem = &bo->mem; if (!mem->bus.io_reserved_vm) return; @@ -191,8 +191,8 @@ void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) ttm_mem_io_free(bo->bdev, mem); } -static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem, +static int ttm_resource_ioremap(struct ttm_bo_device *bdev, + struct ttm_resource *mem, void **virtual) { struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); @@ -226,8 +226,8 @@ static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, return 0; } -static void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem, +static void ttm_resource_iounmap(struct ttm_bo_device *bdev, + struct ttm_resource *mem, void *virtual) { struct ttm_resource_manager *man; @@ -300,13 +300,13 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_bo_device *bdev = bo->bdev; struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); struct ttm_tt *ttm = bo->ttm; - struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg old_copy = *old_mem; + struct ttm_resource *old_mem = &bo->mem; + struct ttm_resource old_copy = *old_mem; void *old_iomap; void *new_iomap; int ret; @@ -319,10 +319,10 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ret) return ret; - ret = ttm_mem_reg_ioremap(bdev, old_mem, &old_iomap); + ret = ttm_resource_ioremap(bdev, old_mem, &old_iomap); if (ret) return ret; - ret = ttm_mem_reg_ioremap(bdev, new_mem, &new_iomap); + ret = ttm_resource_ioremap(bdev, new_mem, &new_iomap); if (ret) goto out; @@ -390,9 +390,9 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, } out1: - ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); + ttm_resource_iounmap(bdev, old_mem, new_iomap); out: - ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); + ttm_resource_iounmap(bdev, &old_copy, old_iomap); /* * On error, keep the mm node! @@ -502,7 +502,7 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo, unsigned long size, struct ttm_bo_kmap_obj *map) { - struct ttm_mem_reg *mem = &bo->mem; + struct ttm_resource *mem = &bo->mem; if (bo->mem.bus.addr) { map->bo_kmap_type = ttm_bo_map_premapped; @@ -526,7 +526,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, unsigned long num_pages, struct ttm_bo_kmap_obj *map) { - struct ttm_mem_reg *mem = &bo->mem; + struct ttm_resource *mem = &bo->mem; struct ttm_operation_ctx ctx = { .interruptible = false, .no_wait_gpu = false @@ -631,11 +631,11 @@ EXPORT_SYMBOL(ttm_bo_kunmap); int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_bo_device *bdev = bo->bdev; struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; int ret; struct ttm_buffer_object *ghost_obj; @@ -692,10 +692,10 @@ EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem) + struct ttm_resource *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_mem_reg *old_mem = &bo->mem; + struct ttm_resource *old_mem = &bo->mem; struct ttm_resource_manager *from = ttm_manager_type(bdev, old_mem->mem_type); struct ttm_resource_manager *to = ttm_manager_type(bdev, new_mem->mem_type); diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index df62177cd913e..274a05ca13d3b 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -57,7 +57,7 @@ static inline struct ttm_range_manager *to_range_manager(struct ttm_resource_man static int ttm_range_man_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; @@ -96,7 +96,7 @@ static int ttm_range_man_get_node(struct ttm_resource_manager *man, } static void ttm_range_man_put_node(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct ttm_range_manager *rman = to_range_manager(man); diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index e25d4097aa168..bdd6169cef132 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -322,7 +322,7 @@ void ttm_tt_unbind(struct ttm_tt *ttm) } } -int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem, +int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, struct ttm_operation_ctx *ctx) { int ret = 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 1e59c019affab..3229451d07062 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -1135,14 +1135,14 @@ void vmw_bo_swap_notify(struct ttm_buffer_object *bo) * vmw_bo_move_notify - TTM move_notify_callback * * @bo: The TTM buffer object about to move. - * @mem: The struct ttm_mem_reg indicating to what memory + * @mem: The struct ttm_resource indicating to what memory * region the move is taking place. * * Detaches cached maps and device bindings that require that the * buffer doesn't move. */ void vmw_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmw_buffer_object *vbo; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index aa763c6b11462..871ad738dadbd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -793,7 +793,7 @@ extern void vmw_resource_unreserve(struct vmw_resource *res, struct vmw_buffer_object *new_backup, unsigned long new_backup_offset); extern void vmw_query_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); extern int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob); extern void vmw_resource_evict_all(struct vmw_private *dev_priv); extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo); @@ -878,7 +878,7 @@ extern void vmw_bo_fence_single(struct ttm_buffer_object *bo, extern void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo); extern void vmw_bo_unmap(struct vmw_buffer_object *vbo); extern void vmw_bo_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo); extern struct vmw_buffer_object * vmw_user_bo_noref_lookup(struct ttm_object_file *tfile, u32 handle); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index c8fe6e9cf0921..3fea7a6c7cfaf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -53,7 +53,7 @@ static struct vmwgfx_gmrid_man *to_gmrid_manager(struct ttm_resource_manager *ma static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); int id; @@ -85,7 +85,7 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man, } static void vmw_gmrid_man_put_node(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmwgfx_gmrid_man *gman = to_gmrid_manager(man); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index c8441030637a3..c0f156078ddae 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -855,7 +855,7 @@ int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob) * states from the device. */ void vmw_query_move_notify(struct ttm_buffer_object *bo, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmw_buffer_object *dx_query_mob; struct ttm_bo_device *bdev = bo->bdev; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 6cac7b091205f..f594e2e6ab7ec 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -29,7 +29,7 @@ static struct vmw_thp_manager *to_thp_manager(struct ttm_resource_manager *man) static int vmw_thp_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node, unsigned long align_pages, const struct ttm_place *place, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, unsigned long lpfn, enum drm_mm_insert_mode mode) { @@ -47,7 +47,7 @@ static int vmw_thp_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node, static int vmw_thp_get_node(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmw_thp_manager *rman = to_thp_manager(man); struct drm_mm *mm = &rman->mm; @@ -107,7 +107,7 @@ static int vmw_thp_get_node(struct ttm_resource_manager *man, static void vmw_thp_put_node(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { struct vmw_thp_manager *rman = to_thp_manager(man); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 01c81e89ed7a6..69e7e7fe2a4c1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -539,7 +539,7 @@ const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo) } -static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) +static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -713,7 +713,7 @@ static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) return vmw_user_bo_verify_access(bo, tfile); } -static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); @@ -743,7 +743,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg * vmw_move_notify - TTM move_notify_callback * * @bo: The TTM buffer object about to move. - * @mem: The struct ttm_mem_reg indicating to what memory + * @mem: The struct ttm_resource indicating to what memory * region the move is taking place. * * Calls move_notify for all subsystems needing it. @@ -751,7 +751,7 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg */ static void vmw_move_notify(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *mem) + struct ttm_resource *mem) { vmw_bo_move_notify(bo, mem); vmw_query_move_notify(bo, mem); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 7b0655bc13dab..770ad2195875d 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -81,7 +81,7 @@ struct ttm_bus_placement { /** - * struct ttm_mem_reg + * struct ttm_resource * * @mm_node: Memory manager node. * @size: Requested size of memory region. @@ -94,7 +94,7 @@ struct ttm_bus_placement { * buffer object. */ -struct ttm_mem_reg { +struct ttm_resource { void *mm_node; unsigned long start; unsigned long size; @@ -187,7 +187,7 @@ struct ttm_buffer_object { * Members protected by the bo::resv::reserved lock. */ - struct ttm_mem_reg mem; + struct ttm_resource mem; struct file *persistent_swap_storage; struct ttm_tt *ttm; bool evicted; @@ -316,12 +316,12 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, bool interruptible, bool no_wait); * ttm_bo_mem_compat - Check if proposed placement is compatible with a bo * * @placement: Return immediately if buffer is busy. - * @mem: The struct ttm_mem_reg indicating the region where the bo resides + * @mem: The struct ttm_resource indicating the region where the bo resides * @new_flags: Describes compatible placement found * * Returns true if the placement is compatible */ -bool ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_mem_reg *mem, +bool ttm_bo_mem_compat(struct ttm_placement *placement, struct ttm_resource *mem, uint32_t *new_flags); /** diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index d17e25ba80d44..eb1c3312e1758 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -55,7 +55,7 @@ struct ttm_resource_manager_func { * @bo: Pointer to the buffer object we're allocating space for. * @placement: Placement details. * @flags: Additional placement flags. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. + * @mem: Pointer to a struct ttm_resource to be filled in. * * This function should allocate space in the memory type managed * by @man. Placement details if @@ -79,20 +79,20 @@ struct ttm_resource_manager_func { int (*get_node)(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * struct ttm_resource_manager member put_node * * @man: Pointer to a memory type manager. - * @mem: Pointer to a struct ttm_mem_reg to be filled in. + * @mem: Pointer to a struct ttm_resource to be filled in. * * This function frees memory type resources previously allocated * and that are identified by @mem::mm_node and @mem::start. May not * be called from within atomic context. */ void (*put_node)(struct ttm_resource_manager *man, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * struct ttm_resource_manager member debug @@ -251,7 +251,7 @@ struct ttm_bo_driver { */ int (*move)(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * struct ttm_bo_driver_member verify_access @@ -277,7 +277,7 @@ struct ttm_bo_driver { */ void (*move_notify)(struct ttm_buffer_object *bo, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /* notify the driver we are taking a fault on this BO * and have reserved it */ int (*fault_reserve_notify)(struct ttm_buffer_object *bo); @@ -294,9 +294,9 @@ struct ttm_bo_driver { * are balanced. */ int (*io_mem_reserve)(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); void (*io_mem_free)(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * Return the pfn for a given page_offset inside the BO. @@ -503,15 +503,15 @@ ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) */ /** - * ttm_mem_reg_is_pci + * ttm_resource_is_pci * * @bdev: Pointer to a struct ttm_bo_device. - * @mem: A valid struct ttm_mem_reg. + * @mem: A valid struct ttm_resource. * * Returns true if the memory described by @mem is PCI memory, * false otherwise. */ -bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); +bool ttm_resource_is_pci(struct ttm_bo_device *bdev, struct ttm_resource *mem); /** * ttm_bo_mem_space @@ -519,7 +519,7 @@ bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); * @bo: Pointer to a struct ttm_buffer_object. the data of which * we want to allocate space for. * @proposed_placement: Proposed new placement for the buffer object. - * @mem: A struct ttm_mem_reg. + * @mem: A struct ttm_resource. * @interruptible: Sleep interruptible when sliping. * @no_wait_gpu: Return immediately if the GPU is busy. * @@ -534,10 +534,10 @@ bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); */ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_placement *placement, - struct ttm_mem_reg *mem, + struct ttm_resource *mem, struct ttm_operation_ctx *ctx); -void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem); +void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_resource *mem); int ttm_bo_device_release(struct ttm_bo_device *bdev); @@ -733,16 +733,16 @@ int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, */ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); void ttm_mem_io_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); + struct ttm_resource *mem); /** * ttm_bo_move_ttm * * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait_gpu: Return immediately if the GPU is busy. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Optimized move function for a buffer object with both old and * new placement backed by a TTM. The function will, if successful, @@ -756,7 +756,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev, int ttm_bo_move_ttm(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_move_memcpy @@ -764,7 +764,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. * @no_wait_gpu: Return immediately if the GPU is busy. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Fallback move function for a mappable buffer object in mappable memory. * The function will, if successful, @@ -778,7 +778,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_free_old_node @@ -795,7 +795,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); * @bo: A pointer to a struct ttm_buffer_object. * @fence: A fence object that signals when moving is complete. * @evict: This is an evict move. Don't return until the buffer is idle. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Accelerated move function to be called when an accelerated move * has been scheduled. The function will create a new temporary buffer object @@ -806,7 +806,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); */ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_pipeline_move. @@ -814,14 +814,14 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * @bo: A pointer to a struct ttm_buffer_object. * @fence: A fence object that signals when moving is complete. * @evict: This is an evict move. Don't return until the buffer is idle. - * @new_mem: struct ttm_mem_reg indicating where to move. + * @new_mem: struct ttm_resource indicating where to move. * * Function for pipelining accelerated moves. Either free the memory * immediately or hang it on a temporary buffer object. */ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, - struct ttm_mem_reg *new_mem); + struct ttm_resource *new_mem); /** * ttm_bo_pipeline_gutting. diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index c0e928abf5920..2ac34219ecb53 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -30,7 +30,7 @@ #include <linux/types.h> struct ttm_tt; -struct ttm_mem_reg; +struct ttm_resource; struct ttm_buffer_object; struct ttm_operation_ctx; @@ -53,14 +53,14 @@ struct ttm_backend_func { * struct ttm_backend_func member bind * * @ttm: Pointer to a struct ttm_tt. - * @bo_mem: Pointer to a struct ttm_mem_reg describing the + * @bo_mem: Pointer to a struct ttm_resource describing the * memory type and location for binding. * * Bind the backend pages into the aperture in the location * indicated by @bo_mem. This function should be able to handle * differences between aperture and system page sizes. */ - int (*bind) (struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem); + int (*bind) (struct ttm_tt *ttm, struct ttm_resource *bo_mem); /** * struct ttm_backend_func member unbind @@ -179,11 +179,11 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); * ttm_ttm_bind: * * @ttm: The struct ttm_tt containing backing pages. - * @bo_mem: The struct ttm_mem_reg identifying the binding location. + * @bo_mem: The struct ttm_resource identifying the binding location. * * Bind the pages of @ttm to an aperture location identified by @bo_mem */ -int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem, +int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, struct ttm_operation_ctx *ctx); /** -- GitLab From c35376137e940c3389df2726a92649c01a9844b4 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Date: Sun, 2 Aug 2020 19:15:36 +0800 Subject: [PATCH 0306/1494] drm/amd/display: Fix wrong return value in dm_update_plane_state() On an error exit path, a negative error code should be returned instead of a positive return value. Fixes: 9e869063b0021 ("drm/amd/display: Move iteration out of dm_update_planes") Cc: Leo Li <sunpeng.li@amd.com> Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 27dfd285a9445..7f6a91b4fe4e1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8343,8 +8343,7 @@ static int dm_update_plane_state(struct dc *dc, dm_old_plane_state->dc_state, dm_state->context)) { - ret = EINVAL; - return ret; + return -EINVAL; } -- GitLab From b80f050ff23d48c9b191e3da7e31ee520d1b2126 Mon Sep 17 00:00:00 2001 From: Philip Yang <Philip.Yang@amd.com> Date: Mon, 27 Jul 2020 09:06:18 -0400 Subject: [PATCH 0307/1494] drm/amdkfd: option to disable system mem limit If multiple process share system memory through /dev/shm, KFD allocate memory should not fail if it reaches the system memory limit because one copy of physical system memory are shared by multiple process. Add module parameter no_system_mem_limit to provide user option to disable system memory limit check at runtime using sysfs or during driver module init using kernel boot argument. By default the system memory limit is on. Print out debug message to warn user if KFD allocate memory failed because system memory reaches limit. Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +++++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index a5ea70697fba9..3e82a11577d90 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -188,9 +188,11 @@ extern int amdgpu_force_asic_type; #ifdef CONFIG_HSA_AMD extern int sched_policy; extern bool debug_evictions; +extern bool no_system_mem_limit; #else static const int sched_policy = KFD_SCHED_POLICY_HWS; static const bool debug_evictions; /* = false */ +static const bool no_system_mem_limit; #endif extern int amdgpu_tmz; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index a21cf84b882c0..fcf72f3377852 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -148,8 +148,12 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, spin_lock(&kfd_mem_limit.mem_limit_lock); + if (kfd_mem_limit.system_mem_used + system_mem_needed > + kfd_mem_limit.max_system_mem_limit) + pr_debug("Set no_system_mem_limit=1 if using shared memory\n"); + if ((kfd_mem_limit.system_mem_used + system_mem_needed > - kfd_mem_limit.max_system_mem_limit) || + kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) || (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > kfd_mem_limit.max_ttm_mem_limit) || (adev->kfd.vram_used + vram_needed > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6d66705a11413..5156c67ec67b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -717,6 +717,15 @@ MODULE_PARM_DESC(queue_preemption_timeout_ms, "queue preemption timeout in ms (1 bool debug_evictions; module_param(debug_evictions, bool, 0644); MODULE_PARM_DESC(debug_evictions, "enable eviction debug messages (false = default)"); + +/** + * DOC: no_system_mem_limit(bool) + * Disable system memory limit, to support multiple process shared memory + */ +bool no_system_mem_limit; +module_param(no_system_mem_limit, bool, 0644); +MODULE_PARM_DESC(no_system_mem_limit, "disable system memory limit (false = default)"); + #endif /** -- GitLab From 9993d8b174925a45810c45d2f5fd90d040400293 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 4 Aug 2020 16:58:30 +0800 Subject: [PATCH 0308/1494] drm/amd/powerplay: grant Arcturus softmin/max setting on latest PM firmware For Arcturus, the softmin/max settings from driver are permitted on the latest(54.26 later) SMU firmware. Thus enabling them in driver. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 0147a5b9b06d4..d292898120be8 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -897,9 +897,10 @@ static int arcturus_force_clk_levels(struct smu_context *smu, return ret; } - if (smu_version >= 0x361200) { + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 and onwards SMU firmwares\n"); + "54.18 - 54.26(included) SMU firmwares\n"); return -EOPNOTSUPP; } @@ -1392,9 +1393,10 @@ static int arcturus_set_performance_level(struct smu_context *smu, case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - if (smu_version >= 0x361200) { + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 and onwards SMU firmwares\n"); + "54.18 - 54.26(included) SMU firmwares\n"); return -EOPNOTSUPP; } break; -- GitLab From c16ce56240aa654c1676f36119561162405322b1 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 5 Aug 2020 13:15:27 +0100 Subject: [PATCH 0309/1494] drm/amdgpu: fix spelling mistake "paramter" -> "parameter" There is a spelling mistake in a dev_warn message. Fix it. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b72aeeb0a226e..16e23f0533614 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1201,7 +1201,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { amdgpu_num_kcq = 8; - dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid paramter provided by user\n"); + dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n"); } return 0; -- GitLab From 39c5a1cef84b4bc70123400d75f0fe637e1df6a6 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 23 Jul 2020 16:07:01 +0800 Subject: [PATCH 0310/1494] drm/amd/powerplay: define an universal data structure for gpu metrics (V4) Thus we can provide an interface for UMD to retrieve gpu metrics data. V2: better naming and comments V3: two structures created for dGPU and APU separately V4: add driver attached timestamp Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/include/kgd_pp_interface.h | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a7f92d0b3a90b..5f38ee62c1039 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -324,4 +324,112 @@ struct amd_pm_funcs { int (*set_xgmi_pstate)(void *handle, uint32_t pstate); }; +struct metrics_table_header { + uint16_t structure_size; + uint8_t format_revision; + uint8_t content_revision; +}; + +struct gpu_metrics_v1_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint32_t energy_accumulator; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint8_t pcie_link_width; + uint8_t pcie_link_speed; // in 0.1 GT/s +}; + +struct gpu_metrics_v2_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding; +}; + #endif -- GitLab From 25c933b1c4fcfaa65ed735e9782fdb2622f7b7e8 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 23 Jul 2020 18:03:35 +0800 Subject: [PATCH 0311/1494] drm/amd/powerplay: add new sysfs interface for retrieving gpu metrics(V2) A new interface for UMD to retrieve gpu metrics data. V2: rich the documentation Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- Documentation/gpu/amdgpu.rst | 6 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 57 +++++++++++++++++++ .../gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 20 +++++++ .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 + 6 files changed, 90 insertions(+) diff --git a/Documentation/gpu/amdgpu.rst b/Documentation/gpu/amdgpu.rst index 17112352f605e..0f7679a7cf542 100644 --- a/Documentation/gpu/amdgpu.rst +++ b/Documentation/gpu/amdgpu.rst @@ -206,6 +206,12 @@ pp_power_profile_mode .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c :doc: mem_busy_percent +gpu_metrics +~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c + :doc: gpu_metrics + GPU Product Information ======================= diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index aa27fe65cdfa9..b190c0af7db12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -369,6 +369,9 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ (adev)->powerplay.pp_handle, (ppfeatures))) +#define amdgpu_dpm_get_gpu_metrics(adev, table) \ + ((adev)->powerplay.pp_funcs->get_gpu_metrics((adev)->powerplay.pp_handle, table)) + struct amdgpu_dpm { struct amdgpu_ps *ps; /* number of valid power states */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 576e3ac983657..1705e328c6fcf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -2120,6 +2120,59 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, return count; } +/** + * DOC: gpu_metrics + * + * The amdgpu driver provides a sysfs API for retrieving current gpu + * metrics data. The file gpu_metrics is used for this. Reading the + * file will dump all the current gpu metrics data. + * + * These data include temperature, frequency, engines utilization, + * power consume, throttler status, fan speed and cpu core statistics( + * available for APU only). That's it will give a snapshot of all sensors + * at the same time. + */ +static ssize_t amdgpu_get_gpu_metrics(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + void *gpu_metrics; + ssize_t size = 0; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) + size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); + else if (adev->powerplay.pp_funcs->get_gpu_metrics) + size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); + up_read(&adev->reset_sem); + + if (size <= 0) + goto out; + + if (size >= PAGE_SIZE) + size = PAGE_SIZE - 1; + + memcpy(buf, gpu_metrics, size); + +out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(power_dpm_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(power_dpm_force_performance_level, ATTR_FLAG_BASIC), @@ -2143,6 +2196,7 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(gpu_metrics, ATTR_FLAG_BASIC), }; static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, @@ -2192,6 +2246,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(pp_features)) { if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(gpu_metrics)) { + if (asic_type < CHIP_VEGA12) + *states = ATTR_STATE_UNSUPPORTED; } if (asic_type == CHIP_ARCTURUS) { diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 5f38ee62c1039..0aec28fda0587 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -322,6 +322,7 @@ struct amd_pm_funcs { int (*asic_reset_mode_2)(void *handle); int (*set_df_cstate)(void *handle, enum pp_df_cstate state); int (*set_xgmi_pstate)(void *handle, uint32_t pstate); + ssize_t (*get_gpu_metrics)(void *handle, void **table); }; struct metrics_table_header { diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index d03b4852ed5fa..f3f50b5add996 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -2516,3 +2516,23 @@ int smu_get_dpm_clock_table(struct smu_context *smu, return ret; } + +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + ssize_t size; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + size = smu->ppt_funcs->get_gpu_metrics(smu, table); + + mutex_unlock(&smu->mutex); + + return size; +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index b57b104063907..a08155b832897 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -589,6 +589,7 @@ struct pptable_funcs { void (*log_thermal_throttling_event)(struct smu_context *smu); size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); + ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); }; typedef enum { @@ -791,5 +792,7 @@ int smu_get_dpm_clock_table(struct smu_context *smu, int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); + #endif #endif -- GitLab From e4c9200df51033e2394c165fdafb183dbd6100ab Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 24 Jul 2020 18:39:33 +0800 Subject: [PATCH 0312/1494] drm/amd/powerplay: implement SMU V11 common APIs for retrieving link speed/width This will be shared around all SMU V11 asics. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 8 +++ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 9 +--- drivers/gpu/drm/amd/powerplay/navi10_ppt.h | 3 -- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 8 +-- .../drm/amd/powerplay/sienna_cichlid_ppt.h | 3 -- drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 53 +++++++++++++++++++ 6 files changed, 65 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 6a42331aba8aa..aeb12654257e8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -264,5 +264,13 @@ int smu_v11_0_get_dpm_level_range(struct smu_context *smu, uint32_t *min_value, uint32_t *max_value); +int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index c33bdc6747f29..45d2d6c2481c9 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -917,7 +917,6 @@ static int navi10_print_clk_levels(struct smu_context *smu, uint32_t gen_speed, lane_width; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - struct amdgpu_device *adev = smu->adev; PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; OverDriveTable_t *od_table = (OverDriveTable_t *)table_context->overdrive_table; @@ -971,12 +970,8 @@ static int navi10_print_clk_levels(struct smu_context *smu, } break; case SMU_PCIE: - gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu); + lane_width = smu_v11_0_get_current_pcie_link_width_level(smu); for (i = 0; i < NUM_LINK_LEVELS; i++) size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h index 2abb4ba01db1a..84dc5a1b68303 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h @@ -49,9 +49,6 @@ #define NAVI10_VOLTAGE_SCALE (4) -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - extern void navi10_set_ppt_funcs(struct smu_context *smu); #endif diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f373e2d0d31ca..05ad29fcfe683 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -960,12 +960,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, } break; case SMU_PCIE: - gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + gen_speed = smu_v11_0_get_current_pcie_link_speed(smu); + lane_width = smu_v11_0_get_current_pcie_link_width(smu); for (i = 0; i < NUM_LINK_LEVELS; i++) size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h index 8078886e4cbc5..57e120c440eae 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h @@ -31,7 +31,4 @@ typedef enum { extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index 7d7de854a826e..ff90e20eed5c9 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -67,6 +67,19 @@ MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin"); #define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 + +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4 +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE + +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + int smu_v11_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -1918,3 +1931,43 @@ int smu_v11_0_get_dpm_level_range(struct smu_context *smu, return ret; } + +int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu) +{ + uint32_t width_level; + + width_level = smu_v11_0_get_current_pcie_link_width_level(smu); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) +{ + uint32_t speed_level; + + speed_level = smu_v11_0_get_current_pcie_link_speed_level(smu); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} -- GitLab From f1c378593153c93ed1db6ec8c025fa388474dd12 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 24 Jul 2020 10:42:39 +0800 Subject: [PATCH 0313/1494] drm/amd/powerplay: add Arcturus support for gpu metrics export Add Arcturus gpu metrics export interface. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 92 +++++++++++++++++++ .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 + drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 14 +++ 4 files changed, 111 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index d292898120be8..5aa0d5b03f7e5 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -79,6 +79,8 @@ /* possible frequency drift (1Mhz) */ #define EPSILON 1 +#define smnPCIE_ESM_CTRL 0x111003D0 + static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -234,6 +236,13 @@ static int arcturus_tables_init(struct smu_context *smu) return -ENOMEM; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) { + kfree(smu_table->metrics_table); + return -ENOMEM; + } + return 0; } @@ -2242,6 +2251,88 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu) kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status); } +static int arcturus_get_current_pcie_link_speed(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t esm_ctrl; + + /* TODO: confirm this on real target */ + esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL); + if ((esm_ctrl >> 15) & 0x1FFFF) + return (((esm_ctrl >> 8) & 0x3F) + 128); + + return smu_v11_0_get_current_pcie_link_speed(smu); +} + +static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + arcturus_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pptable_funcs arcturus_ppt_funcs = { /* init dpm */ .get_allowed_feature_mask = arcturus_get_allowed_feature_mask, @@ -2319,6 +2410,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .log_thermal_throttling_event = arcturus_log_thermal_throttling_event, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = arcturus_get_gpu_metrics, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index a08155b832897..ec2d2aa7f4ec5 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -274,6 +274,9 @@ struct smu_table_context void *overdrive_table; void *boot_overdrive_table; + + uint32_t gpu_metrics_table_size; + void *gpu_metrics_table; }; struct smu_dpm_context { diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index aeb12654257e8..f2a522176ca0a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -272,5 +272,7 @@ int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu); int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); +void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index ff90e20eed5c9..ff574ebc179ee 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -417,10 +417,12 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu) struct smu_table_context *smu_table = &smu->smu_table; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + kfree(smu_table->gpu_metrics_table); kfree(smu_table->boot_overdrive_table); kfree(smu_table->overdrive_table); kfree(smu_table->max_sustainable_clocks); kfree(smu_table->driver_pptable); + smu_table->gpu_metrics_table = NULL; smu_table->boot_overdrive_table = NULL; smu_table->overdrive_table = NULL; smu_table->max_sustainable_clocks = NULL; @@ -1971,3 +1973,15 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) return link_speed[speed_level]; } + +void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} -- GitLab From 14a12beab8b9d943edd3bfaac8fd31f4aa578e43 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 24 Jul 2020 17:47:03 +0800 Subject: [PATCH 0314/1494] drm/amd/powerplay: update the data structure for NV12 SmuMetrics Although it does not bring any problem for now, the coming gpu metrics interface needs to handle them differently based on the asic type. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../powerplay/inc/smu11_driver_if_navi10.h | 39 +++++++++++++++++++ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 18 +++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h index 4b2da98afcd27..246d3951a78ab 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h @@ -884,6 +884,45 @@ typedef struct { uint32_t MmHubPadding[8]; // SMU internal use } SmuMetrics_t; +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureMem ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureLiquid0 ; + uint16_t TemperatureLiquid1 ; + uint16_t TemperaturePlx ; + uint16_t Padding16 ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t Padding8_2; + uint16_t CurrFanSpeed; + + uint32_t EnergyAccumulator; + uint16_t AverageVclkFrequency ; + uint16_t AverageDclkFrequency ; + uint16_t VcnActivityPercentage ; + uint16_t padding16_2; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetrics_NV12_t; + typedef struct { uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 45d2d6c2481c9..fc29d290f596e 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -456,13 +456,18 @@ static int navi10_tables_init(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *tables = smu_table->tables; + struct amdgpu_device *adev = smu->adev; SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + if (adev->asic_type == CHIP_NAVI12) + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV12_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + else + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), @@ -473,7 +478,9 @@ static int navi10_tables_init(struct smu_context *smu) sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + smu_table->metrics_table = kzalloc(adev->asic_type == CHIP_NAVI12 ? + sizeof(SmuMetrics_NV12_t) : + sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) return -ENOMEM; smu_table->metrics_time = 0; @@ -490,6 +497,11 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, uint32_t *value) { struct smu_table_context *smu_table= &smu->smu_table; + /* + * This works for NV12 also. As although NV12 uses a different + * SmuMetrics structure from other NV1X ASICs, they share the + * same offsets for the heading parts(those members used here). + */ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; -- GitLab From 6d4ff50a27749fdce0a8b8c674d9b9db13d9824d Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 24 Jul 2020 17:24:34 +0800 Subject: [PATCH 0315/1494] drm/amd/powerplay: add Navi1x support for gpu metrics export Add Navi1x gpu metrics export interface. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 93 +++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index fc29d290f596e..0c5667db136b7 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -482,14 +482,26 @@ static int navi10_tables_init(struct smu_context *smu) sizeof(SmuMetrics_NV12_t) : sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; } static int navi10_get_smu_metrics_data(struct smu_context *smu, @@ -2487,6 +2499,82 @@ static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter i2c_del_adapter(control); } +static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + struct amdgpu_device *adev = smu->adev; + SmuMetrics_NV12_t nv12_metrics = { 0 }; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + if (adev->asic_type == CHIP_NAVI12) + memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + if (adev->asic_type == CHIP_NAVI12) { + gpu_metrics->energy_accumulator = nv12_metrics.EnergyAccumulator; + gpu_metrics->average_vclk0_frequency = nv12_metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = nv12_metrics.AverageDclkFrequency; + gpu_metrics->average_mm_activity = nv12_metrics.VcnActivityPercentage; + } + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} static const struct pptable_funcs navi10_ppt_funcs = { .get_allowed_feature_mask = navi10_get_allowed_feature_mask, @@ -2568,6 +2656,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_power_source = smu_v11_0_set_power_source, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = navi10_get_gpu_metrics, }; void navi10_set_ppt_funcs(struct smu_context *smu) -- GitLab From 8ca78a0a0e7719d1045c50e0876299c94b6454a2 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 27 Jul 2020 10:00:47 +0800 Subject: [PATCH 0316/1494] drm/amd/powerplay: add Sienna Cichlid support for gpu metrics export Add Sienna Cichlid gpu metrics export interface. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 91 ++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 05ad29fcfe683..f86c3cdd3b1c4 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -385,14 +385,26 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; } static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, @@ -2649,6 +2661,80 @@ static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_ i2c_del_adapter(control); } +static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + if (metrics.AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs; + else + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclk0Frequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclk0Frequency; + gpu_metrics->average_vclk1_frequency = metrics.AverageVclk1Frequency; + gpu_metrics->average_dclk1_frequency = metrics.AverageDclk1Frequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK_0]; + gpu_metrics->current_vclk1 = metrics.CurrClock[PPCLK_VCLK_1]; + gpu_metrics->current_dclk1 = metrics.CurrClock[PPCLK_DCLK_1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, @@ -2726,6 +2812,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- GitLab From 95868b85764aff2dcbf78d3054076df75446ad15 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 27 Jul 2020 16:24:46 +0800 Subject: [PATCH 0317/1494] drm/amd/powerplay: add Renoir support for gpu metrics export(V2) Add Renoir gpu metrics export interface. V2: use memcpy to make code more compact Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h | 2 + drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 80 ++++++++++++++++++- drivers/gpu/drm/amd/powerplay/smu_v12_0.c | 12 +++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h index 02de3b6199e53..fa2e8cb079670 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h @@ -60,5 +60,7 @@ int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ int smu_v12_0_set_driver_table_location(struct smu_context *smu); +void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 575ae4be98a29..61e8700a7bdb8 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -166,18 +166,32 @@ static int renoir_init_smc_tables(struct smu_context *smu) smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); if (!smu_table->clocks_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err1_out; smu_table->metrics_time = 0; smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err3_out; return 0; + +err3_out: + kfree(smu_table->watermarks_table); +err2_out: + kfree(smu_table->metrics_table); +err1_out: + kfree(smu_table->clocks_table); +err0_out: + return -ENOMEM; } /** @@ -995,6 +1009,65 @@ static bool renoir_is_dpm_running(struct smu_context *smu) } +static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v2_0 *gpu_metrics = + (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = renoir_get_metrics_table(smu, &metrics); + if (ret) + return ret; + + smu_v12_0_init_gpu_metrics_v2_0(gpu_metrics); + + gpu_metrics->temperature_gfx = metrics.GfxTemperature; + gpu_metrics->temperature_soc = metrics.SocTemperature; + memcpy(&gpu_metrics->temperature_core[0], + &metrics.CoreTemperature[0], + sizeof(uint16_t) * 8); + gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; + gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_mm_activity = metrics.AverageUvdActivity; + + gpu_metrics->average_socket_power = metrics.CurrentSocketPower; + gpu_metrics->average_cpu_power = metrics.Power[0]; + gpu_metrics->average_soc_power = metrics.Power[1]; + memcpy(&gpu_metrics->average_core_power[0], + &metrics.CorePower[0], + sizeof(uint16_t) * 8); + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency; + gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency; + + gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK]; + gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK]; + gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK]; + gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK]; + gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK]; + gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK]; + memcpy(&gpu_metrics->current_coreclk[0], + &metrics.CoreFrequency[0], + sizeof(uint16_t) * 8); + gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; + gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->fan_pwm = metrics.FanPwm; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v2_0); +} + static const struct pptable_funcs renoir_ppt_funcs = { .set_power_state = NULL, .print_clk_levels = renoir_print_clk_levels, @@ -1029,6 +1102,7 @@ static const struct pptable_funcs renoir_ppt_funcs = { .is_dpm_running = renoir_is_dpm_running, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = renoir_get_gpu_metrics, }; void renoir_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c index 31456437bb18e..660f403d5770c 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c @@ -274,3 +274,15 @@ int smu_v12_0_set_driver_table_location(struct smu_context *smu) return ret; } + +void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v2_0); + gpu_metrics->common_header.format_revision = 2; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} -- GitLab From 0b01b8306789b0c07c5bf2d6f9134f8b30990932 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 11:40:07 +0800 Subject: [PATCH 0318/1494] drm/amd/powerplay: enable gpu_metrics export on legacy powerplay routines Enable gpu_metrics support on legacy powerplay routines. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 2 files changed, 20 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 7e6dcdf7df73a..a6321f2063c1d 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -1598,6 +1598,24 @@ static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) return 0; } +static ssize_t pp_get_gpu_metrics(void *handle, void **table) +{ + struct pp_hwmgr *hwmgr = handle; + ssize_t size; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&hwmgr->smu_lock); + size = hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); + mutex_unlock(&hwmgr->smu_lock); + + return size; +} + static const struct amd_pm_funcs pp_dpm_funcs = { .load_firmware = pp_dpm_load_fw, .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, @@ -1658,4 +1676,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .smu_i2c_bus_access = pp_smu_i2c_bus_access, .set_df_cstate = pp_set_df_cstate, .set_xgmi_pstate = pp_set_xgmi_pstate, + .get_gpu_metrics = pp_get_gpu_metrics, }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 15ed6cbdf3660..1b3529efc91e6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -359,6 +359,7 @@ struct pp_hwmgr_func { int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate); int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr, bool disable); + ssize_t (*get_gpu_metrics)(struct pp_hwmgr *hwmgr, void **table); }; struct pp_table_func { -- GitLab From e467c3a9f4ed143fd2ea3f9aef7672d3674de9f4 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 12:23:42 +0800 Subject: [PATCH 0319/1494] drm/amd/powerplay: add Vega20 support for gpu metrics export Add Vega20 gpu metrics export interface. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 123 +++++++++++++++++- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.h | 1 + 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index bacbe2fa1f9ac..037bebda2eaec 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -55,6 +55,11 @@ #define smnPCIE_LC_SPEED_CNTL 0x11140290 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) { struct vega20_hwmgr *data = @@ -3265,6 +3270,46 @@ static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return 0; } +static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega20_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { @@ -3277,7 +3322,6 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable; - struct amdgpu_device *adev = hwmgr->adev; struct pp_clock_levels_with_latency clocks; struct vega20_single_dpm_table *fclk_dpm_table = &(data->dpm_table.fclk_table); @@ -3371,12 +3415,10 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, break; case PP_PCIE: - current_gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - current_lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + current_gen_speed = + vega20_get_current_pcie_link_speed_level(hwmgr); + current_lane_width = + vega20_get_current_pcie_link_width_level(hwmgr); for (i = 0; i < NUM_LINK_LEVELS; i++) { if (i == 1 && data->pcie_parameters_override) { gen_speed = data->pcie_gen_level1; @@ -4218,6 +4260,72 @@ static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, return ret; } +static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega20_get_metrics_table(hwmgr, &metrics); + if (ret) + return ret; + + vega20_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega20_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega20_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pp_hwmgr_func vega20_hwmgr_funcs = { /* init/fini related */ .backend_init = vega20_hwmgr_backend_init, @@ -4288,6 +4396,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { .smu_i2c_bus_access = vega20_smu_i2c_bus_access, .set_df_cstate = vega20_set_df_cstate, .set_xgmi_pstate = vega20_set_xgmi_pstate, + .get_gpu_metrics = vega20_get_gpu_metrics, }; int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h index 2c3125f82b24a..075c0094da9c0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h @@ -527,6 +527,7 @@ struct vega20_hwmgr { unsigned long metrics_time; SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; bool pcie_parameters_override; uint32_t pcie_gen_level1; -- GitLab From 0fbc6533de67f49815e5bd7232cbd37fb68c6afa Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 12:39:58 +0800 Subject: [PATCH 0320/1494] drm/amd/powerplay: add Vega12 support for gpu metrics export Add Vega12 gpu metrics export interface. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 111 ++++++++++++++++++ .../drm/amd/powerplay/hwmgr/vega12_hwmgr.h | 1 + 2 files changed, 112 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index a678a67f1c0d0..40bb0c2e4e8c8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -47,6 +47,13 @@ #include "pp_thermal.h" #include "vega12_baco.h" +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 + +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); @@ -2095,6 +2102,46 @@ static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return 0; } +static int vega12_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega12_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega12_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega12_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega12_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega12_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { @@ -2682,6 +2729,69 @@ static int vega12_set_mp1_state(struct pp_hwmgr *hwmgr, return 0; } +static void vega12_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega12_get_metrics_table(hwmgr, &metrics); + if (ret) + return ret; + + vega12_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega12_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega12_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega12_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pp_hwmgr_func vega12_hwmgr_funcs = { .backend_init = vega12_hwmgr_backend_init, .backend_fini = vega12_hwmgr_backend_fini, @@ -2739,6 +2849,7 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = { .get_ppfeature_status = vega12_get_ppfeature_status, .set_ppfeature_status = vega12_set_ppfeature_status, .set_mp1_state = vega12_set_mp1_state, + .get_gpu_metrics = vega12_get_gpu_metrics, }; int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h index 73875399666a8..aa63ae41942d5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h @@ -399,6 +399,7 @@ struct vega12_hwmgr { unsigned long metrics_time; SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; }; #define VEGA12_DPM2_NEAR_TDP_DEC 10 -- GitLab From 345fcb02d9ec4cf5eae19d063dfb27f152bde291 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 14:31:21 +0800 Subject: [PATCH 0321/1494] drm/amd/powerplay: add control method to bypass metrics cache on Arcturus As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 74 +++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 5aa0d5b03f7e5..e3a2d7f0aba15 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -541,18 +541,16 @@ static int arcturus_freqs_in_same_level(int32_t frequency1, return (abs(frequency1 - frequency2) <= EPSILON); } -static int arcturus_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int arcturus_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -560,12 +558,50 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int arcturus_get_metrics_table(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = arcturus_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int arcturus_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = arcturus_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2273,23 +2309,11 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); + ret = arcturus_get_metrics_table(smu, + &metrics, + true); + if (ret) return ret; - } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); -- GitLab From 62d351632db8908e8bb5b359182b6ead54147e71 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 14:55:32 +0800 Subject: [PATCH 0322/1494] drm/amd/powerplay: add control method to bypass metrics cache on Navi10 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 60 ++++++++++++++-------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 0c5667db136b7..8c45c472f7f2c 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -504,22 +504,16 @@ static int navi10_tables_init(struct smu_context *smu) return -ENOMEM; } -static int navi10_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int navi10_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - /* - * This works for NV12 also. As although NV12 uses a different - * SmuMetrics structure from other NV1X ASICs, they share the - * same offsets for the heading parts(those members used here). - */ - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -527,12 +521,40 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int navi10_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + /* + * This works for NV12 also. As although NV12 uses a different + * SmuMetrics structure from other NV1X ASICs, they share the + * same offsets for the heading parts(those members used here). + */ + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = navi10_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2512,19 +2534,13 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); + ret = navi10_get_metrics_table_locked(smu, + &metrics, + true); if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); mutex_unlock(&smu->metrics_lock); return ret; } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); if (adev->asic_type == CHIP_NAVI12) memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); -- GitLab From 60ae4d67ee6d804215067f49e183214de405302b Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 15:09:57 +0800 Subject: [PATCH 0323/1494] drm/amd/powerplay: add control method to bypass metrics cache on Sienna Cichlid As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 73 +++++++++++++------ 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f86c3cdd3b1c4..2566ae5df64b8 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -407,17 +407,16 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) return -ENOMEM; } -static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int sienna_cichlid_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -425,12 +424,50 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int sienna_cichlid_get_metrics_table(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = sienna_cichlid_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = sienna_cichlid_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2670,23 +2707,11 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); + ret = sienna_cichlid_get_metrics_table(smu, + &metrics, + true); + if (ret) return ret; - } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); -- GitLab From 2ba38817219bfbae3cf870cb0092afb12f616fd3 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 15:02:11 +0800 Subject: [PATCH 0324/1494] drm/amd/powerplay: add control method to bypass metrics cache on Renoir As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 61e8700a7bdb8..4c1a506c3c177 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -129,13 +129,17 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = }; static int renoir_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table) + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; int ret = 0; mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { + + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)smu_table->metrics_table, false); if (ret) { @@ -146,7 +150,9 @@ static int renoir_get_metrics_table(struct smu_context *smu, smu_table->metrics_time = jiffies; } - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + mutex_unlock(&smu->metrics_lock); return ret; @@ -375,7 +381,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, memset(&metrics, 0, sizeof(metrics)); - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -529,7 +535,7 @@ static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, int ret = 0, clk_id = 0; SmuMetrics_t metrics; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -612,7 +618,7 @@ static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -632,7 +638,7 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -1018,7 +1024,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, true); if (ret) return ret; -- GitLab From 740dce9517cb4f67f762131b4f62584e65b97593 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 15:24:08 +0800 Subject: [PATCH 0325/1494] drm/amd/powerplay: add control method to bypass metrics cache on Vega20 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 037bebda2eaec..86d3a10379bef 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -2090,22 +2090,29 @@ static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) return (mem_clk * 100); } -static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table) +static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); int ret = 0; - if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) { - ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table, - TABLE_SMU_METRICS, true); + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + HZ / 2)) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); if (ret) { pr_info("Failed to export SMU metrics table!\n"); return ret; } - memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t)); data->metrics_time = jiffies; - } else + } + + if (metrics_table) memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); return ret; @@ -2117,7 +2124,7 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, int ret = 0; SmuMetrics_t metrics_table; - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2155,7 +2162,7 @@ static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, int ret = 0; SmuMetrics_t metrics_table; - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2185,7 +2192,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2210,7 +2217,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2219,7 +2226,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -4283,7 +4290,7 @@ static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, uint32_t fan_speed_rpm; int ret; - ret = vega20_get_metrics_table(hwmgr, &metrics); + ret = vega20_get_metrics_table(hwmgr, &metrics, true); if (ret) return ret; -- GitLab From bf1102877751175fe6c1d68734d3c57d4af65df9 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 30 Jul 2020 15:28:40 +0800 Subject: [PATCH 0326/1494] drm/amd/powerplay: add control method to bypass metrics cache on Vega12 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 40bb0c2e4e8c8..c70c301758015 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -1262,22 +1262,29 @@ static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) return (mem_clk * 100); } -static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table) +static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); int ret = 0; - if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) { - ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table, - TABLE_SMU_METRICS, true); + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + HZ / 2)) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); if (ret) { pr_info("Failed to export SMU metrics table!\n"); return ret; } - memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t)); data->metrics_time = jiffies; - } else + } + + if (metrics_table) memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); return ret; @@ -1288,7 +1295,7 @@ static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr, uint32_t *query) SmuMetrics_t metrics_table; int ret = 0; - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1339,7 +1346,7 @@ static int vega12_get_current_activity_percent( SmuMetrics_t metrics_table; int ret = 0; - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1387,7 +1394,7 @@ static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1396,7 +1403,7 @@ static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2752,7 +2759,7 @@ static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, uint32_t fan_speed_rpm; int ret; - ret = vega12_get_metrics_table(hwmgr, &metrics); + ret = vega12_get_metrics_table(hwmgr, &metrics, true); if (ret) return ret; -- GitLab From 16c642ec3fe9a144fbe1e97dc56f13a6308f1381 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Date: Thu, 30 Jul 2020 15:54:59 +0200 Subject: [PATCH 0327/1494] drm/amdgpu: new ids flag for tmz (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows UMD to know if TMZ is supported and enabled. This commit also bumps KMS_DRIVER_MINOR because if we don't UMD can't tell if "ids_flags & AMDGPU_IDS_FLAGS_TMZ == 0" means "tmz is not enabled" or "tmz may be enabled but the kernel doesn't report it". v2: use amdgpu_is_tmz() and reworded commit message. Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 ++ include/uapi/drm/amdgpu_drm.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 5156c67ec67b7..92d0368217a2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -88,9 +88,10 @@ * - 3.37.0 - L2 is invalidated before SDMA IBs, needed for correctness * - 3.38.0 - Add AMDGPU_IB_FLAG_EMIT_MEM_SYNC * - 3.39.0 - DMABUF implicit sync does a full pipeline sync + * - 3.40.0 - Add AMDGPU_IDS_FLAGS_TMZ */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 39 +#define KMS_DRIVER_MINOR 40 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index e99ad031efd41..58580a48b6486 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -737,6 +737,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION; if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; + if (amdgpu_is_tmz(adev)) + dev_info.ids_flags |= AMDGPU_IDS_FLAGS_TMZ; vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE; vm_size -= AMDGPU_VA_RESERVED_SIZE; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 3218576e109d9..c5ff2b275fcd7 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -673,6 +673,7 @@ struct drm_amdgpu_cs_chunk_data { */ #define AMDGPU_IDS_FLAGS_FUSION 0x1 #define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 +#define AMDGPU_IDS_FLAGS_TMZ 0x4 /* indicate if acceleration can be working */ #define AMDGPU_INFO_ACCEL_WORKING 0x00 -- GitLab From efa85f3a2b535bbc51e43a191b40f258538425b0 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Thu, 6 Aug 2020 14:41:06 +0800 Subject: [PATCH 0328/1494] drm/amd/powerplay: update driver if file for sienna_cichlid Update drive if file for sienna_cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h | 6 +++--- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h index aa2708fccb6de..5ef9c92f57c47 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x34 +#define SMU11_DRIVER_IF_VERSION 0x35 #define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 @@ -127,7 +127,7 @@ #define FEATURE_DF_CSTATE_BIT 45 #define FEATURE_2_STEP_PSTATE_BIT 46 #define FEATURE_SMNCLK_DPM_BIT 47 -#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_PERLINK_GMIDOWN_BIT 48 #define FEATURE_GFX_EDC_BIT 49 #define FEATURE_SPARE_50_BIT 50 #define FEATURE_SPARE_51_BIT 51 @@ -169,7 +169,7 @@ typedef enum { #define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 #define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 #define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCEFCLK 0x00000800 -#define DPM_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00001000 +#define DPM_OVERRIDE_ENABLE_FAST_FCLK_TIMER 0x00001000 #define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 #define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index f2a522176ca0a..ee1506beb0ea1 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -30,7 +30,7 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x34 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 /* MP Apertures */ -- GitLab From 707477b0861f5d7b93512024db8d39db5a65025c Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Tue, 28 Jul 2020 09:44:26 -0400 Subject: [PATCH 0329/1494] drm/amd/display: Store tiling_flags and tmz_surface on dm_plane_state [Why] Store these in advance so we can reuse them later in commit_tail without having to reserve the fbo again. These will also be used for checking for tiling changes when deciding to reset the plane or not. [How] This change should mostly be a refactor. Only commit check is affected for now and I'll drop the get_fb_info calls in prepare_planes and commit_tail after. This runs a prepass loop once we think that all planes have been added to the context and replaces the get_fb_info calls with accessing the dm_plane_state instead. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 60 +++++++++++-------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 + 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7f6a91b4fe4e1..81eeaff3acb1a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3627,8 +3627,17 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state, static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, uint64_t *tiling_flags, bool *tmz_surface) { - struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); - int r = amdgpu_bo_reserve(rbo, false); + struct amdgpu_bo *rbo; + int r; + + if (!amdgpu_fb) { + *tiling_flags = 0; + *tmz_surface = false; + return 0; + } + + rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); + r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { /* Don't show error message when returning -ERESTARTSYS */ @@ -4051,13 +4060,10 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, struct drm_crtc_state *crtc_state) { struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state); - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(plane_state->fb); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); struct dc_scaling_info scaling_info; struct dc_plane_info plane_info; - uint64_t tiling_flags; int ret; - bool tmz_surface = false; bool force_disable_dcc = false; ret = fill_dc_scaling_info(plane_state, &scaling_info); @@ -4069,15 +4075,12 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, dc_plane_state->clip_rect = scaling_info.clip_rect; dc_plane_state->scaling_quality = scaling_info.scaling_quality; - ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface); - if (ret) - return ret; - force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend; - ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags, + ret = fill_dc_plane_info_and_addr(adev, plane_state, + dm_plane_state->tiling_flags, &plane_info, &dc_plane_state->address, - tmz_surface, + dm_plane_state->tmz_surface, force_disable_dcc); if (ret) return ret; @@ -5675,6 +5678,10 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) dc_plane_state_retain(dm_plane_state->dc_state); } + /* Framebuffer hasn't been updated yet, so retain old flags. */ + dm_plane_state->tiling_flags = old_dm_plane_state->tiling_flags; + dm_plane_state->tmz_surface = old_dm_plane_state->tmz_surface; + return &dm_plane_state->base; } @@ -8482,13 +8489,9 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, continue; for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(new_plane_state->fb); struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane]; struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane]; struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane]; - uint64_t tiling_flags; - bool tmz_surface = false; new_plane_crtc = new_plane_state->crtc; new_dm_plane_state = to_dm_plane_state(new_plane_state); @@ -8535,16 +8538,12 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, bundle->surface_updates[num_plane].scaling_info = scaling_info; - if (amdgpu_fb) { - ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface); - if (ret) - goto cleanup; - + if (new_plane_state->fb) { ret = fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, tiling_flags, - plane_info, - &flip_addr->address, tmz_surface, - false); + dm->adev, new_plane_state, + new_dm_plane_state->tiling_flags, + plane_info, &flip_addr->address, + new_dm_plane_state->tmz_surface, false); if (ret) goto cleanup; @@ -8758,6 +8757,17 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* Prepass for updating tiling flags on new planes. */ + for_each_new_plane_in_state(state, plane, new_plane_state, i) { + struct dm_plane_state *new_dm_plane_state = to_dm_plane_state(new_plane_state); + struct amdgpu_framebuffer *new_afb = to_amdgpu_framebuffer(new_plane_state->fb); + + ret = get_fb_info(new_afb, &new_dm_plane_state->tiling_flags, + &new_dm_plane_state->tmz_surface); + if (ret) + goto fail; + } + /* Remove exiting planes if they are modified */ for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { ret = dm_update_plane_state(dc, state, plane, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index fd863331dee1c..a7856ae2e5f50 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -412,6 +412,8 @@ struct dc_plane_state; struct dm_plane_state { struct drm_plane_state base; struct dc_plane_state *dc_state; + uint64_t tiling_flags; + bool tmz_surface; }; struct dm_crtc_state { -- GitLab From 9a81cc60796b9f86cf19245e68562750541bb575 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Tue, 28 Jul 2020 09:59:53 -0400 Subject: [PATCH 0330/1494] drm/amd/display: Reset plane when tiling flags change [Why] Enabling or disable DCC or switching between tiled and linear formats can require bandwidth updates. They're currently skipping all DC validation by being treated as purely surface updates. [How] Treat tiling_flag changes (which encode DCC state) as a condition for resetting the plane. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 81eeaff3acb1a..89083210855d6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8258,6 +8258,8 @@ static bool should_reset_plane(struct drm_atomic_state *state, * TODO: Come up with a more elegant solution for this. */ for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) { + struct dm_plane_state *old_dm_plane_state, *new_dm_plane_state; + if (other->type == DRM_PLANE_TYPE_CURSOR) continue; @@ -8268,9 +8270,20 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (old_other_state->crtc != new_other_state->crtc) return true; - /* TODO: Remove this once we can handle fast format changes. */ - if (old_other_state->fb && new_other_state->fb && - old_other_state->fb->format != new_other_state->fb->format) + /* Framebuffer checks fall at the end. */ + if (!old_other_state->fb || !new_other_state->fb) + continue; + + /* Pixel format changes can require bandwidth updates. */ + if (old_other_state->fb->format != new_other_state->fb->format) + return true; + + old_dm_plane_state = to_dm_plane_state(old_other_state); + new_dm_plane_state = to_dm_plane_state(new_other_state); + + /* Tiling and DCC changes also require bandwidth updates. */ + if (old_dm_plane_state->tiling_flags != + new_dm_plane_state->tiling_flags) return true; } -- GitLab From cf322b49c9e8fe41e5c9d0b5e57eee84085da553 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Tue, 28 Jul 2020 10:03:10 -0400 Subject: [PATCH 0331/1494] drm/amd/display: Avoid using unvalidated tiling_flags and tmz_surface in prepare_planes [Why] We're racing with userspace as the flags could potentially change from when we acquired and validated them in commit_check. [How] We unfortunately can't drop this function in its entirety from prepare_planes since we don't know the afb->address at commit_check time yet. So instead of querying new tiling_flags and tmz_surface use the ones from the plane_state directly. While we're at it, also update the force_disable_dcc option based on the state from atomic check. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 89083210855d6..03534ff0c8958 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5716,14 +5716,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, struct list_head list; struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; - uint64_t tiling_flags; uint32_t domain; int r; - bool tmz_surface = false; - bool force_disable_dcc = false; - - dm_plane_state_old = to_dm_plane_state(plane->state); - dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { DRM_DEBUG_DRIVER("No FB bound\n"); @@ -5767,27 +5761,35 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, return r; } - amdgpu_bo_get_tiling_flags(rbo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(rbo); - ttm_eu_backoff_reservation(&ticket, &list); afb->address = amdgpu_bo_gpu_offset(rbo); amdgpu_bo_ref(rbo); + /** + * We don't do surface updates on planes that have been newly created, + * but we also don't have the afb->address during atomic check. + * + * Fill in buffer attributes depending on the address here, but only on + * newly created planes since they're not being used by DC yet and this + * won't modify global state. + */ + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); + if (dm_plane_state_new->dc_state && - dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { - struct dc_plane_state *plane_state = dm_plane_state_new->dc_state; + dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { + struct dc_plane_state *plane_state = + dm_plane_state_new->dc_state; + bool force_disable_dcc = !plane_state->dcc.enable; - force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend; fill_plane_buffer_attributes( adev, afb, plane_state->format, plane_state->rotation, - tiling_flags, &plane_state->tiling_info, - &plane_state->plane_size, &plane_state->dcc, - &plane_state->address, tmz_surface, - force_disable_dcc); + dm_plane_state_new->tiling_flags, + &plane_state->tiling_info, &plane_state->plane_size, + &plane_state->dcc, &plane_state->address, + dm_plane_state_new->tmz_surface, force_disable_dcc); } return 0; -- GitLab From 8ce5d8425d39eb9197e30bcffc5afbaa7079b723 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Thu, 6 Aug 2020 15:48:10 -0400 Subject: [PATCH 0332/1494] drm/amd/display: Use validated tiling_flags and tmz_surface in commit_tail [Why] So we're not racing with userspace or deadlocking DM. [How] These flags are now stored on dm_plane_state itself and acquried and validated during commit_check, so just use those instead. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 03534ff0c8958..c3ac47b835d6b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7012,8 +7012,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, long r; unsigned long flags; struct amdgpu_bo *abo; - uint64_t tiling_flags; - bool tmz_surface = false; uint32_t target_vblank, last_flip_vblank; bool vrr_active = amdgpu_dm_vrr_active(acrtc_state); bool pflip_present = false; @@ -7097,21 +7095,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (unlikely(r <= 0)) DRM_ERROR("Waiting for fences timed out!"); - /* - * We cannot reserve buffers here, which means the normal flag - * access functions don't work. Paper over this with READ_ONCE, - * but maybe the flags are invariant enough that not even that - * would be needed. - */ - tiling_flags = READ_ONCE(abo->tiling_flags); - tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; - fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, tiling_flags, + dm->adev, new_plane_state, + dm_new_plane_state->tiling_flags, &bundle->plane_infos[planes_count], &bundle->flip_addrs[planes_count].address, - tmz_surface, - false); + dm_new_plane_state->tmz_surface, false); DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n", new_plane_state->plane->index, -- GitLab From dc4cb30deec713888d31ec6d81c8ca34605089d5 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Tue, 28 Jul 2020 10:48:21 -0400 Subject: [PATCH 0333/1494] drm/amd/display: Reset plane for anything that's not a FAST update [Why] MEDIUM or FULL updates can require global validation or affect bandwidth. By treating these all simply as surface updates we aren't actually passing this through DC global validation. [How] There's currently no way to pass surface updates through DC global validation, nor do I think it's a good idea to change the interface to accept these. DC global validation itself is currently stateless, and we can move our update type checking to be stateless as well by duplicating DC surface checks in DM based on DRM properties. We wanted to rely on DC automatically determining this since DC knows best, but DM is ultimately what fills in everything into DC plane state so it does need to know as well. There are basically only three paths that we exercise in DM today: 1) Cursor (async update) 2) Pageflip (fast update) 3) Full pipe programming (medium/full updates) Which means that anything that's more than a pageflip really needs to go down path #3. So this change duplicates all the surface update checks based on DRM state instead inside of should_reset_plane(). Next step is dropping dm_determine_update_type_for_commit and we no longer require the old DC state at all for global validation. Optimization can come later so we don't reset DC planes at all for MEDIUM udpates and avoid validation, but we might require some extra checks in DM to achieve this. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c3ac47b835d6b..0b23c42200206 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8261,6 +8261,31 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (old_other_state->crtc != new_other_state->crtc) return true; + /* Src/dst size and scaling updates. */ + if (old_other_state->src_w != new_other_state->src_w || + old_other_state->src_h != new_other_state->src_h || + old_other_state->crtc_w != new_other_state->crtc_w || + old_other_state->crtc_h != new_other_state->crtc_h) + return true; + + /* Rotation / mirroring updates. */ + if (old_other_state->rotation != new_other_state->rotation) + return true; + + /* Blending updates. */ + if (old_other_state->pixel_blend_mode != + new_other_state->pixel_blend_mode) + return true; + + /* Alpha updates. */ + if (old_other_state->alpha != new_other_state->alpha) + return true; + + /* Colorspace changes. */ + if (old_other_state->color_range != new_other_state->color_range || + old_other_state->color_encoding != new_other_state->color_encoding) + return true; + /* Framebuffer checks fall at the end. */ if (!old_other_state->fb || !new_other_state->fb) continue; -- GitLab From f6d7c7faf0ee69569bc2ad309f48ab76785d2972 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Tue, 28 Jul 2020 11:08:02 -0400 Subject: [PATCH 0334/1494] drm/amd/display: Drop dm_determine_update_type_for_commit [Why] This was added in the past to solve the issue of not knowing when to stall for medium and full updates in DM. Since DC is ultimately decides what requires bandwidth changes we wanted to make use of it directly to determine this. The problem is that we can't actually pass any of the stream or surface updates into DC global validation, so we don't actually check if the new configuration is valid - we just validate the old existing config instead and stall for outstanding commits to finish. There's also the problem of grabbing the DRM private object for pageflips which can lead to page faults in the case where commits execute out of order and free a DRM private object state that was still required for commit tail. [How] Now that we reset the plane in DM with the same conditions DC checks we can have planes go through DC validation and we know when we need to check and stall based on whether the stream or planes changed. We mark lock_and_validation_needed whenever we've done this, so just go back to using that instead of dm_determine_update_type_for_commit. Since we'll skip resetting the plane for a pageflip we will no longer grab the DRM private object for pageflips as well, avoiding the page fault issued caused by pageflipping under load with commits executing out of order. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 199 ++---------------- 1 file changed, 17 insertions(+), 182 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0b23c42200206..8f27bebf46337 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8466,161 +8466,6 @@ static int dm_update_plane_state(struct dc *dc, return ret; } -static int -dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, - struct drm_atomic_state *state, - enum surface_update_type *out_type) -{ - struct dc *dc = dm->dc; - struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL; - int i, j, num_plane, ret = 0; - struct drm_plane_state *old_plane_state, *new_plane_state; - struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; - struct drm_crtc *new_plane_crtc; - struct drm_plane *plane; - - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state, *old_crtc_state; - struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state; - struct dc_stream_status *status = NULL; - enum surface_update_type update_type = UPDATE_TYPE_FAST; - struct surface_info_bundle { - struct dc_surface_update surface_updates[MAX_SURFACES]; - struct dc_plane_info plane_infos[MAX_SURFACES]; - struct dc_scaling_info scaling_infos[MAX_SURFACES]; - struct dc_flip_addrs flip_addrs[MAX_SURFACES]; - struct dc_stream_update stream_update; - } *bundle; - - bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); - - if (!bundle) { - DRM_ERROR("Failed to allocate update bundle\n"); - /* Set type to FULL to avoid crashing in DC*/ - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - - memset(bundle, 0, sizeof(struct surface_info_bundle)); - - new_dm_crtc_state = to_dm_crtc_state(new_crtc_state); - old_dm_crtc_state = to_dm_crtc_state(old_crtc_state); - num_plane = 0; - - if (new_dm_crtc_state->stream != old_dm_crtc_state->stream) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - if (!new_dm_crtc_state->stream) - continue; - - for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { - struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane]; - struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane]; - struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane]; - - new_plane_crtc = new_plane_state->crtc; - new_dm_plane_state = to_dm_plane_state(new_plane_state); - old_dm_plane_state = to_dm_plane_state(old_plane_state); - - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (new_dm_plane_state->dc_state != old_dm_plane_state->dc_state) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - if (crtc != new_plane_crtc) - continue; - - bundle->surface_updates[num_plane].surface = - new_dm_plane_state->dc_state; - - if (new_crtc_state->mode_changed) { - bundle->stream_update.dst = new_dm_crtc_state->stream->dst; - bundle->stream_update.src = new_dm_crtc_state->stream->src; - } - - if (new_crtc_state->color_mgmt_changed) { - bundle->surface_updates[num_plane].gamma = - new_dm_plane_state->dc_state->gamma_correction; - bundle->surface_updates[num_plane].in_transfer_func = - new_dm_plane_state->dc_state->in_transfer_func; - bundle->surface_updates[num_plane].gamut_remap_matrix = - &new_dm_plane_state->dc_state->gamut_remap_matrix; - bundle->stream_update.gamut_remap = - &new_dm_crtc_state->stream->gamut_remap_matrix; - bundle->stream_update.output_csc_transform = - &new_dm_crtc_state->stream->csc_color_matrix; - bundle->stream_update.out_transfer_func = - new_dm_crtc_state->stream->out_transfer_func; - } - - ret = fill_dc_scaling_info(new_plane_state, - scaling_info); - if (ret) - goto cleanup; - - bundle->surface_updates[num_plane].scaling_info = scaling_info; - - if (new_plane_state->fb) { - ret = fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, - new_dm_plane_state->tiling_flags, - plane_info, &flip_addr->address, - new_dm_plane_state->tmz_surface, false); - if (ret) - goto cleanup; - - bundle->surface_updates[num_plane].plane_info = plane_info; - bundle->surface_updates[num_plane].flip_addr = flip_addr; - } - - num_plane++; - } - - if (num_plane == 0) - continue; - - ret = dm_atomic_get_state(state, &dm_state); - if (ret) - goto cleanup; - - old_dm_state = dm_atomic_get_old_state(state); - if (!old_dm_state) { - ret = -EINVAL; - goto cleanup; - } - - status = dc_stream_get_status_from_state(old_dm_state->context, - new_dm_crtc_state->stream); - bundle->stream_update.stream = new_dm_crtc_state->stream; - /* - * TODO: DC modifies the surface during this call so we need - * to lock here - find a way to do this without locking. - */ - mutex_lock(&dm->dc_lock); - update_type = dc_check_update_surfaces_for_stream( - dc, bundle->surface_updates, num_plane, - &bundle->stream_update, status); - mutex_unlock(&dm->dc_lock); - - if (update_type > UPDATE_TYPE_MED) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - } - -cleanup: - kfree(bundle); - - *out_type = update_type; - return ret; -} #if defined(CONFIG_DRM_AMD_DC_DCN) static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) { @@ -8661,8 +8506,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm * acquired. For full updates case which removes/adds/updates streams on one * CRTC while flipping on another CRTC, acquiring global lock will guarantee * that any such full update commit will wait for completion of any outstanding - * flip using DRMs synchronization events. See - * dm_determine_update_type_for_commit() + * flip using DRMs synchronization events. * * Note that DM adds the affected connectors for all CRTCs in state, when that * might not seem necessary. This is because DC stream creation requires the @@ -8683,15 +8527,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; - enum surface_update_type update_type = UPDATE_TYPE_FAST; - enum surface_update_type overall_update_type = UPDATE_TYPE_FAST; enum dc_status status; int ret, i; - - /* - * This bool will be set for true for any modeset/reset - * or plane update which implies non fast surface update. - */ bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); @@ -8885,27 +8722,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; - overall_update_type = UPDATE_TYPE_FULL; lock_and_validation_needed = true; } - ret = dm_determine_update_type_for_commit(&adev->dm, state, &update_type); - if (ret) - goto fail; - - if (overall_update_type < update_type) - overall_update_type = update_type; - - /* - * lock_and_validation_needed was an old way to determine if we need to set - * the global lock. Leaving it in to check if we broke any corner cases - * lock_and_validation_needed true = UPDATE_TYPE_FULL or UPDATE_TYPE_MED - * lock_and_validation_needed false = UPDATE_TYPE_FAST + /** + * Streams and planes are reset when there are changes that affect + * bandwidth. Anything that affects bandwidth needs to go through + * DC global validation to ensure that the configuration can be applied + * to hardware. + * + * We have to currently stall out here in atomic_check for outstanding + * commits to finish in this case because our IRQ handlers reference + * DRM state directly - we can end up disabling interrupts too early + * if we don't. + * + * TODO: Remove this stall and drop DM state private objects. */ - if (lock_and_validation_needed && overall_update_type <= UPDATE_TYPE_FAST) - WARN(1, "Global lock should be Set, overall_update_type should be UPDATE_TYPE_MED or UPDATE_TYPE_FULL"); - - if (overall_update_type > UPDATE_TYPE_FAST) { + if (lock_and_validation_needed) { ret = dm_atomic_get_state(state, &dm_state); if (ret) goto fail; @@ -8987,7 +8820,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - dm_new_crtc_state->update_type = (int)overall_update_type; + dm_new_crtc_state->update_type = lock_and_validation_needed ? + UPDATE_TYPE_FULL : + UPDATE_TYPE_FAST; } /* Must be success */ -- GitLab From 77f47d239545810a899bd0531ae81712f3a85092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 6 Aug 2020 14:44:07 +0200 Subject: [PATCH 0335/1494] drm/amdgpu: make sure userptr ttm is allocated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to allocate that manually now. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com> Tested-by: Michel Dänzer <mdaenzer@redhat.com> Link: https://patchwork.freedesktop.org/patch/384330/ --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 17 +++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 ++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 9015c7b76d600..55d2e870fddad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -564,7 +564,7 @@ static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr) mutex_lock(&process_info->lock); - ret = amdgpu_ttm_tt_set_userptr(bo->tbo.ttm, user_addr, 0); + ret = amdgpu_ttm_tt_set_userptr(&bo->tbo, user_addr, 0); if (ret) { pr_err("%s: Failed to set userptr: %d\n", __func__, ret); goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index de9784b0c19b1..b2dc320e7305c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -332,7 +332,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, bo = gem_to_amdgpu_bo(gobj); bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT; bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT; - r = amdgpu_ttm_tt_set_userptr(bo->tbo.ttm, args->addr, args->flags); + r = amdgpu_ttm_tt_set_userptr(&bo->tbo, args->addr, args->flags); if (r) goto release_object; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 28557839f1329..67d2eef2f9ebd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1407,21 +1407,26 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt for the current * task * - * @ttm: The ttm_tt object to bind this userptr object to + * @bo: The ttm_buffer_object to bind this userptr to * @addr: The address in the current tasks VM space to use * @flags: Requirements of userptr object. * * Called by amdgpu_gem_userptr_ioctl() to bind userptr pages * to current task */ -int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, - uint32_t flags) +int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, + uint64_t addr, uint32_t flags) { - struct amdgpu_ttm_tt *gtt = (void *)ttm; + struct amdgpu_ttm_tt *gtt; - if (gtt == NULL) - return -EINVAL; + if (!bo->ttm) { + /* TODO: We want a separate TTM object type for userptrs */ + bo->ttm = amdgpu_ttm_tt_create(bo, 0); + if (bo->ttm == NULL) + return -ENOMEM; + } + gtt = (void*)bo->ttm; gtt->userptr = addr; gtt->userflags = flags; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 36b024fd077e3..433156c2e8fbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -132,8 +132,8 @@ static inline bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm) #endif void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages); -int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, - uint32_t flags); +int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, + uint64_t addr, uint32_t flags); bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm); bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, -- GitLab From 3a74265c54f883c847ed8554129baefb3e04f135 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso <tomeu.vizoso@collabora.com> Date: Thu, 11 Jun 2020 10:58:43 +0200 Subject: [PATCH 0336/1494] drm/panfrost: Make sure GPU is powered on when reading GPU_LATEST_FLUSH_ID Bifrost devices do support the flush reduction feature, so on first job submit we were trying to read the register while still powered off. If the GPU is powered off, the feature doesn't bring any benefit, so don't try to read. Tested-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-1-tomeu.vizoso@collabora.com --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index f2c1ddc41a9bf..e0f190e438139 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -10,6 +10,7 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include "panfrost_device.h" #include "panfrost_features.h" @@ -368,7 +369,16 @@ void panfrost_gpu_fini(struct panfrost_device *pfdev) u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev) { - if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) - return gpu_read(pfdev, GPU_LATEST_FLUSH_ID); + u32 flush_id; + + if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) { + /* Flush reduction only makes sense when the GPU is kept powered on between jobs */ + if (pm_runtime_get_if_in_use(pfdev->dev)) { + flush_id = gpu_read(pfdev, GPU_LATEST_FLUSH_ID); + pm_runtime_put(pfdev->dev); + return flush_id; + } + } + return 0; } -- GitLab From 72ef7fe96fd20d3d0e538e165b393819f99870ad Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso <tomeu.vizoso@collabora.com> Date: Thu, 11 Jun 2020 10:58:44 +0200 Subject: [PATCH 0337/1494] drm/panfrost: Add compatible string for bifrost Mesa now supports some Bifrost devices, so enable it. Tested-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200611085900.49740-2-tomeu.vizoso@collabora.com --- drivers/gpu/drm/panfrost/panfrost_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index ada51df9a7a32..f79f98534ab62 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -677,6 +677,7 @@ static const struct of_device_id dt_match[] = { { .compatible = "arm,mali-t830", .data = &default_data, }, { .compatible = "arm,mali-t860", .data = &default_data, }, { .compatible = "arm,mali-t880", .data = &default_data, }, + { .compatible = "arm,mali-bifrost", .data = &default_data, }, {} }; MODULE_DEVICE_TABLE(of, dt_match); -- GitLab From 862cc626210e34501b4d7a7795c41a67785987e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:53:56 +0200 Subject: [PATCH 0338/1494] drm/panfrost: avoid static declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This declaration can be avoided so change it. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-2-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 38 ++++++++++----------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 413987038fbfc..1b560b903ea61 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -14,7 +14,24 @@ #include "panfrost_gpu.h" #include "panfrost_regs.h" -static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev); +static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) +{ + ktime_t now; + ktime_t last; + + if (!pfdev->devfreq.devfreq) + return; + + now = ktime_get(); + last = pfdev->devfreq.time_last_update; + + if (atomic_read(&pfdev->devfreq.busy_count) > 0) + pfdev->devfreq.busy_time += ktime_sub(now, last); + else + pfdev->devfreq.idle_time += ktime_sub(now, last); + + pfdev->devfreq.time_last_update = now; +} static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) @@ -139,25 +156,6 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) devfreq_suspend_device(pfdev->devfreq.devfreq); } -static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) -{ - ktime_t now; - ktime_t last; - - if (!pfdev->devfreq.devfreq) - return; - - now = ktime_get(); - last = pfdev->devfreq.time_last_update; - - if (atomic_read(&pfdev->devfreq.busy_count) > 0) - pfdev->devfreq.busy_time += ktime_sub(now, last); - else - pfdev->devfreq.idle_time += ktime_sub(now, last); - - pfdev->devfreq.time_last_update = now; -} - void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) { panfrost_devfreq_update_utilization(pfdev); -- GitLab From 9713e942a539c55b5e0bc64ba83b736bda1087fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:53:57 +0200 Subject: [PATCH 0339/1494] drm/panfrost: clean headers in devfreq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't include not required headers and sort them. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-3-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 1b560b903ea61..df7b71da9a84a 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -1,18 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright 2019 Collabora ltd. */ + +#include <linux/clk.h> #include <linux/devfreq.h> #include <linux/devfreq_cooling.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> -#include <linux/clk.h> -#include <linux/regulator/consumer.h> #include "panfrost_device.h" #include "panfrost_devfreq.h" -#include "panfrost_features.h" -#include "panfrost_issues.h" -#include "panfrost_gpu.h" -#include "panfrost_regs.h" static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) { -- GitLab From eb9dd67249b55fd1fa3d7359be387ea2079247a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:53:58 +0200 Subject: [PATCH 0340/1494] drm/panfrost: don't use pfdevfreq.busy_count to know if hw is idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This use devfreq variable that will be lock with spinlock in future patches. We should either introduce a function to access this one but as devfreq is optional let's just remove it. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-4-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_job.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 360146f6f3d9d..4c13dbae68fbb 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -581,10 +581,6 @@ int panfrost_job_is_idle(struct panfrost_device *pfdev) struct panfrost_job_slot *js = pfdev->js; int i; - /* Check whether the hardware is idle */ - if (atomic_read(&pfdev->devfreq.busy_count)) - return false; - for (i = 0; i < NUM_JOB_SLOTS; i++) { /* If there are any jobs in the HW queue, we're not idle */ if (atomic_read(&js->queue[i].sched.hw_rq_count)) -- GitLab From 9bfacfc82f903b066b0b63460d5b7943705048a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:53:59 +0200 Subject: [PATCH 0341/1494] drm/panfrost: introduce panfrost_devfreq struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a proper panfrost_devfreq to deal with devfreq variables. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-5-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 76 ++++++++++++--------- drivers/gpu/drm/panfrost/panfrost_devfreq.h | 20 +++++- drivers/gpu/drm/panfrost/panfrost_device.h | 11 +-- drivers/gpu/drm/panfrost/panfrost_job.c | 6 +- 4 files changed, 66 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index df7b71da9a84a..962550363391b 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -10,23 +10,23 @@ #include "panfrost_device.h" #include "panfrost_devfreq.h" -static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev) +static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) { ktime_t now; ktime_t last; - if (!pfdev->devfreq.devfreq) + if (!pfdevfreq->devfreq) return; now = ktime_get(); - last = pfdev->devfreq.time_last_update; + last = pfdevfreq->time_last_update; - if (atomic_read(&pfdev->devfreq.busy_count) > 0) - pfdev->devfreq.busy_time += ktime_sub(now, last); + if (atomic_read(&pfdevfreq->busy_count) > 0) + pfdevfreq->busy_time += ktime_sub(now, last); else - pfdev->devfreq.idle_time += ktime_sub(now, last); + pfdevfreq->idle_time += ktime_sub(now, last); - pfdev->devfreq.time_last_update = now; + pfdevfreq->time_last_update = now; } static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, @@ -47,30 +47,31 @@ static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, return 0; } -static void panfrost_devfreq_reset(struct panfrost_device *pfdev) +static void panfrost_devfreq_reset(struct panfrost_devfreq *pfdevfreq) { - pfdev->devfreq.busy_time = 0; - pfdev->devfreq.idle_time = 0; - pfdev->devfreq.time_last_update = ktime_get(); + pfdevfreq->busy_time = 0; + pfdevfreq->idle_time = 0; + pfdevfreq->time_last_update = ktime_get(); } static int panfrost_devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *status) { struct panfrost_device *pfdev = dev_get_drvdata(dev); + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; - panfrost_devfreq_update_utilization(pfdev); + panfrost_devfreq_update_utilization(pfdevfreq); status->current_frequency = clk_get_rate(pfdev->clock); - status->total_time = ktime_to_ns(ktime_add(pfdev->devfreq.busy_time, - pfdev->devfreq.idle_time)); + status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, + pfdevfreq->idle_time)); - status->busy_time = ktime_to_ns(pfdev->devfreq.busy_time); + status->busy_time = ktime_to_ns(pfdevfreq->busy_time); - panfrost_devfreq_reset(pfdev); + panfrost_devfreq_reset(pfdevfreq); - dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", status->busy_time, - status->total_time, + dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", + status->busy_time, status->total_time, status->busy_time / (status->total_time / 100), status->current_frequency / 1000 / 1000); @@ -91,6 +92,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) struct device *dev = &pfdev->pdev->dev; struct devfreq *devfreq; struct thermal_cooling_device *cooling; + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; ret = dev_pm_opp_of_add_table(dev); if (ret == -ENODEV) /* Optional, continue without devfreq */ @@ -98,7 +100,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) else if (ret) return ret; - panfrost_devfreq_reset(pfdev); + panfrost_devfreq_reset(pfdevfreq); cur_freq = clk_get_rate(pfdev->clock); @@ -116,53 +118,59 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) dev_pm_opp_of_remove_table(dev); return PTR_ERR(devfreq); } - pfdev->devfreq.devfreq = devfreq; + pfdevfreq->devfreq = devfreq; cooling = of_devfreq_cooling_register(dev->of_node, devfreq); if (IS_ERR(cooling)) DRM_DEV_INFO(dev, "Failed to register cooling device\n"); else - pfdev->devfreq.cooling = cooling; + pfdevfreq->cooling = cooling; return 0; } void panfrost_devfreq_fini(struct panfrost_device *pfdev) { - if (pfdev->devfreq.cooling) - devfreq_cooling_unregister(pfdev->devfreq.cooling); + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + + if (pfdevfreq->cooling) + devfreq_cooling_unregister(pfdevfreq->cooling); dev_pm_opp_of_remove_table(&pfdev->pdev->dev); } void panfrost_devfreq_resume(struct panfrost_device *pfdev) { - if (!pfdev->devfreq.devfreq) + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + + if (!pfdevfreq->devfreq) return; - panfrost_devfreq_reset(pfdev); + panfrost_devfreq_reset(pfdevfreq); - devfreq_resume_device(pfdev->devfreq.devfreq); + devfreq_resume_device(pfdevfreq->devfreq); } void panfrost_devfreq_suspend(struct panfrost_device *pfdev) { - if (!pfdev->devfreq.devfreq) + struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + + if (!pfdevfreq->devfreq) return; - devfreq_suspend_device(pfdev->devfreq.devfreq); + devfreq_suspend_device(pfdevfreq->devfreq); } -void panfrost_devfreq_record_busy(struct panfrost_device *pfdev) +void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) { - panfrost_devfreq_update_utilization(pfdev); - atomic_inc(&pfdev->devfreq.busy_count); + panfrost_devfreq_update_utilization(pfdevfreq); + atomic_inc(&pfdevfreq->busy_count); } -void panfrost_devfreq_record_idle(struct panfrost_device *pfdev) +void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) { int count; - panfrost_devfreq_update_utilization(pfdev); - count = atomic_dec_if_positive(&pfdev->devfreq.busy_count); + panfrost_devfreq_update_utilization(pfdevfreq); + count = atomic_dec_if_positive(&pfdevfreq->busy_count); WARN_ON(count < 0); } diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 0611beffc8d0e..0697f8d5aa34d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -4,13 +4,29 @@ #ifndef __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__ +#include <linux/ktime.h> + +struct devfreq; +struct thermal_cooling_device; + +struct panfrost_device; + +struct panfrost_devfreq { + struct devfreq *devfreq; + struct thermal_cooling_device *cooling; + ktime_t busy_time; + ktime_t idle_time; + ktime_t time_last_update; + atomic_t busy_count; +}; + int panfrost_devfreq_init(struct panfrost_device *pfdev); void panfrost_devfreq_fini(struct panfrost_device *pfdev); void panfrost_devfreq_resume(struct panfrost_device *pfdev); void panfrost_devfreq_suspend(struct panfrost_device *pfdev); -void panfrost_devfreq_record_busy(struct panfrost_device *pfdev); -void panfrost_devfreq_record_idle(struct panfrost_device *pfdev); +void panfrost_devfreq_record_busy(struct panfrost_devfreq *devfreq); +void panfrost_devfreq_record_idle(struct panfrost_devfreq *devfreq); #endif /* __PANFROST_DEVFREQ_H__ */ diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index c30c719a80594..2efa59c9d1c5d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -13,6 +13,8 @@ #include <drm/drm_mm.h> #include <drm/gpu_scheduler.h> +#include "panfrost_devfreq.h" + struct panfrost_device; struct panfrost_mmu; struct panfrost_job_slot; @@ -107,14 +109,7 @@ struct panfrost_device { struct list_head shrinker_list; struct shrinker shrinker; - struct { - struct devfreq *devfreq; - struct thermal_cooling_device *cooling; - ktime_t busy_time; - ktime_t idle_time; - ktime_t time_last_update; - atomic_t busy_count; - } devfreq; + struct panfrost_devfreq pfdevfreq; }; struct panfrost_mmu { diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 4c13dbae68fbb..30e7b7196dab0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -145,7 +145,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) u64 jc_head = job->jc; int ret; - panfrost_devfreq_record_busy(pfdev); + panfrost_devfreq_record_busy(&pfdev->pfdevfreq); ret = pm_runtime_get_sync(pfdev->dev); if (ret < 0) @@ -410,7 +410,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) for (i = 0; i < NUM_JOB_SLOTS; i++) { if (pfdev->jobs[i]) { pm_runtime_put_noidle(pfdev->dev); - panfrost_devfreq_record_idle(pfdev); + panfrost_devfreq_record_idle(&pfdev->pfdevfreq); pfdev->jobs[i] = NULL; } } @@ -478,7 +478,7 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data) pfdev->jobs[j] = NULL; panfrost_mmu_as_put(pfdev, &job->file_priv->mmu); - panfrost_devfreq_record_idle(pfdev); + panfrost_devfreq_record_idle(&pfdev->pfdevfreq); dma_fence_signal_locked(job->done_fence); pm_runtime_put_autosuspend(pfdev->dev); -- GitLab From ed85df3f60740bb4be23fbc2db283d59b361a834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:00 +0200 Subject: [PATCH 0342/1494] drm/panfrost: use spinlock instead of atomic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert busy_count to a simple int protected by spinlock. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-6-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 43 +++++++++++++++------ drivers/gpu/drm/panfrost/panfrost_devfreq.h | 9 ++++- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 962550363391b..78753cfb59fb2 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -12,16 +12,12 @@ static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) { - ktime_t now; - ktime_t last; - - if (!pfdevfreq->devfreq) - return; + ktime_t now, last; now = ktime_get(); last = pfdevfreq->time_last_update; - if (atomic_read(&pfdevfreq->busy_count) > 0) + if (pfdevfreq->busy_count > 0) pfdevfreq->busy_time += ktime_sub(now, last); else pfdevfreq->idle_time += ktime_sub(now, last); @@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, { struct panfrost_device *pfdev = dev_get_drvdata(dev); struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + unsigned long irqflags; + + status->current_frequency = clk_get_rate(pfdev->clock); + + spin_lock_irqsave(&pfdevfreq->lock, irqflags); panfrost_devfreq_update_utilization(pfdevfreq); - status->current_frequency = clk_get_rate(pfdev->clock); status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, pfdevfreq->idle_time)); @@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, panfrost_devfreq_reset(pfdevfreq); + spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); + dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", status->busy_time, status->total_time, status->busy_time / (status->total_time / 100), @@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) else if (ret) return ret; + spin_lock_init(&pfdevfreq->lock); + panfrost_devfreq_reset(pfdevfreq); cur_freq = clk_get_rate(pfdev->clock); @@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) { + unsigned long irqflags; + + if (!pfdevfreq->devfreq) + return; + + spin_lock_irqsave(&pfdevfreq->lock, irqflags); + panfrost_devfreq_update_utilization(pfdevfreq); - atomic_inc(&pfdevfreq->busy_count); + + pfdevfreq->busy_count++; + + spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); } void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) { - int count; + unsigned long irqflags; + + if (!pfdevfreq->devfreq) + return; + + spin_lock_irqsave(&pfdevfreq->lock, irqflags); panfrost_devfreq_update_utilization(pfdevfreq); - count = atomic_dec_if_positive(&pfdevfreq->busy_count); - WARN_ON(count < 0); + + WARN_ON(--pfdevfreq->busy_count < 0); + + spin_unlock_irqrestore(&pfdevfreq->lock, irqflags); } diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 0697f8d5aa34d..3392df1020be0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -4,6 +4,7 @@ #ifndef __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__ +#include <linux/spinlock.h> #include <linux/ktime.h> struct devfreq; @@ -14,10 +15,16 @@ struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; struct thermal_cooling_device *cooling; + ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; - atomic_t busy_count; + int busy_count; + /* + * Protect busy_time, idle_time, time_last_update and busy_count + * because these can be updated concurrently between multiple jobs. + */ + spinlock_t lock; }; int panfrost_devfreq_init(struct panfrost_device *pfdev); -- GitLab From 81f2fbe62cb54b6cf3d91078c4d49451ba7b9877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:01 +0200 Subject: [PATCH 0343/1494] drm/panfrost: properly handle error in probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a boolean to know if opp table has been added. With this, we can call panfrost_devfreq_fini() in case of error and release what has been initialised. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-7-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 25 ++++++++++++++++----- drivers/gpu/drm/panfrost/panfrost_devfreq.h | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 78753cfb59fb2..d9007f44b772d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -101,6 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) return 0; else if (ret) return ret; + pfdevfreq->opp_of_table_added = true; spin_lock_init(&pfdevfreq->lock); @@ -109,8 +110,10 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) cur_freq = clk_get_rate(pfdev->clock); opp = devfreq_recommended_opp(dev, &cur_freq, 0); - if (IS_ERR(opp)) - return PTR_ERR(opp); + if (IS_ERR(opp)) { + ret = PTR_ERR(opp); + goto err_fini; + } panfrost_devfreq_profile.initial_freq = cur_freq; dev_pm_opp_put(opp); @@ -119,8 +122,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL); if (IS_ERR(devfreq)) { DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n"); - dev_pm_opp_of_remove_table(dev); - return PTR_ERR(devfreq); + ret = PTR_ERR(devfreq); + goto err_fini; } pfdevfreq->devfreq = devfreq; @@ -131,15 +134,25 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) pfdevfreq->cooling = cooling; return 0; + +err_fini: + panfrost_devfreq_fini(pfdev); + return ret; } void panfrost_devfreq_fini(struct panfrost_device *pfdev) { struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; - if (pfdevfreq->cooling) + if (pfdevfreq->cooling) { devfreq_cooling_unregister(pfdevfreq->cooling); - dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + pfdevfreq->cooling = NULL; + } + + if (pfdevfreq->opp_of_table_added) { + dev_pm_opp_of_remove_table(&pfdev->pdev->dev); + pfdevfreq->opp_of_table_added = false; + } } void panfrost_devfreq_resume(struct panfrost_device *pfdev) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 3392df1020be0..2102699446874 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -15,6 +15,7 @@ struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; struct thermal_cooling_device *cooling; + bool opp_of_table_added; ktime_t busy_time; ktime_t idle_time; -- GitLab From d3c335da0200be9287cdf5755d19f62ce1670a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:02 +0200 Subject: [PATCH 0344/1494] drm/panfrost: rename error labels in device_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename goto labels in device_init it will be easier to maintain. Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-8-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_device.c | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index b172087eee6ae..9f89984f652a6 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -216,56 +216,56 @@ int panfrost_device_init(struct panfrost_device *pfdev) err = panfrost_regulator_init(pfdev); if (err) - goto err_out0; + goto out_clk; err = panfrost_reset_init(pfdev); if (err) { dev_err(pfdev->dev, "reset init failed %d\n", err); - goto err_out1; + goto out_regulator; } err = panfrost_pm_domain_init(pfdev); if (err) - goto err_out2; + goto out_reset; res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0); pfdev->iomem = devm_ioremap_resource(pfdev->dev, res); if (IS_ERR(pfdev->iomem)) { dev_err(pfdev->dev, "failed to ioremap iomem\n"); err = PTR_ERR(pfdev->iomem); - goto err_out3; + goto out_pm_domain; } err = panfrost_gpu_init(pfdev); if (err) - goto err_out3; + goto out_pm_domain; err = panfrost_mmu_init(pfdev); if (err) - goto err_out4; + goto out_gpu; err = panfrost_job_init(pfdev); if (err) - goto err_out5; + goto out_mmu; err = panfrost_perfcnt_init(pfdev); if (err) - goto err_out6; + goto out_job; return 0; -err_out6: +out_job: panfrost_job_fini(pfdev); -err_out5: +out_mmu: panfrost_mmu_fini(pfdev); -err_out4: +out_gpu: panfrost_gpu_fini(pfdev); -err_out3: +out_pm_domain: panfrost_pm_domain_fini(pfdev); -err_out2: +out_reset: panfrost_reset_fini(pfdev); -err_out1: +out_regulator: panfrost_regulator_fini(pfdev); -err_out0: +out_clk: panfrost_clk_fini(pfdev); return err; } -- GitLab From 25e247bbf85af3ad721dfeb2e2caf405f43b7e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:03 +0200 Subject: [PATCH 0345/1494] drm/panfrost: move devfreq_init()/fini() in device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Later we will introduce devfreq probing regulator if they are present. As regulator should be probe only one time we need to get this logic in the device_init(). panfrost_device is already taking care of devfreq_resume() and devfreq_suspend(), so it's not totally illogic to move the devfreq_init() and devfreq_fini() here. Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-9-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_device.c | 12 +++++++++++- drivers/gpu/drm/panfrost/panfrost_drv.c | 15 ++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index 9f89984f652a6..36b5c8fea3eba 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -214,9 +214,16 @@ int panfrost_device_init(struct panfrost_device *pfdev) return err; } + err = panfrost_devfreq_init(pfdev); + if (err) { + if (err != -EPROBE_DEFER) + dev_err(pfdev->dev, "devfreq init failed %d\n", err); + goto out_clk; + } + err = panfrost_regulator_init(pfdev); if (err) - goto out_clk; + goto out_devfreq; err = panfrost_reset_init(pfdev); if (err) { @@ -265,6 +272,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) panfrost_reset_fini(pfdev); out_regulator: panfrost_regulator_fini(pfdev); +out_devfreq: + panfrost_devfreq_fini(pfdev); out_clk: panfrost_clk_fini(pfdev); return err; @@ -278,6 +287,7 @@ void panfrost_device_fini(struct panfrost_device *pfdev) panfrost_gpu_fini(pfdev); panfrost_pm_domain_fini(pfdev); panfrost_reset_fini(pfdev); + panfrost_devfreq_fini(pfdev); panfrost_regulator_fini(pfdev); panfrost_clk_fini(pfdev); } diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index f79f98534ab62..36463c89e9669 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -14,7 +14,6 @@ #include <drm/drm_utils.h> #include "panfrost_device.h" -#include "panfrost_devfreq.h" #include "panfrost_gem.h" #include "panfrost_mmu.h" #include "panfrost_job.h" @@ -606,13 +605,6 @@ static int panfrost_probe(struct platform_device *pdev) goto err_out0; } - err = panfrost_devfreq_init(pfdev); - if (err) { - if (err != -EPROBE_DEFER) - dev_err(&pdev->dev, "Fatal error during devfreq init\n"); - goto err_out1; - } - pm_runtime_set_active(pfdev->dev); pm_runtime_mark_last_busy(pfdev->dev); pm_runtime_enable(pfdev->dev); @@ -625,16 +617,14 @@ static int panfrost_probe(struct platform_device *pdev) */ err = drm_dev_register(ddev, 0); if (err < 0) - goto err_out2; + goto err_out1; panfrost_gem_shrinker_init(ddev); return 0; -err_out2: - pm_runtime_disable(pfdev->dev); - panfrost_devfreq_fini(pfdev); err_out1: + pm_runtime_disable(pfdev->dev); panfrost_device_fini(pfdev); err_out0: drm_dev_put(ddev); @@ -650,7 +640,6 @@ static int panfrost_remove(struct platform_device *pdev) panfrost_gem_shrinker_cleanup(ddev); pm_runtime_get_sync(pfdev->dev); - panfrost_devfreq_fini(pfdev); panfrost_device_fini(pfdev); pm_runtime_put_sync_suspend(pfdev->dev); pm_runtime_disable(pfdev->dev); -- GitLab From 512f21227fd3d2dbe7aad57a995b9732229c9b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:04 +0200 Subject: [PATCH 0346/1494] drm/panfrost: dynamically alloc regulators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will later introduce regulators managed by OPP. Only alloc regulators when it's needed. This also help use to release the regulators only when they are allocated. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-10-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_device.c | 14 +++++++++----- drivers/gpu/drm/panfrost/panfrost_device.h | 3 +-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index 36b5c8fea3eba..f1474b961def1 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -90,9 +90,11 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) { int ret, i; - if (WARN(pfdev->comp->num_supplies > ARRAY_SIZE(pfdev->regulators), - "Too many supplies in compatible structure.\n")) - return -EINVAL; + pfdev->regulators = devm_kcalloc(pfdev->dev, pfdev->comp->num_supplies, + sizeof(*pfdev->regulators), + GFP_KERNEL); + if (!pfdev->regulators) + return -ENOMEM; for (i = 0; i < pfdev->comp->num_supplies; i++) pfdev->regulators[i].supply = pfdev->comp->supply_names[i]; @@ -119,8 +121,10 @@ static int panfrost_regulator_init(struct panfrost_device *pfdev) static void panfrost_regulator_fini(struct panfrost_device *pfdev) { - regulator_bulk_disable(pfdev->comp->num_supplies, - pfdev->regulators); + if (!pfdev->regulators) + return; + + regulator_bulk_disable(pfdev->comp->num_supplies, pfdev->regulators); } static void panfrost_pm_domain_fini(struct panfrost_device *pfdev) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index 2efa59c9d1c5d..953f7536a773f 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -22,7 +22,6 @@ struct panfrost_job; struct panfrost_perfcnt; #define NUM_JOB_SLOTS 3 -#define MAX_REGULATORS 2 #define MAX_PM_DOMAINS 3 struct panfrost_features { @@ -81,7 +80,7 @@ struct panfrost_device { void __iomem *iomem; struct clk *clock; struct clk *bus_clock; - struct regulator_bulk_data regulators[MAX_REGULATORS]; + struct regulator_bulk_data *regulators; struct reset_control *rstc; /* pm_domains for devices with more than one. */ struct device *pm_domain_devs[MAX_PM_DOMAINS]; -- GitLab From fd587ff01d59554144e2fd20f4113638a45c7c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com> Date: Fri, 10 Jul 2020 11:54:05 +0200 Subject: [PATCH 0347/1494] drm/panfrost: add regulators to devfreq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some OPP tables specify voltage for each frequency. Devfreq can handle these regulators but they should be get only 1 time to avoid issue and know who is in charge. If OPP table is probe don't init regulator. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-11-peron.clem@gmail.com --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 29 ++++++++++++++++++--- drivers/gpu/drm/panfrost/panfrost_devfreq.h | 2 ++ drivers/gpu/drm/panfrost/panfrost_device.c | 9 ++++--- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index d9007f44b772d..8ab025d0035f3 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -93,14 +93,30 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) unsigned long cur_freq; struct device *dev = &pfdev->pdev->dev; struct devfreq *devfreq; + struct opp_table *opp_table; struct thermal_cooling_device *cooling; struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; + opp_table = dev_pm_opp_set_regulators(dev, pfdev->comp->supply_names, + pfdev->comp->num_supplies); + if (IS_ERR(opp_table)) { + ret = PTR_ERR(opp_table); + /* Continue if the optional regulator is missing */ + if (ret != -ENODEV) { + DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n"); + goto err_fini; + } + } else { + pfdevfreq->regulators_opp_table = opp_table; + } + ret = dev_pm_opp_of_add_table(dev); - if (ret == -ENODEV) /* Optional, continue without devfreq */ - return 0; - else if (ret) - return ret; + if (ret) { + /* Optional, continue without devfreq */ + if (ret == -ENODEV) + ret = 0; + goto err_fini; + } pfdevfreq->opp_of_table_added = true; spin_lock_init(&pfdevfreq->lock); @@ -153,6 +169,11 @@ void panfrost_devfreq_fini(struct panfrost_device *pfdev) dev_pm_opp_of_remove_table(&pfdev->pdev->dev); pfdevfreq->opp_of_table_added = false; } + + if (pfdevfreq->regulators_opp_table) { + dev_pm_opp_put_regulators(pfdevfreq->regulators_opp_table); + pfdevfreq->regulators_opp_table = NULL; + } } void panfrost_devfreq_resume(struct panfrost_device *pfdev) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 2102699446874..db6ea48e21f9c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -8,12 +8,14 @@ #include <linux/ktime.h> struct devfreq; +struct opp_table; struct thermal_cooling_device; struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; + struct opp_table *regulators_opp_table; struct thermal_cooling_device *cooling; bool opp_of_table_added; diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index f1474b961def1..e6896733838ab 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -225,9 +225,12 @@ int panfrost_device_init(struct panfrost_device *pfdev) goto out_clk; } - err = panfrost_regulator_init(pfdev); - if (err) - goto out_devfreq; + /* OPP will handle regulators */ + if (!pfdev->pfdevfreq.opp_of_table_added) { + err = panfrost_regulator_init(pfdev); + if (err) + goto out_devfreq; + } err = panfrost_reset_init(pfdev); if (err) { -- GitLab From 9df0e0c1889677175037445d5ad1654d54176369 Mon Sep 17 00:00:00 2001 From: Navid Emamdoost <navid.emamdoost@gmail.com> Date: Sun, 14 Jun 2020 01:36:19 -0500 Subject: [PATCH 0348/1494] drm/panfrost: perfcnt: fix ref count leak in panfrost_perfcnt_enable_locked in panfrost_perfcnt_enable_locked, pm_runtime_get_sync is called which increments the counter even in case of failure, leading to incorrect ref count. In case of failure, decrement the ref count before returning. Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200614063619.44944-1-navid.emamdoost@gmail.com --- drivers/gpu/drm/panfrost/panfrost_perfcnt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c index ec4695cf3caf3..fdbc8d9491356 100644 --- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c +++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c @@ -83,11 +83,13 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, ret = pm_runtime_get_sync(pfdev->dev); if (ret < 0) - return ret; + goto err_put_pm; bo = drm_gem_shmem_create(pfdev->ddev, perfcnt->bosize); - if (IS_ERR(bo)) - return PTR_ERR(bo); + if (IS_ERR(bo)) { + ret = PTR_ERR(bo); + goto err_put_pm; + } /* Map the perfcnt buf in the address space attached to file_priv. */ ret = panfrost_gem_open(&bo->base, file_priv); @@ -168,6 +170,8 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, panfrost_gem_close(&bo->base, file_priv); err_put_bo: drm_gem_object_put(&bo->base); +err_put_pm: + pm_runtime_put(pfdev->dev); return ret; } -- GitLab From 018315d399fcc0407c4c160f24ffd60a36ee30c8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Fri, 7 Aug 2020 20:05:47 +0200 Subject: [PATCH 0349/1494] drm/mgag200: fix build on alpha arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building imgag200 for the alpha architecture it fails like this: mgag200_drv.c:233:9: error: implicit declaration of function ‘vmalloc’ 233 | bios = vmalloc(size); | ^~~~~~~ | kmalloc When building for other architectures vmalloc.h is pulled in via some other header file - for example asm-generic/io.h. Use an explicit include of vmalloc.h to fix the build. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Fixes: e20dfd27f7aa ("drm/mgag200: Add support for G200 desktop cards") Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Egbert Eich <eich@suse.com> Cc: Takashi Iwai <tiwai@suse.de> Cc: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200807180547.GA923146@ravnborg.org --- drivers/gpu/drm/mgag200/mgag200_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index 09170d46aa53b..b282b0e42c2df 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -9,6 +9,7 @@ #include <linux/console.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/vmalloc.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> -- GitLab From ca6fd7a66843b6ef64179d0a4ce943affbb6c057 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Thu, 6 Aug 2020 17:37:28 +0800 Subject: [PATCH 0350/1494] drm/amdgpu: use mode1 reset by default for sienna_cichlid Swith default gpu reset method for sienna_cichlid to MODE1 reset. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 74d02d270d342..da8024c2826ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -362,10 +362,15 @@ nv_asic_reset_method(struct amdgpu_device *adev) dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n", amdgpu_reset_method); - if (smu_baco_is_support(smu)) - return AMD_RESET_METHOD_BACO; - else + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: return AMD_RESET_METHOD_MODE1; + default: + if (smu_baco_is_support(smu)) + return AMD_RESET_METHOD_BACO; + else + return AMD_RESET_METHOD_MODE1; + } } static int nv_asic_reset(struct amdgpu_device *adev) -- GitLab From ad1cac262ed2c344ec93e145c5307480cecfbc2f Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 3 Aug 2020 11:15:14 +0800 Subject: [PATCH 0351/1494] drm/amd/powerplay: update swSMU VCN/JPEG PG logics Add lock protections and avoid unnecessary actions if the PG state is already the same as required. Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Matt Coffin <mcoffin13@gmail.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 57 ++++++++++++++++++- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 4 -- .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 6 +- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 8 --- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 8 --- .../drm/amd/powerplay/sienna_cichlid_ppt.c | 9 --- drivers/gpu/drm/amd/powerplay/smu_internal.h | 2 - 7 files changed, 60 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f3f50b5add996..1b64ca9ecccb6 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -133,6 +133,56 @@ int smu_get_dpm_freq_range(struct smu_context *smu, return ret; } +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_vcn_enable) + return 0; + + mutex_lock(&power_gate->vcn_gate_lock); + + if (atomic_read(&power_gate->vcn_gated) ^ enable) + goto out; + + ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->vcn_gated, !enable); + +out: + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_jpeg_enable) + return 0; + + mutex_lock(&power_gate->jpeg_gate_lock); + + if (atomic_read(&power_gate->jpeg_gated) ^ enable) + goto out; + + ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->jpeg_gated, !enable); + +out: + mutex_unlock(&power_gate->jpeg_gate_lock); + + return ret; +} + /** * smu_dpm_set_power_gate - power gate/ungate the specific IP block * @@ -650,6 +700,11 @@ static int smu_sw_init(void *handle) smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); + atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); + mutex_init(&smu->smu_power.power_gate.vcn_gate_lock); + mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock); + smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; @@ -1974,7 +2029,7 @@ int smu_read_sensor(struct smu_context *smu, *size = 4; break; case AMDGPU_PP_SENSOR_VCN_POWER_STATE: - *(uint32_t *)data = smu->smu_power.power_gate.vcn_gated ? 0 : 1; + *(uint32_t *)data = atomic_read(&smu->smu_power.power_gate.vcn_gated) ? 0: 1; *size = 4; break; case AMDGPU_PP_SENSOR_MIN_FAN_RPM: diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index e3a2d7f0aba15..e59e6fb6f0a80 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -1896,8 +1896,6 @@ static bool arcturus_is_dpm_running(struct smu_context *smu) static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -1908,7 +1906,6 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) return ret; } } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0); @@ -1917,7 +1914,6 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) return ret; } } - power_gate->vcn_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index ec2d2aa7f4ec5..23c2279bd5006 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -295,8 +295,10 @@ struct smu_dpm_context { struct smu_power_gate { bool uvd_gated; bool vce_gated; - bool vcn_gated; - bool jpeg_gated; + atomic_t vcn_gated; + atomic_t jpeg_gated; + struct mutex vcn_gate_lock; + struct mutex jpeg_gate_lock; }; struct smu_power_context { diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 8c45c472f7f2c..82659b781f05c 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -831,8 +831,6 @@ static int navi10_set_default_dpm_table(struct smu_context *smu) static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -842,14 +840,12 @@ static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } - power_gate->vcn_gated = true; } return ret; @@ -857,8 +853,6 @@ static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -867,14 +861,12 @@ static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 4c1a506c3c177..8a8e6033f71f9 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -479,8 +479,6 @@ static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -490,14 +488,12 @@ static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } - power_gate->vcn_gated = true; } return ret; @@ -505,8 +501,6 @@ static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -515,14 +509,12 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 2566ae5df64b8..bb756b4c284ed 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -815,10 +815,7 @@ static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu) static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; struct amdgpu_device *adev = smu->adev; - int ret = 0; if (enable) { @@ -834,7 +831,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl return ret; } } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); @@ -847,7 +843,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl return ret; } } - power_gate->vcn_gated = true; } return ret; @@ -855,8 +850,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -865,14 +858,12 @@ static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enab if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index d0deaefd3feb7..f1d8f247e5898 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -77,8 +77,6 @@ #define smu_get_dal_power_level(smu, clocks) smu_ppt_funcs(get_dal_power_level, 0, smu, clocks) #define smu_get_perf_level(smu, designation, level) smu_ppt_funcs(get_perf_level, 0, smu, designation, level) #define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks) -#define smu_dpm_set_vcn_enable(smu, enable) smu_ppt_funcs(dpm_set_vcn_enable, 0, smu, enable) -#define smu_dpm_set_jpeg_enable(smu, enable) smu_ppt_funcs(dpm_set_jpeg_enable, 0, smu, enable) #define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges) #define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) #define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) -- GitLab From 520f5e425a69417540b7563c266f773752dcea44 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 5 Aug 2020 17:24:41 +0800 Subject: [PATCH 0352/1494] drm/amd/powerplay: put VCN/JPEG into PG ungate state before dpm table setup(V3) As VCN related dpm table setup needs VCN be in PG ungate state. Same logics applies to JPEG. V2: fix paste typo V3: code cosmetic Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Matt Coffin <mcoffin13@gmail.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 85 +++++++++++++++++--- drivers/gpu/drm/amd/powerplay/smu_internal.h | 1 - 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 1b64ca9ecccb6..1ffacc712e53e 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -133,8 +133,8 @@ int smu_get_dpm_freq_range(struct smu_context *smu, return ret; } -static int smu_dpm_set_vcn_enable(struct smu_context *smu, - bool enable) +static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -143,23 +143,34 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu, if (!smu->ppt_funcs->dpm_set_vcn_enable) return 0; - mutex_lock(&power_gate->vcn_gate_lock); - if (atomic_read(&power_gate->vcn_gated) ^ enable) - goto out; + return 0; ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); if (!ret) atomic_set(&power_gate->vcn_gated, !enable); -out: + return ret; +} + +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->vcn_gate_lock); + + ret = smu_dpm_set_vcn_enable_locked(smu, enable); + mutex_unlock(&power_gate->vcn_gate_lock); return ret; } -static int smu_dpm_set_jpeg_enable(struct smu_context *smu, - bool enable) +static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -168,16 +179,27 @@ static int smu_dpm_set_jpeg_enable(struct smu_context *smu, if (!smu->ppt_funcs->dpm_set_jpeg_enable) return 0; - mutex_lock(&power_gate->jpeg_gate_lock); - if (atomic_read(&power_gate->jpeg_gated) ^ enable) - goto out; + return 0; ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); if (!ret) atomic_set(&power_gate->jpeg_gated, !enable); -out: + return ret; +} + +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->jpeg_gate_lock); + + ret = smu_dpm_set_jpeg_enable_locked(smu, enable); + mutex_unlock(&power_gate->jpeg_gate_lock); return ret; @@ -403,6 +425,45 @@ static int smu_early_init(void *handle) return smu_set_funcs(adev); } +static int smu_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int vcn_gate, jpeg_gate; + int ret = 0; + + if (!smu->ppt_funcs->set_default_dpm_table) + return 0; + + mutex_lock(&power_gate->vcn_gate_lock); + mutex_lock(&power_gate->jpeg_gate_lock); + + vcn_gate = atomic_read(&power_gate->vcn_gated); + jpeg_gate = atomic_read(&power_gate->jpeg_gated); + + ret = smu_dpm_set_vcn_enable_locked(smu, true); + if (ret) + goto err0_out; + + ret = smu_dpm_set_jpeg_enable_locked(smu, true); + if (ret) + goto err1_out; + + ret = smu->ppt_funcs->set_default_dpm_table(smu); + if (ret) + dev_err(smu->adev->dev, + "Failed to setup default dpm clock tables!\n"); + + smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate); +err1_out: + smu_dpm_set_vcn_enable_locked(smu, !vcn_gate); +err0_out: + mutex_unlock(&power_gate->jpeg_gate_lock); + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + static int smu_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index f1d8f247e5898..264073d4e2635 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -60,7 +60,6 @@ #define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) -#define smu_set_default_dpm_table(smu) smu_ppt_funcs(set_default_dpm_table, 0, smu) #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) #define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu) #define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu) -- GitLab From 94561899ddb0f89d7fd3fb58ee3ed6961ef048ad Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Tue, 4 Aug 2020 12:32:13 +0800 Subject: [PATCH 0353/1494] drm/amdgpu: unlock mutex on error Make sure to unlock the mutex when error happen v2: 1. correct syntax error in the commit comments 2. remove change-Id Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 92790db5edc02..9738dccb1c2c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -632,13 +632,14 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, } ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); + + up_read(&adev->reset_sem); + if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; } - up_read(&adev->reset_sem); - ret = dma_fence_wait(f, false); err_ib_sched: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 4e017f379eb67..67a756f4337bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -545,7 +545,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) } ret = amdgpu_xgmi_update_topology(hive, tmp_adev); if (ret) - goto exit; + goto exit_unlock; } /* get latest topology info for each device from psp */ @@ -558,7 +558,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) tmp_adev->gmc.xgmi.node_id, tmp_adev->gmc.xgmi.hive_id, ret); /* To do : continue with some node failed or disable the whole hive */ - goto exit; + goto exit_unlock; } } } @@ -566,7 +566,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) if (!ret) ret = amdgpu_xgmi_sysfs_add_dev_info(adev, hive); - +exit_unlock: mutex_unlock(&hive->hive_lock); exit: if (!ret) -- GitLab From 82c2454761298a2fdaade6a253a7b034b9cfa15d Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman <sandy.8925@gmail.com> Date: Thu, 6 Aug 2020 22:52:20 +0530 Subject: [PATCH 0354/1494] drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume Reproducing bug report here: After hibernating and resuming, DPM is not enabled. This remains the case even if you test hibernate using the steps here: https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html I debugged the problem, and figured out that in the file hardwaremanager.c, in the function, phm_enable_dynamic_state_management(), the check 'if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev) && adev->in_suspend)' returns true for the hibernate case, and false for the suspend case. This means that for the hibernate case, the AMDGPU driver doesn't enable DPM (even though it should) and simply returns from that function. In the suspend case, it goes ahead and enables DPM, even though it doesn't need to. I debugged further, and found out that in the case of suspend, for the CIK/Hawaii GPUs, smum_is_dpm_running(hwmgr) returns false, while in the case of hibernate, smum_is_dpm_running(hwmgr) returns true. For CIK, the ci_is_dpm_running() function calls the ci_is_smc_ram_running() function, which is ultimately used to determine if DPM is currently enabled or not, and this seems to provide the wrong answer. I've changed the ci_is_dpm_running() function to instead use the same method that some other AMD GPU chips do (e.g Fiji), which seems to read the voltage controller. I've tested on my R9 390 and it seems to work correctly for both suspend and hibernate use cases, and has been stable so far. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=208839 Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index 02159ca29fa29..c18169aa59ce5 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -2725,7 +2725,10 @@ static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) { - return ci_is_smc_ram_running(hwmgr); + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, + VOLTAGE_CONTROLLER_ON)) + ? true : false; } static int ci_smu_init(struct pp_hwmgr *hwmgr) -- GitLab From 87154ff86bf69ecf76600e56ecab0b79fc3f71ea Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Sun, 2 Aug 2020 09:43:59 -0700 Subject: [PATCH 0355/1494] drm: Remove unnecessary drm_panel_attach and drm_panel_detach These functions are now empty and no longer useful so remove the functions and their uses. Signed-off-by: Joe Perches <joe@perches.com> Cc: Bernard Zhao <bernard@vivo.com> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org>, Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Icenowy Zheng <icenowy@aosc.io>, Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Robert Chiras <robert.chiras@nxp.com> Cc: dri-devel@lists.freedesktop.org, Cc: linux-kernel@vger.kernel.org Cc: opensource.kernel@vivo.com Signed-off-by: Sam Ravnborg <sam@ravnborg.org> # Fixed build and a few warnings Link: https://patchwork.freedesktop.org/patch/msgid/9e13761020750b1ce2f1fabee23ef6e2a2942882.camel@perches.com --- .../drm/bridge/analogix/analogix-anx6345.c | 12 ------- .../drm/bridge/analogix/analogix_dp_core.c | 9 ----- drivers/gpu/drm/bridge/panel.c | 7 ---- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 3 -- drivers/gpu/drm/drm_panel.c | 36 ------------------- drivers/gpu/drm/exynos/exynos_drm_dpi.c | 8 ----- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 7 ++-- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 9 ----- drivers/gpu/drm/imx/imx-ldb.c | 10 ------ drivers/gpu/drm/imx/parallel-display.c | 6 ---- drivers/gpu/drm/mediatek/mtk_dsi.c | 14 -------- .../drm/msm/disp/mdp4/mdp4_lvds_connector.c | 7 +--- drivers/gpu/drm/msm/dsi/dsi_manager.c | 1 - drivers/gpu/drm/omapdrm/omap_drv.c | 17 --------- drivers/gpu/drm/rcar-du/rcar_lvds.c | 6 +--- drivers/gpu/drm/rockchip/rockchip_lvds.c | 9 ----- drivers/gpu/drm/sti/sti_dvo.c | 2 -- drivers/gpu/drm/sun4i/sun4i_lvds.c | 9 ----- drivers/gpu/drm/sun4i/sun4i_rgb.c | 9 ----- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 -- drivers/gpu/drm/tegra/dsi.c | 4 +-- drivers/gpu/drm/tegra/output.c | 10 ------ include/drm/drm_panel.h | 3 -- 23 files changed, 5 insertions(+), 196 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c index f082b4ed48783..d9164fab044d0 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c @@ -507,10 +507,6 @@ static const struct drm_connector_helper_funcs anx6345_connector_helper_funcs = static void anx6345_connector_destroy(struct drm_connector *connector) { - struct anx6345 *anx6345 = connector_to_anx6345(connector); - - if (anx6345->panel) - drm_panel_detach(anx6345->panel); drm_connector_cleanup(connector); } @@ -575,14 +571,6 @@ static int anx6345_bridge_attach(struct drm_bridge *bridge, return err; } - if (anx6345->panel) { - err = drm_panel_attach(anx6345->panel, &anx6345->connector); - if (err) { - DRM_ERROR("Failed to attach panel: %d\n", err); - return err; - } - } - return 0; } diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 76736fb8ed949..aa1bb86293fdf 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1265,14 +1265,6 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge, } } - if (dp->plat_data->panel) { - ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); - if (ret) { - DRM_ERROR("Failed to attach panel\n"); - return ret; - } - } - return 0; } @@ -1803,7 +1795,6 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); - drm_panel_detach(dp->plat_data->panel); } drm_dp_aux_unregister(&dp->aux); diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 1e63ed6b18aa4..0ddc37551194e 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -82,18 +82,11 @@ static int panel_bridge_attach(struct drm_bridge *bridge, drm_connector_attach_encoder(&panel_bridge->connector, bridge->encoder); - ret = drm_panel_attach(panel_bridge->panel, &panel_bridge->connector); - if (ret < 0) - return ret; - return 0; } static void panel_bridge_detach(struct drm_bridge *bridge) { - struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge); - - drm_panel_detach(panel_bridge->panel); } static void panel_bridge_pre_enable(struct drm_bridge *bridge) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 86b9f0f87a14b..454544e0da7de 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -394,9 +394,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge, } pdata->dsi = dsi; - /* attach panel to bridge */ - drm_panel_attach(pdata->panel, &pdata->connector); - return 0; err_dsi_attach: diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index b8e9abb537cfc..ba11c3641bf37 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -93,42 +93,6 @@ void drm_panel_remove(struct drm_panel *panel) } EXPORT_SYMBOL(drm_panel_remove); -/** - * drm_panel_attach - attach a panel to a connector - * @panel: DRM panel - * @connector: DRM connector - * - * After obtaining a pointer to a DRM panel a display driver calls this - * function to attach a panel to a connector. - * - * An error is returned if the panel is already attached to another connector. - * - * When unloading, the driver should detach from the panel by calling - * drm_panel_detach(). - * - * Return: 0 on success or a negative error code on failure. - */ -int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector) -{ - return 0; -} -EXPORT_SYMBOL(drm_panel_attach); - -/** - * drm_panel_detach - detach a panel from a connector - * @panel: DRM panel - * - * Detaches a panel from the connector it is attached to. If a panel is not - * attached to any connector this is effectively a no-op. - * - * This function should not be called by the panel device itself. It - * is only for the drm device that called drm_panel_attach(). - */ -void drm_panel_detach(struct drm_panel *panel) -{ -} -EXPORT_SYMBOL(drm_panel_detach); - /** * drm_panel_prepare - power on a panel * @panel: DRM panel diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c index 7ba5354e7d944..741323a2e6c3c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c @@ -42,11 +42,6 @@ static inline struct exynos_dpi *encoder_to_dpi(struct drm_encoder *e) static enum drm_connector_status exynos_dpi_detect(struct drm_connector *connector, bool force) { - struct exynos_dpi *ctx = connector_to_dpi(connector); - - if (ctx->panel) - drm_panel_attach(ctx->panel, &ctx->connector); - return connector_status_connected; } @@ -249,8 +244,5 @@ int exynos_dpi_remove(struct drm_encoder *encoder) exynos_dpi_disable(&ctx->encoder); - if (ctx->panel) - drm_panel_detach(ctx->panel); - return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index ee96a95fb6be5..db0eab53dcfea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1551,12 +1551,10 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, } dsi->panel = of_drm_find_panel(device->dev.of_node); - if (IS_ERR(dsi->panel)) { + if (IS_ERR(dsi->panel)) dsi->panel = NULL; - } else { - drm_panel_attach(dsi->panel, &dsi->connector); + else dsi->connector.status = connector_status_connected; - } } /* @@ -1596,7 +1594,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, if (dsi->panel) { mutex_lock(&drm->mode_config.mutex); exynos_dsi_disable(&dsi->encoder); - drm_panel_detach(dsi->panel); dsi->panel = NULL; dsi->connector.status = connector_status_disconnected; mutex_unlock(&drm->mode_config.mutex); diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 9b0c4736c21ae..4d4a715b429d1 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -40,10 +40,7 @@ int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector) { - struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector); - drm_connector_unregister(connector); - drm_panel_detach(fsl_con->panel); drm_connector_cleanup(connector); } @@ -101,12 +98,6 @@ static int fsl_dcu_attach_panel(struct fsl_dcu_drm_device *fsl_dev, if (ret < 0) goto err_sysfs; - ret = drm_panel_attach(panel, connector); - if (ret) { - dev_err(fsl_dev->dev, "failed to attach panel\n"); - goto err_sysfs; - } - return 0; err_sysfs: diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 66ea68e8da875..35a6bad7dcf8b 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -463,13 +463,6 @@ static int imx_ldb_register(struct drm_device *drm, drm_connector_attach_encoder(&imx_ldb_ch->connector, encoder); } - if (imx_ldb_ch->panel) { - ret = drm_panel_attach(imx_ldb_ch->panel, - &imx_ldb_ch->connector); - if (ret) - return ret; - } - return 0; } @@ -718,9 +711,6 @@ static void imx_ldb_unbind(struct device *dev, struct device *master, for (i = 0; i < 2; i++) { struct imx_ldb_channel *channel = &imx_ldb->channel[i]; - if (channel->panel) - drm_panel_detach(channel->panel); - kfree(channel->edid); i2c_put_adapter(channel->ddc); } diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index ac916c84a6318..cba2abbb420d7 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -298,9 +298,6 @@ static int imx_pd_register(struct drm_device *drm, DRM_MODE_CONNECTOR_DPI); } - if (imxpd->panel) - drm_panel_attach(imxpd->panel, &imxpd->connector); - if (imxpd->next_bridge) { ret = drm_bridge_attach(encoder, imxpd->next_bridge, &imxpd->bridge, 0); @@ -369,9 +366,6 @@ static void imx_pd_unbind(struct device *dev, struct device *master, { struct imx_parallel_display *imxpd = dev_get_drvdata(dev); - if (imxpd->panel) - drm_panel_detach(imxpd->panel); - kfree(imxpd->edid); } diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 270bf22c98feb..e4e56e53aeeac 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -861,19 +861,7 @@ static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi) dsi->conn.dpms = DRM_MODE_DPMS_OFF; drm_connector_attach_encoder(&dsi->conn, &dsi->encoder); - if (dsi->panel) { - ret = drm_panel_attach(dsi->panel, &dsi->conn); - if (ret) { - DRM_ERROR("Failed to attach panel to drm\n"); - goto err_connector_cleanup; - } - } - return 0; - -err_connector_cleanup: - drm_connector_cleanup(&dsi->conn); - return ret; } static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi) @@ -921,8 +909,6 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi) /* Skip connector cleanup if creation was delegated to the bridge */ if (dsi->conn.dev) drm_connector_cleanup(&dsi->conn); - if (dsi->panel) - drm_panel_detach(dsi->panel); } static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index c7df71e2fafca..7288041dd86ad 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -50,14 +50,9 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector) struct drm_panel *panel = mdp4_lvds_connector->panel; int ret = 0; - if (panel) { - drm_panel_attach(panel, connector); - + if (panel) ret = drm_panel_get_modes(panel, connector); - drm_panel_detach(panel); - } - return ret; } diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 4b363bd7ddfff..1d28dfba2c9bb 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -328,7 +328,6 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector) * In dual DSI mode, we have one connector that can be * attached to the drm_panel. */ - drm_panel_attach(panel, connector); num = drm_panel_get_modes(panel, connector); if (!num) return 0; diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 4526967978b7a..53d5e184ee77c 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -349,13 +349,6 @@ static int omap_modeset_init(struct drm_device *dev) drm_connector_attach_encoder(pipe->connector, encoder); - if (pipe->output->panel) { - ret = drm_panel_attach(pipe->output->panel, - pipe->connector); - if (ret < 0) - return ret; - } - crtc = omap_crtc_init(dev, pipe, priv->planes[i]); if (IS_ERR(crtc)) return PTR_ERR(crtc); @@ -394,18 +387,8 @@ static int omap_modeset_init(struct drm_device *dev) static void omap_modeset_fini(struct drm_device *ddev) { - struct omap_drm_private *priv = ddev->dev_private; - unsigned int i; - omap_drm_irq_uninstall(ddev); - for (i = 0; i < priv->num_pipes; i++) { - struct omap_drm_pipeline *pipe = &priv->pipes[i]; - - if (pipe->output->panel) - drm_panel_detach(pipe->output->panel); - } - drm_mode_config_cleanup(ddev); } diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index ab0d49618cf90..bced729a96fe8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -677,15 +677,11 @@ static int rcar_lvds_attach(struct drm_bridge *bridge, if (ret < 0) return ret; - return drm_panel_attach(lvds->panel, connector); + return 0; } static void rcar_lvds_detach(struct drm_bridge *bridge) { - struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); - - if (lvds->panel) - drm_panel_detach(lvds->panel); } static const struct drm_bridge_funcs rcar_lvds_bridge_ops = { diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 63f967902c2d8..f292c6a6e20fb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -634,13 +634,6 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master, "failed to attach encoder: %d\n", ret); goto err_free_connector; } - - ret = drm_panel_attach(lvds->panel, connector); - if (ret < 0) { - DRM_DEV_ERROR(drm_dev->dev, - "failed to attach panel: %d\n", ret); - goto err_free_connector; - } } else { ret = drm_bridge_attach(encoder, lvds->bridge, NULL, 0); if (ret) { @@ -676,8 +669,6 @@ static void rockchip_lvds_unbind(struct device *dev, struct device *master, encoder_funcs = lvds->soc_data->helper_funcs; encoder_funcs->disable(&lvds->encoder); - if (lvds->panel) - drm_panel_detach(lvds->panel); pm_runtime_disable(dev); drm_connector_cleanup(&lvds->connector); drm_encoder_cleanup(&lvds->encoder); diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index de4af7735c469..ddb4184f07264 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -389,8 +389,6 @@ sti_dvo_connector_detect(struct drm_connector *connector, bool force) dvo->panel = of_drm_find_panel(dvo->panel_node); if (IS_ERR(dvo->panel)) dvo->panel = NULL; - else - drm_panel_attach(dvo->panel, connector); } if (dvo->panel) diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c index ffda3184aa12a..d06dd313d3c01 100644 --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -54,9 +54,6 @@ static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { static void sun4i_lvds_connector_destroy(struct drm_connector *connector) { - struct sun4i_lvds *lvds = drm_connector_to_sun4i_lvds(connector); - - drm_panel_detach(lvds->panel); drm_connector_cleanup(connector); } @@ -141,12 +138,6 @@ int sun4i_lvds_init(struct drm_device *drm, struct sun4i_tcon *tcon) drm_connector_attach_encoder(&lvds->connector, &lvds->encoder); - - ret = drm_panel_attach(lvds->panel, &lvds->connector); - if (ret) { - dev_err(drm->dev, "Couldn't attach our panel\n"); - goto err_cleanup_connector; - } } if (bridge) { diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 5a7d43939ae67..23df1ec034162 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -145,9 +145,6 @@ static struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = { static void sun4i_rgb_connector_destroy(struct drm_connector *connector) { - struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector); - - drm_panel_detach(rgb->panel); drm_connector_cleanup(connector); } @@ -233,12 +230,6 @@ int sun4i_rgb_init(struct drm_device *drm, struct sun4i_tcon *tcon) drm_connector_attach_encoder(&rgb->connector, &rgb->encoder); - - ret = drm_panel_attach(rgb->panel, &rgb->connector); - if (ret) { - dev_err(drm->dev, "Couldn't attach our panel\n"); - goto err_cleanup_connector; - } } if (rgb->bridge) { diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index aa67cb037e9d1..a78aebfe773db 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -973,7 +973,6 @@ static int sun6i_dsi_attach(struct mipi_dsi_host *host, dsi->panel = panel; dsi->device = device; - drm_panel_attach(dsi->panel, &dsi->connector); drm_kms_helper_hotplug_event(dsi->drm); dev_info(host->dev, "Attached device %s\n", device->name); @@ -985,12 +984,10 @@ static int sun6i_dsi_detach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); - struct drm_panel *panel = dsi->panel; dsi->panel = NULL; dsi->device = NULL; - drm_panel_detach(panel); drm_kms_helper_hotplug_event(dsi->drm); return 0; diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 38beab9ab4f8c..37b89c396d3b6 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -1493,10 +1493,8 @@ static int tegra_dsi_host_attach(struct mipi_dsi_host *host, if (IS_ERR(output->panel)) output->panel = NULL; - if (output->panel && output->connector.dev) { - drm_panel_attach(output->panel, &output->connector); + if (output->panel && output->connector.dev) drm_helper_hpd_irq_event(output->connector.dev); - } } return 0; diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index e36e5e7c2f694..a3adb9e4debf5 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -179,13 +179,6 @@ void tegra_output_remove(struct tegra_output *output) int tegra_output_init(struct drm_device *drm, struct tegra_output *output) { int connector_type; - int err; - - if (output->panel) { - err = drm_panel_attach(output->panel, &output->connector); - if (err < 0) - return err; - } /* * The connector is now registered and ready to receive hotplug events @@ -220,9 +213,6 @@ void tegra_output_exit(struct tegra_output *output) */ if (output->hpd_gpio) disable_irq(output->hpd_irq); - - if (output->panel) - drm_panel_detach(output->panel); } void tegra_output_find_possible_crtcs(struct tegra_output *output, diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index ff066524cb707..45a1b5a2275db 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -178,9 +178,6 @@ void drm_panel_init(struct drm_panel *panel, struct device *dev, void drm_panel_add(struct drm_panel *panel); void drm_panel_remove(struct drm_panel *panel); -int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); -void drm_panel_detach(struct drm_panel *panel); - int drm_panel_prepare(struct drm_panel *panel); int drm_panel_unprepare(struct drm_panel *panel); -- GitLab From 4f297b9c82e1a43d2c02a687aa134e1b7318b7e6 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Fri, 7 Aug 2020 09:04:50 +1000 Subject: [PATCH 0356/1494] drm/amdgpu/ttm: move vram/gtt mgr allocations to mman. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Christian suggested this and it makes sense. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200806233459.4057784-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 21 ++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 19 ++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 24 ++++---------------- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index c847a5fe94c92..010518148ef89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -24,13 +24,6 @@ #include "amdgpu.h" -struct amdgpu_gtt_mgr { - struct ttm_resource_manager manager; - struct drm_mm mm; - spinlock_t lock; - atomic64_t available; -}; - static inline struct amdgpu_gtt_mgr *to_gtt_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_gtt_mgr, manager); @@ -93,16 +86,11 @@ static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func; */ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) { - struct ttm_resource_manager *man; - struct amdgpu_gtt_mgr *mgr; + struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr; + struct ttm_resource_manager *man = &mgr->manager; uint64_t start, size; int ret; - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (!mgr) - return -ENOMEM; - - man = &mgr->manager; man->use_tt = true; man->func = &amdgpu_gtt_mgr_func; man->available_caching = TTM_PL_MASK_CACHING; @@ -142,8 +130,8 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) */ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) { - struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); - struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); + struct amdgpu_gtt_mgr *mgr = &adev->mman.gtt_mgr; + struct ttm_resource_manager *man = &mgr->manager; int ret; ttm_resource_manager_set_used(man, false); @@ -161,7 +149,6 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_TT, NULL); - kfree(mgr); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 433156c2e8fbb..67022ed6c6431 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -41,6 +41,22 @@ #define AMDGPU_POISON 0xd0bed0be +struct amdgpu_vram_mgr { + struct ttm_resource_manager manager; + struct drm_mm mm; + spinlock_t lock; + atomic64_t usage; + atomic64_t vis_usage; + struct amdgpu_device *adev; +}; + +struct amdgpu_gtt_mgr { + struct ttm_resource_manager manager; + struct drm_mm mm; + spinlock_t lock; + atomic64_t available; +}; + struct amdgpu_mman { struct ttm_bo_device bdev; bool mem_global_referenced; @@ -59,6 +75,9 @@ struct amdgpu_mman { struct mutex gtt_window_lock; /* Scheduler entity for buffer moves */ struct drm_sched_entity entity; + + struct amdgpu_vram_mgr vram_mgr; + struct amdgpu_gtt_mgr gtt_mgr; }; struct amdgpu_copy_mem { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 895634cbf999c..a41a8abc99273 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -28,15 +28,6 @@ #include "amdgpu_atomfirmware.h" #include "atom.h" -struct amdgpu_vram_mgr { - struct ttm_resource_manager manager; - struct drm_mm mm; - spinlock_t lock; - atomic64_t usage; - atomic64_t vis_usage; - struct amdgpu_device *adev; -}; - static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_vram_mgr, manager); @@ -177,16 +168,10 @@ static const struct ttm_resource_manager_func amdgpu_vram_mgr_func; */ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) { - struct ttm_resource_manager *man; - struct amdgpu_vram_mgr *mgr; + struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr; + struct ttm_resource_manager *man = &mgr->manager; int ret; - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); - if (!mgr) - return -ENOMEM; - - man = &mgr->manager; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; @@ -219,8 +204,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) */ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) { - struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); + struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr; + struct ttm_resource_manager *man = &mgr->manager; int ret; ttm_resource_manager_set_used(man, false); @@ -237,7 +222,6 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) ttm_resource_manager_cleanup(man); ttm_set_driver_manager(&adev->mman.bdev, TTM_PL_VRAM, NULL); - kfree(mgr); } /** -- GitLab From 373627930f0208c9a8ddc96510583db532c3e354 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Fri, 7 Aug 2020 09:18:17 +1000 Subject: [PATCH 0357/1494] drm/amdgpu/ttm: drop the adev link from vram mgr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need for that now since it's embedded. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200806233459.4057784-3-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 11 +++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 67022ed6c6431..7ba2be37e6ba5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -47,7 +47,6 @@ struct amdgpu_vram_mgr { spinlock_t lock; atomic64_t usage; atomic64_t vis_usage; - struct amdgpu_device *adev; }; struct amdgpu_gtt_mgr { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index a41a8abc99273..7882efd275d19 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -33,6 +33,11 @@ static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_resource_manager *m return container_of(man, struct amdgpu_vram_mgr, manager); } +static inline struct amdgpu_device *to_amdgpu_device(struct amdgpu_vram_mgr *mgr) +{ + return container_of(mgr, struct amdgpu_device, mman.vram_mgr); +} + /** * DOC: mem_info_vram_total * @@ -182,8 +187,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) drm_mm_init(&mgr->mm, 0, man->size); spin_lock_init(&mgr->lock); - mgr->adev = adev; - /* Add the two VRAM-related sysfs files */ ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); if (ret) @@ -311,7 +314,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, struct ttm_resource *mem) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); - struct amdgpu_device *adev = mgr->adev; + struct amdgpu_device *adev = to_amdgpu_device(mgr); struct drm_mm *mm = &mgr->mm; struct drm_mm_node *nodes; enum drm_mm_insert_mode mode; @@ -429,7 +432,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, struct ttm_resource *mem) { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); - struct amdgpu_device *adev = mgr->adev; + struct amdgpu_device *adev = to_amdgpu_device(mgr); struct drm_mm_node *nodes = mem->mm_node; uint64_t usage = 0, vis_usage = 0; unsigned pages = mem->num_pages; -- GitLab From e4fbdd8b5d5a5121a3407ed53d8e601fa941b1bf Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 5 Aug 2020 13:42:27 +0100 Subject: [PATCH 0358/1494] drm/gma500: fix spelling mistake "pannel" -> "panel" There a handful of spelling mistakes. fix them. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200805124227.20005-1-colin.king@canonical.com --- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 4 ++-- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index f350ac1ead182..2f3486f32fedc 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -366,7 +366,7 @@ static enum drm_mode_status mdfld_dsi_connector_mode_valid(struct drm_connector /** * FIXME: current DC has no fitting unit, reject any mode setting * request - * Will figure out a way to do up-scaling(pannel fitting) later. + * Will figure out a way to do up-scaling(panel fitting) later. **/ if (fixed_mode) { if (mode->hdisplay != fixed_mode->hdisplay) @@ -531,7 +531,7 @@ void mdfld_dsi_output_init(struct drm_device *dev, dsi_config->connector = dsi_connector; if (!dsi_config->fixed_mode) { - DRM_ERROR("No pannel fixed mode was found\n"); + DRM_ERROR("No panel fixed mode was found\n"); goto dsi_init_err0; } diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 06e44f47e73ed..907f966d6f221 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -125,7 +125,7 @@ struct psb_intel_sdvo { bool is_lvds; /** - * This is sdvo fixed pannel mode pointer + * This is sdvo fixed panel mode pointer */ struct drm_display_mode *sdvo_lvds_fixed_mode; -- GitLab From 5bd858d7bfd2746df34f54cec3b6d0c36a70bdd7 Mon Sep 17 00:00:00 2001 From: Melissa Wen <melissa.srw@gmail.com> Date: Sat, 8 Aug 2020 09:09:00 -0300 Subject: [PATCH 0359/1494] drm/vkms: guarantee vblank when capturing crc VKMS needs vblank interrupts enabled to capture CRC. When vblank is disabled, tests like kms_cursor_crc and kms_pipe_crc_basic getting stuck waiting for a capture that will not occur until vkms wakes up. This patch adds a helper to set composer and ensure that vblank remains enabled as long as the CRC capture is needed. It clears the execution of the following kms_cursor_crc subtests: 1. pipe-A-cursor-[size,alpha-opaque, NxN-(on-screen, off-screen, sliding, random, fast-moving])] - successful when running individually. 2. pipe-A-cursor-dpms passes again 3. pipe-A-cursor-suspend also passes The issue was initially tracked in the sequential execution of IGT kms_cursor_crc subtests: when running the test sequence or one of its subtests twice, the odd execs complete and the pairs get stuck in an endless wait. In the IGT code, calling a wait_for_vblank on preparing for CRC capture prevented the busy-wait. But the problem persisted in the pipe-A-cursor-dpms and -suspend subtests. Checking the history, the pipe-A-cursor-dpms subtest was successful when, in vkms_atomic_commit_tail, instead of using the flip_done op, it used wait_for_vblanks. Another way to prevent blocking was wait_one_vblank when enabling crtc. However, in both cases, pipe-A-cursor-suspend persisted blocking in the 2nd start of CRC capture, which may indicate that something got stuck in the step of CRC setup. Indeed, wait_one_vblank in the crc setup was able to sync things and free all kms_cursor_crc subtests. Besides, other alternatives to force enabling vblanks or prevent disabling them such as calling drm_crtc_put_vblank or modeset_enables before commit_planes + offdelay = 0, also unlock all subtests executions. Finally, due to vkms's dependence on vblank interruptions to perform tasks, this patch uses refcount to ensure that vblanks happen when enabling composer and while crc capture is needed. Cc: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Cc: Haneen Mohammed <hamohammed.sa@gmail.com> v2: - extract a vkms_set_composer helper - fix vblank refcounting for the disabling case v3: - make the vkms_set_composer helper static - review the credit tags Co-debugged-by: Sidong Yang <realwakka@gmail.com> Signed-off-by: Sidong Yang <realwakka@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> [danvet: add changelog back in] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200808120900.pudwwrfz44g3rqx7@smtp.gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index b8b060354667e..4f3b07a32b602 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -233,6 +233,22 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } +static void vkms_set_composer(struct vkms_output *out, bool enabled) +{ + bool old_enabled; + + if (enabled) + drm_crtc_vblank_get(&out->crtc); + + spin_lock_irq(&out->lock); + old_enabled = out->composer_enabled; + out->composer_enabled = enabled; + spin_unlock_irq(&out->lock); + + if (old_enabled) + drm_crtc_vblank_put(&out->crtc); +} + int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) { struct vkms_output *out = drm_crtc_to_vkms_output(crtc); @@ -241,9 +257,7 @@ int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) ret = vkms_crc_parse_source(src_name, &enabled); - spin_lock_irq(&out->lock); - out->composer_enabled = enabled; - spin_unlock_irq(&out->lock); + vkms_set_composer(out, enabled); return ret; } -- GitLab From 57fb54082d5d14512dfd21bc39d91945d3ad1ee9 Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 10 Aug 2020 20:59:42 +0800 Subject: [PATCH 0360/1494] drm/vgem: add missing platform_device_unregister() in vgem_init() When vgem_init() get into out_put, the unregister call of vgem_device->platform is missing. So add it before return. Fixes: 363de9e7d4f6 ("drm/vgem: Use drmm_add_final_kfree") Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200810125942.186637-1-miaoqinglang@huawei.com --- drivers/gpu/drm/vgem/vgem_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index a775feda1cc73..313339bbff901 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -471,8 +471,8 @@ static int __init vgem_init(void) out_put: drm_dev_put(&vgem_device->drm); + platform_device_unregister(vgem_device->platform); return ret; - out_unregister: platform_device_unregister(vgem_device->platform); out_free: -- GitLab From 7995bd13296111d672d8c5959f5e81dbbbda5286 Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 10 Aug 2020 21:00:11 +0800 Subject: [PATCH 0361/1494] drm/vkms: add missing platform_device_unregister() in vkms_init() When vkms_init() get into out_put, the unregister call of vkms_device->platform is missing. So add it before return. Fixes: ac19f140bc27 ("drm/vkms: Use drmm_add_final_kfree") Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200810130011.187691-1-miaoqinglang@huawei.com --- drivers/gpu/drm/vkms/vkms_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 57a8a397d5e84..83dd5567de8b5 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -190,8 +190,8 @@ static int __init vkms_init(void) out_put: drm_dev_put(&vkms_device->drm); + platform_device_unregister(vkms_device->platform); return ret; - out_unregister: platform_device_unregister(vkms_device->platform); out_free: -- GitLab From ad28cd694293eff7322974d071af6fbb1e59e2c6 Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 10 Aug 2020 20:59:31 +0800 Subject: [PATCH 0362/1494] drm/v3d: convert to use module_platform_driver Get rid of boilerplate code by using module_platform_driver macro for v3d_drm. Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200810125931.186456-1-miaoqinglang@huawei.com --- drivers/gpu/drm/v3d/v3d_drv.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 82a7dfdd14c2a..9f7c261938312 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -358,18 +358,7 @@ static struct platform_driver v3d_platform_driver = { }, }; -static int __init v3d_drm_register(void) -{ - return platform_driver_register(&v3d_platform_driver); -} - -static void __exit v3d_drm_unregister(void) -{ - platform_driver_unregister(&v3d_platform_driver); -} - -module_init(v3d_drm_register); -module_exit(v3d_drm_unregister); +module_platform_driver(v3d_platform_driver); MODULE_ALIAS("platform:v3d-drm"); MODULE_DESCRIPTION("Broadcom V3D DRM Driver"); -- GitLab From 8b0d47e879b8feb1e00a7f1a8da772f8c5cf984b Mon Sep 17 00:00:00 2001 From: Vinay Simha BN <simhavcs@gmail.com> Date: Fri, 10 Jul 2020 19:11:27 +0530 Subject: [PATCH 0363/1494] dt-binding: Add DSI/LVDS TC358775 bridge bindings - license modified to (GPL-2.0-only OR BSD-2-Clause) - single-link and dual-link lvds description and examples are added - proper indentation - VESA/JEIDA formats picked from panel-lvds dts - dsi data-lanes property removed, it will be picked from dsi0 ports - dual-link lvds port added and implemented - converted from .txt to .yaml Signed-off-by: Vinay Simha BN <simhavcs@gmail.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Sam Ravnborg <sam.ravnborg@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/1594388491-15129-1-git-send-email-simhavcs@gmail.com --- .../display/bridge/toshiba,tc358775.yaml | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml new file mode 100644 index 0000000000000..31f085d8ab13e --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml @@ -0,0 +1,215 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/toshiba,tc358775.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Toshiba TC358775 DSI to LVDS bridge bindings + +maintainers: + - Vinay Simha BN <simhavcs@gmail.com> + +description: | + This binding supports DSI to LVDS bridge TC358775 + + MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane. + Video frame size: + Up to 1600x1200 24-bit/pixel resolution for single-link LVDS display panel + limited by 135 MHz LVDS speed + Up to WUXGA (1920x1200 24-bit pixels) resolution for dual-link LVDS display + panel, limited by 270 MHz LVDS speed. + +properties: + compatible: + const: toshiba,tc358775 + + reg: + maxItems: 1 + description: i2c address of the bridge, 0x0f + + vdd-supply: + maxItems: 1 + description: 1.2V LVDS Power Supply + + vddio-supply: + maxItems: 1 + description: 1.8V IO Power Supply + + stby-gpios: + maxItems: 1 + description: Standby pin, Low active + + reset-gpios: + maxItems: 1 + description: Hardware reset, Low active + + ports: + type: object + description: + A node containing input and output port nodes with endpoint definitions + as documented in + Documentation/devicetree/bindings/media/video-interfaces.txt + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + port@0: + type: object + description: | + DSI Input. The remote endpoint phandle should be a + reference to a valid mipi_dsi_host device node. + + port@1: + type: object + description: | + Video port for LVDS output (panel or connector). + + port@2: + type: object + description: | + Video port for Dual link LVDS output (panel or connector). + + required: + - port@0 + - port@1 + +required: + - compatible + - reg + - vdd-supply + - vddio-supply + - stby-gpios + - reset-gpios + - ports + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + /* For single-link LVDS display panel */ + + i2c@78b8000 { + /* On High speed expansion */ + label = "HS-I2C2"; + reg = <0x078b8000 0x500>; + clock-frequency = <400000>; /* fastmode operation */ + #address-cells = <1>; + #size-cells = <0>; + + tc_bridge: bridge@f { + compatible = "toshiba,tc358775"; + reg = <0x0f>; + + vdd-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; + + stby-gpios = <&msmgpio 99 GPIO_ACTIVE_LOW>; + reset-gpios = <&msmgpio 72 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + d2l_in_test: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + lvds_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + }; + }; + + dsi@1a98000 { + reg = <0x1a98000 0x25c>; + reg-names = "dsi_ctrl"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@1 { + reg = <1>; + dsi0_out: endpoint { + remote-endpoint = <&d2l_in_test>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; + + - | + /* For dual-link LVDS display panel */ + + i2c@78b8000 { + /* On High speed expansion */ + label = "HS-I2C2"; + reg = <0x078b8000 0x500>; + clock-frequency = <400000>; /* fastmode operation */ + #address-cells = <1>; + #size-cells = <0>; + + tc_bridge_dual: bridge@f { + compatible = "toshiba,tc358775"; + reg = <0x0f>; + + vdd-supply = <&pm8916_l2>; + vddio-supply = <&pm8916_l6>; + + stby-gpios = <&msmgpio 99 GPIO_ACTIVE_LOW>; + reset-gpios = <&msmgpio 72 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + d2l_in_dual: endpoint { + remote-endpoint = <&dsi0_out_dual>; + }; + }; + + port@1 { + reg = <1>; + lvds0_out: endpoint { + remote-endpoint = <&panel_in0>; + }; + }; + + port@2 { + reg = <2>; + lvds1_out: endpoint { + remote-endpoint = <&panel_in1>; + }; + }; + }; + }; + }; + + dsi@1a98000 { + reg = <0x1a98000 0x25c>; + reg-names = "dsi_ctrl"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@1 { + reg = <1>; + dsi0_out_dual: endpoint { + remote-endpoint = <&d2l_in_dual>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; +... -- GitLab From b26975593b17c2c7188b96dba6fe9fff14480538 Mon Sep 17 00:00:00 2001 From: Vinay Simha BN <simhavcs@gmail.com> Date: Fri, 10 Jul 2020 19:11:28 +0530 Subject: [PATCH 0364/1494] display/drm/bridge: TC358775 DSI/LVDS driver This driver is tested with two panels individually with Apq8016-IFC6309 board https://www.inforcecomputing.com/products/single-board-computers-sbc/qualcomm-snapdragon-410-inforce-6309-micro-sbc 1. 1366x768@60 auo,b101xtn01 data-mapping = "jeida-24" 2. 800x480@60 innolux,at070tn92 data-mapping = "vesa-24" - power off sequence in proper order - put_unaligned_be16, put_unaligned_le32 macros used - static function for mode_valid - len initialized - MODE_CLOCK_HIGH handled properly - bus_formats handled in mode_valid - GENMASK and FIELD_PREP used - Kconfig proper indentation - error handling endpoint data-lanes - check for bus_formats unsupported - display_timings naming local variables - help modified - ~vsdelay dynamic value set based on the calculation of dsi speed, output speed, blanking - panel->connector_type removed - dual port implemented - devm_drm_panel_bridge_add method used instead of panel description modified - regulator enable and disable with proper orders and delays as per the spec - removed drm_connector_status - added bus_formats - mdelay to usleep_range - magic number to macros for CLRSI and mux registers description modified - replaced u32 instead of uint32_t - updated alphabetic order of headers - added SPDX identifier license Signed-off-by: Vinay Simha BN <simhavcs@gmail.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam.ravnborg@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/1594388491-15129-2-git-send-email-simhavcs@gmail.com --- drivers/gpu/drm/bridge/Kconfig | 10 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/tc358775.c | 749 ++++++++++++++++++++++++++++++ 3 files changed, 760 insertions(+) create mode 100644 drivers/gpu/drm/bridge/tc358775.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c7f0dacfb57aa..e8672cfa2a2f7 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -194,6 +194,16 @@ config DRM_TOSHIBA_TC358768 help Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver. +config DRM_TOSHIBA_TC358775 + tristate "Toshiba TC358775 DSI/LVDS bridge" + depends on OF + select DRM_KMS_HELPER + select REGMAP_I2C + select DRM_PANEL + select DRM_MIPI_DSI + help + Toshiba TC358775 DSI/LVDS bridge chip driver. + config DRM_TI_TFP410 tristate "TI TFP410 DVI/HDMI bridge" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 7d7c123a95e43..5f65f3d212212 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o obj-$(CONFIG_DRM_TOSHIBA_TC358764) += tc358764.o obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o obj-$(CONFIG_DRM_TOSHIBA_TC358768) += tc358768.o +obj-$(CONFIG_DRM_TOSHIBA_TC358775) += tc358775.o obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/ obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c new file mode 100644 index 0000000000000..7da15cd71f49b --- /dev/null +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -0,0 +1,749 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TC358775 DSI to LVDS bridge driver + * + * Copyright (C) 2020 SMART Wireless Computing + * Author: Vinay Simha BN <simhavcs@gmail.com> + * + */ +/* #define DEBUG */ +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +#include <asm/unaligned.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + +#define FLD_VAL(val, start, end) FIELD_PREP(GENMASK(start, end), val) + +/* Registers */ + +/* DSI D-PHY Layer Registers */ +#define D0W_DPHYCONTTX 0x0004 /* Data Lane 0 DPHY Tx Control */ +#define CLW_DPHYCONTRX 0x0020 /* Clock Lane DPHY Rx Control */ +#define D0W_DPHYCONTRX 0x0024 /* Data Lane 0 DPHY Rx Control */ +#define D1W_DPHYCONTRX 0x0028 /* Data Lane 1 DPHY Rx Control */ +#define D2W_DPHYCONTRX 0x002C /* Data Lane 2 DPHY Rx Control */ +#define D3W_DPHYCONTRX 0x0030 /* Data Lane 3 DPHY Rx Control */ +#define COM_DPHYCONTRX 0x0038 /* DPHY Rx Common Control */ +#define CLW_CNTRL 0x0040 /* Clock Lane Control */ +#define D0W_CNTRL 0x0044 /* Data Lane 0 Control */ +#define D1W_CNTRL 0x0048 /* Data Lane 1 Control */ +#define D2W_CNTRL 0x004C /* Data Lane 2 Control */ +#define D3W_CNTRL 0x0050 /* Data Lane 3 Control */ +#define DFTMODE_CNTRL 0x0054 /* DFT Mode Control */ + +/* DSI PPI Layer Registers */ +#define PPI_STARTPPI 0x0104 /* START control bit of PPI-TX function. */ +#define PPI_START_FUNCTION 1 + +#define PPI_BUSYPPI 0x0108 +#define PPI_LINEINITCNT 0x0110 /* Line Initialization Wait Counter */ +#define PPI_LPTXTIMECNT 0x0114 +#define PPI_LANEENABLE 0x0134 /* Enables each lane at the PPI layer. */ +#define PPI_TX_RX_TA 0x013C /* DSI Bus Turn Around timing parameters */ + +/* Analog timer function enable */ +#define PPI_CLS_ATMR 0x0140 /* Delay for Clock Lane in LPRX */ +#define PPI_D0S_ATMR 0x0144 /* Delay for Data Lane 0 in LPRX */ +#define PPI_D1S_ATMR 0x0148 /* Delay for Data Lane 1 in LPRX */ +#define PPI_D2S_ATMR 0x014C /* Delay for Data Lane 2 in LPRX */ +#define PPI_D3S_ATMR 0x0150 /* Delay for Data Lane 3 in LPRX */ + +#define PPI_D0S_CLRSIPOCOUNT 0x0164 /* For lane 0 */ +#define PPI_D1S_CLRSIPOCOUNT 0x0168 /* For lane 1 */ +#define PPI_D2S_CLRSIPOCOUNT 0x016C /* For lane 2 */ +#define PPI_D3S_CLRSIPOCOUNT 0x0170 /* For lane 3 */ + +#define CLS_PRE 0x0180 /* Digital Counter inside of PHY IO */ +#define D0S_PRE 0x0184 /* Digital Counter inside of PHY IO */ +#define D1S_PRE 0x0188 /* Digital Counter inside of PHY IO */ +#define D2S_PRE 0x018C /* Digital Counter inside of PHY IO */ +#define D3S_PRE 0x0190 /* Digital Counter inside of PHY IO */ +#define CLS_PREP 0x01A0 /* Digital Counter inside of PHY IO */ +#define D0S_PREP 0x01A4 /* Digital Counter inside of PHY IO */ +#define D1S_PREP 0x01A8 /* Digital Counter inside of PHY IO */ +#define D2S_PREP 0x01AC /* Digital Counter inside of PHY IO */ +#define D3S_PREP 0x01B0 /* Digital Counter inside of PHY IO */ +#define CLS_ZERO 0x01C0 /* Digital Counter inside of PHY IO */ +#define D0S_ZERO 0x01C4 /* Digital Counter inside of PHY IO */ +#define D1S_ZERO 0x01C8 /* Digital Counter inside of PHY IO */ +#define D2S_ZERO 0x01CC /* Digital Counter inside of PHY IO */ +#define D3S_ZERO 0x01D0 /* Digital Counter inside of PHY IO */ + +#define PPI_CLRFLG 0x01E0 /* PRE Counters has reached set values */ +#define PPI_CLRSIPO 0x01E4 /* Clear SIPO values, Slave mode use only. */ +#define HSTIMEOUT 0x01F0 /* HS Rx Time Out Counter */ +#define HSTIMEOUTENABLE 0x01F4 /* Enable HS Rx Time Out Counter */ +#define DSI_STARTDSI 0x0204 /* START control bit of DSI-TX function */ +#define DSI_RX_START 1 + +#define DSI_BUSYDSI 0x0208 +#define DSI_LANEENABLE 0x0210 /* Enables each lane at the Protocol layer. */ +#define DSI_LANESTATUS0 0x0214 /* Displays lane is in HS RX mode. */ +#define DSI_LANESTATUS1 0x0218 /* Displays lane is in ULPS or STOP state */ + +#define DSI_INTSTATUS 0x0220 /* Interrupt Status */ +#define DSI_INTMASK 0x0224 /* Interrupt Mask */ +#define DSI_INTCLR 0x0228 /* Interrupt Clear */ +#define DSI_LPTXTO 0x0230 /* Low Power Tx Time Out Counter */ + +#define DSIERRCNT 0x0300 /* DSI Error Count */ +#define APLCTRL 0x0400 /* Application Layer Control */ +#define RDPKTLN 0x0404 /* Command Read Packet Length */ + +#define VPCTRL 0x0450 /* Video Path Control */ +#define HTIM1 0x0454 /* Horizontal Timing Control 1 */ +#define HTIM2 0x0458 /* Horizontal Timing Control 2 */ +#define VTIM1 0x045C /* Vertical Timing Control 1 */ +#define VTIM2 0x0460 /* Vertical Timing Control 2 */ +#define VFUEN 0x0464 /* Video Frame Timing Update Enable */ +#define VFUEN_EN BIT(0) /* Upload Enable */ + +/* Mux Input Select for LVDS LINK Input */ +#define LV_MX0003 0x0480 /* Bit 0 to 3 */ +#define LV_MX0407 0x0484 /* Bit 4 to 7 */ +#define LV_MX0811 0x0488 /* Bit 8 to 11 */ +#define LV_MX1215 0x048C /* Bit 12 to 15 */ +#define LV_MX1619 0x0490 /* Bit 16 to 19 */ +#define LV_MX2023 0x0494 /* Bit 20 to 23 */ +#define LV_MX2427 0x0498 /* Bit 24 to 27 */ +#define LV_MX(b0, b1, b2, b3) (FLD_VAL(b0, 4, 0) | FLD_VAL(b1, 12, 8) | \ + FLD_VAL(b2, 20, 16) | FLD_VAL(b3, 28, 24)) + +/* Input bit numbers used in mux registers */ +enum { + LVI_R0, + LVI_R1, + LVI_R2, + LVI_R3, + LVI_R4, + LVI_R5, + LVI_R6, + LVI_R7, + LVI_G0, + LVI_G1, + LVI_G2, + LVI_G3, + LVI_G4, + LVI_G5, + LVI_G6, + LVI_G7, + LVI_B0, + LVI_B1, + LVI_B2, + LVI_B3, + LVI_B4, + LVI_B5, + LVI_B6, + LVI_B7, + LVI_HS, + LVI_VS, + LVI_DE, + LVI_L0 +}; + +#define LVCFG 0x049C /* LVDS Configuration */ +#define LVPHY0 0x04A0 /* LVDS PHY 0 */ +#define LV_PHY0_RST(v) FLD_VAL(v, 22, 22) /* PHY reset */ +#define LV_PHY0_IS(v) FLD_VAL(v, 15, 14) +#define LV_PHY0_ND(v) FLD_VAL(v, 4, 0) /* Frequency range select */ +#define LV_PHY0_PRBS_ON(v) FLD_VAL(v, 20, 16) /* Clock/Data Flag pins */ + +#define LVPHY1 0x04A4 /* LVDS PHY 1 */ +#define SYSSTAT 0x0500 /* System Status */ +#define SYSRST 0x0504 /* System Reset */ + +#define SYS_RST_I2CS BIT(0) /* Reset I2C-Slave controller */ +#define SYS_RST_I2CM BIT(1) /* Reset I2C-Master controller */ +#define SYS_RST_LCD BIT(2) /* Reset LCD controller */ +#define SYS_RST_BM BIT(3) /* Reset Bus Management controller */ +#define SYS_RST_DSIRX BIT(4) /* Reset DSI-RX and App controller */ +#define SYS_RST_REG BIT(5) /* Reset Register module */ + +/* GPIO Registers */ +#define GPIOC 0x0520 /* GPIO Control */ +#define GPIOO 0x0524 /* GPIO Output */ +#define GPIOI 0x0528 /* GPIO Input */ + +/* I2C Registers */ +#define I2CTIMCTRL 0x0540 /* I2C IF Timing and Enable Control */ +#define I2CMADDR 0x0544 /* I2C Master Addressing */ +#define WDATAQ 0x0548 /* Write Data Queue */ +#define RDATAQ 0x054C /* Read Data Queue */ + +/* Chip ID and Revision ID Register */ +#define IDREG 0x0580 + +#define LPX_PERIOD 4 +#define TTA_GET 0x40000 +#define TTA_SURE 6 +#define SINGLE_LINK 1 +#define DUAL_LINK 2 + +#define TC358775XBG_ID 0x00007500 + +/* Debug Registers */ +#define DEBUG00 0x05A0 /* Debug */ +#define DEBUG01 0x05A4 /* LVDS Data */ + +#define DSI_CLEN_BIT BIT(0) +#define DIVIDE_BY_3 3 /* PCLK=DCLK/3 */ +#define DIVIDE_BY_6 6 /* PCLK=DCLK/6 */ +#define LVCFG_LVEN_BIT BIT(0) + +#define L0EN BIT(1) + +#define TC358775_VPCTRL_VSDELAY__MASK 0x3FF00000 +#define TC358775_VPCTRL_VSDELAY__SHIFT 20 +static inline u32 TC358775_VPCTRL_VSDELAY(uint32_t val) +{ + return ((val) << TC358775_VPCTRL_VSDELAY__SHIFT) & + TC358775_VPCTRL_VSDELAY__MASK; +} + +#define TC358775_VPCTRL_OPXLFMT__MASK 0x00000100 +#define TC358775_VPCTRL_OPXLFMT__SHIFT 8 +static inline u32 TC358775_VPCTRL_OPXLFMT(uint32_t val) +{ + return ((val) << TC358775_VPCTRL_OPXLFMT__SHIFT) & + TC358775_VPCTRL_OPXLFMT__MASK; +} + +#define TC358775_VPCTRL_MSF__MASK 0x00000001 +#define TC358775_VPCTRL_MSF__SHIFT 0 +static inline u32 TC358775_VPCTRL_MSF(uint32_t val) +{ + return ((val) << TC358775_VPCTRL_MSF__SHIFT) & + TC358775_VPCTRL_MSF__MASK; +} + +#define TC358775_LVCFG_PCLKDIV__MASK 0x000000f0 +#define TC358775_LVCFG_PCLKDIV__SHIFT 4 +static inline u32 TC358775_LVCFG_PCLKDIV(uint32_t val) +{ + return ((val) << TC358775_LVCFG_PCLKDIV__SHIFT) & + TC358775_LVCFG_PCLKDIV__MASK; +} + +#define TC358775_LVCFG_LVDLINK__MASK 0x00000002 +#define TC358775_LVCFG_LVDLINK__SHIFT 0 +static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val) +{ + return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) & + TC358775_LVCFG_LVDLINK__MASK; +} + +enum tc358775_ports { + TC358775_DSI_IN, + TC358775_LVDS_OUT0, + TC358775_LVDS_OUT1, +}; + +struct tc_data { + struct i2c_client *i2c; + struct device *dev; + + struct drm_bridge bridge; + struct drm_bridge *panel_bridge; + + struct device_node *host_node; + struct mipi_dsi_device *dsi; + u8 num_dsi_lanes; + + struct regulator *vdd; + struct regulator *vddio; + struct gpio_desc *reset_gpio; + struct gpio_desc *stby_gpio; + u8 lvds_link; /* single-link or dual-link */ + u8 bpc; +}; + +static inline struct tc_data *bridge_to_tc(struct drm_bridge *b) +{ + return container_of(b, struct tc_data, bridge); +} + +static void tc_bridge_pre_enable(struct drm_bridge *bridge) +{ + struct tc_data *tc = bridge_to_tc(bridge); + struct device *dev = &tc->dsi->dev; + int ret; + + ret = regulator_enable(tc->vddio); + if (ret < 0) + dev_err(dev, "regulator vddio enable failed, %d\n", ret); + usleep_range(10000, 11000); + + ret = regulator_enable(tc->vdd); + if (ret < 0) + dev_err(dev, "regulator vdd enable failed, %d\n", ret); + usleep_range(10000, 11000); + + gpiod_set_value(tc->stby_gpio, 0); + usleep_range(10000, 11000); + + gpiod_set_value(tc->reset_gpio, 0); + usleep_range(10, 20); +} + +static void tc_bridge_post_disable(struct drm_bridge *bridge) +{ + struct tc_data *tc = bridge_to_tc(bridge); + struct device *dev = &tc->dsi->dev; + int ret; + + gpiod_set_value(tc->reset_gpio, 1); + usleep_range(10, 20); + + gpiod_set_value(tc->stby_gpio, 1); + usleep_range(10000, 11000); + + ret = regulator_disable(tc->vdd); + if (ret < 0) + dev_err(dev, "regulator vdd disable failed, %d\n", ret); + usleep_range(10000, 11000); + + ret = regulator_disable(tc->vddio); + if (ret < 0) + dev_err(dev, "regulator vddio disable failed, %d\n", ret); + usleep_range(10000, 11000); +} + +static void d2l_read(struct i2c_client *i2c, u16 addr, u32 *val) +{ + int ret; + u8 buf_addr[2]; + + put_unaligned_be16(addr, buf_addr); + ret = i2c_master_send(i2c, buf_addr, sizeof(buf_addr)); + if (ret < 0) + goto fail; + + ret = i2c_master_recv(i2c, (u8 *)val, sizeof(*val)); + if (ret < 0) + goto fail; + + pr_debug("d2l: I2C : addr:%04x value:%08x\n", addr, *val); + +fail: + dev_err(&i2c->dev, "Error %d reading from subaddress 0x%x\n", + ret, addr); +} + +static void d2l_write(struct i2c_client *i2c, u16 addr, u32 val) +{ + u8 data[6]; + int ret; + + put_unaligned_be16(addr, data); + put_unaligned_le32(val, data + 2); + + ret = i2c_master_send(i2c, data, ARRAY_SIZE(data)); + if (ret < 0) + dev_err(&i2c->dev, "Error %d writing to subaddress 0x%x\n", + ret, addr); +} + +/* helper function to access bus_formats */ +static struct drm_connector *get_connector(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder == encoder) + return connector; + + return NULL; +} + +static void tc_bridge_enable(struct drm_bridge *bridge) +{ + struct tc_data *tc = bridge_to_tc(bridge); + u32 hback_porch, hsync_len, hfront_porch, hactive, htime1, htime2; + u32 vback_porch, vsync_len, vfront_porch, vactive, vtime1, vtime2; + u32 val = 0; + u16 dsiclk, clkdiv, byteclk, t1, t2, t3, vsdelay; + struct drm_display_mode *mode; + struct drm_connector *connector = get_connector(bridge->encoder); + + mode = &bridge->encoder->crtc->state->adjusted_mode; + + hback_porch = mode->htotal - mode->hsync_end; + hsync_len = mode->hsync_end - mode->hsync_start; + vback_porch = mode->vtotal - mode->vsync_end; + vsync_len = mode->vsync_end - mode->vsync_start; + + htime1 = (hback_porch << 16) + hsync_len; + vtime1 = (vback_porch << 16) + vsync_len; + + hfront_porch = mode->hsync_start - mode->hdisplay; + hactive = mode->hdisplay; + vfront_porch = mode->vsync_start - mode->vdisplay; + vactive = mode->vdisplay; + + htime2 = (hfront_porch << 16) + hactive; + vtime2 = (vfront_porch << 16) + vactive; + + d2l_read(tc->i2c, IDREG, &val); + + dev_info(tc->dev, "DSI2LVDS Chip ID.%02x Revision ID. %02x **\n", + (val >> 8) & 0xFF, val & 0xFF); + + d2l_write(tc->i2c, SYSRST, SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM | + SYS_RST_LCD | SYS_RST_I2CM | SYS_RST_I2CS); + usleep_range(30000, 40000); + + d2l_write(tc->i2c, PPI_TX_RX_TA, TTA_GET | TTA_SURE); + d2l_write(tc->i2c, PPI_LPTXTIMECNT, LPX_PERIOD); + d2l_write(tc->i2c, PPI_D0S_CLRSIPOCOUNT, 3); + d2l_write(tc->i2c, PPI_D1S_CLRSIPOCOUNT, 3); + d2l_write(tc->i2c, PPI_D2S_CLRSIPOCOUNT, 3); + d2l_write(tc->i2c, PPI_D3S_CLRSIPOCOUNT, 3); + + val = ((L0EN << tc->num_dsi_lanes) - L0EN) | DSI_CLEN_BIT; + d2l_write(tc->i2c, PPI_LANEENABLE, val); + d2l_write(tc->i2c, DSI_LANEENABLE, val); + + d2l_write(tc->i2c, PPI_STARTPPI, PPI_START_FUNCTION); + d2l_write(tc->i2c, DSI_STARTDSI, DSI_RX_START); + + if (tc->bpc == 8) + val = TC358775_VPCTRL_OPXLFMT(1); + else /* bpc = 6; */ + val = TC358775_VPCTRL_MSF(1); + + dsiclk = mode->crtc_clock * 3 * tc->bpc / tc->num_dsi_lanes / 1000; + clkdiv = dsiclk / DIVIDE_BY_3 * tc->lvds_link; + byteclk = dsiclk / 4; + t1 = hactive * (tc->bpc * 3 / 8) / tc->num_dsi_lanes; + t2 = ((100000 / clkdiv)) * (hactive + hback_porch + hsync_len + hfront_porch) / 1000; + t3 = ((t2 * byteclk) / 100) - (hactive * (tc->bpc * 3 / 8) / + tc->num_dsi_lanes); + + vsdelay = (clkdiv * (t1 + t3) / byteclk) - hback_porch - hsync_len - hactive; + + val |= TC358775_VPCTRL_VSDELAY(vsdelay); + d2l_write(tc->i2c, VPCTRL, val); + + d2l_write(tc->i2c, HTIM1, htime1); + d2l_write(tc->i2c, VTIM1, vtime1); + d2l_write(tc->i2c, HTIM2, htime2); + d2l_write(tc->i2c, VTIM2, vtime2); + + d2l_write(tc->i2c, VFUEN, VFUEN_EN); + d2l_write(tc->i2c, SYSRST, SYS_RST_LCD); + d2l_write(tc->i2c, LVPHY0, LV_PHY0_PRBS_ON(4) | LV_PHY0_ND(6)); + + dev_dbg(tc->dev, "bus_formats %04x bpc %d\n", + connector->display_info.bus_formats[0], + tc->bpc); + /* + * Default hardware register settings of tc358775 configured + * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format + */ + if (connector->display_info.bus_formats[0] == + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) { + /* VESA-24 */ + d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); + d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_R7, LVI_R5, LVI_G0)); + d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_G6, LVI_G7)); + d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2)); + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6)); + } else { /* MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */ + d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); + d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0)); + d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0)); + d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2)); + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0)); + } + + d2l_write(tc->i2c, VFUEN, VFUEN_EN); + + val = LVCFG_LVEN_BIT; + if (tc->lvds_link == DUAL_LINK) { + val |= TC358775_LVCFG_LVDLINK(1); + val |= TC358775_LVCFG_PCLKDIV(DIVIDE_BY_6); + } else { + val |= TC358775_LVCFG_PCLKDIV(DIVIDE_BY_3); + }; + d2l_write(tc->i2c, LVCFG, val); +} + +static enum drm_mode_status +tc_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + struct tc_data *tc = bridge_to_tc(bridge); + + /* + * Maximum pixel clock speed 135MHz for single-link + * 270MHz for dual-link + */ + if ((mode->clock > 135000 && tc->lvds_link == SINGLE_LINK) || + (mode->clock > 270000 && tc->lvds_link == DUAL_LINK)) + return MODE_CLOCK_HIGH; + + switch (info->bus_formats[0]) { + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + /* RGB888 */ + tc->bpc = 8; + break; + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + /* RGB666 */ + tc->bpc = 6; + break; + default: + dev_warn(tc->dev, + "unsupported LVDS bus format 0x%04x\n", + info->bus_formats[0]); + return MODE_NOMODE; + } + + return MODE_OK; +} + +static int tc358775_parse_dt(struct device_node *np, struct tc_data *tc) +{ + struct device_node *endpoint; + struct device_node *parent; + struct device_node *remote; + struct property *prop; + int len = 0; + + /* + * To get the data-lanes of dsi, we need to access the dsi0_out of port1 + * of dsi0 endpoint from bridge port0 of d2l_in + */ + endpoint = of_graph_get_endpoint_by_regs(tc->dev->of_node, + TC358775_DSI_IN, -1); + if (endpoint) { + /* dsi0_out node */ + parent = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); + if (parent) { + /* dsi0 port 1 */ + endpoint = of_graph_get_endpoint_by_regs(parent, 1, -1); + of_node_put(parent); + if (endpoint) { + prop = of_find_property(endpoint, "data-lanes", + &len); + of_node_put(endpoint); + if (!prop) { + dev_err(tc->dev, + "failed to find data lane\n"); + return -EPROBE_DEFER; + } + } + } + } + + tc->num_dsi_lanes = len / sizeof(u32); + + if (tc->num_dsi_lanes < 1 || tc->num_dsi_lanes > 4) + return -EINVAL; + + tc->host_node = of_graph_get_remote_node(np, 0, 0); + if (!tc->host_node) + return -ENODEV; + + of_node_put(tc->host_node); + + tc->lvds_link = SINGLE_LINK; + endpoint = of_graph_get_endpoint_by_regs(tc->dev->of_node, + TC358775_LVDS_OUT1, -1); + if (endpoint) { + remote = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); + + if (remote) { + if (of_device_is_available(remote)) + tc->lvds_link = DUAL_LINK; + of_node_put(remote); + } + } + + dev_dbg(tc->dev, "no.of dsi lanes: %d\n", tc->num_dsi_lanes); + dev_dbg(tc->dev, "operating in %d-link mode\n", tc->lvds_link); + + return 0; +} + +static int tc_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct tc_data *tc = bridge_to_tc(bridge); + struct device *dev = &tc->i2c->dev; + struct mipi_dsi_host *host; + struct mipi_dsi_device *dsi; + int ret; + + const struct mipi_dsi_device_info info = { .type = "tc358775", + .channel = 0, + .node = NULL, + }; + + host = of_find_mipi_dsi_host_by_node(tc->host_node); + if (!host) { + dev_err(dev, "failed to find dsi host\n"); + return -EPROBE_DEFER; + } + + dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dsi)) { + dev_err(dev, "failed to create dsi device\n"); + ret = PTR_ERR(dsi); + goto err_dsi_device; + } + + tc->dsi = dsi; + + dsi->lanes = tc->num_dsi_lanes; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "failed to attach dsi to host\n"); + goto err_dsi_attach; + } + + /* Attach the panel-bridge to the dsi bridge */ + return drm_bridge_attach(bridge->encoder, tc->panel_bridge, + &tc->bridge, flags); +err_dsi_attach: + mipi_dsi_device_unregister(dsi); +err_dsi_device: + return ret; +} + +static const struct drm_bridge_funcs tc_bridge_funcs = { + .attach = tc_bridge_attach, + .pre_enable = tc_bridge_pre_enable, + .enable = tc_bridge_enable, + .mode_valid = tc_mode_valid, + .post_disable = tc_bridge_post_disable, +}; + +static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct drm_panel *panel; + struct tc_data *tc; + int ret; + + tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); + if (!tc) + return -ENOMEM; + + tc->dev = dev; + tc->i2c = client; + + ret = drm_of_find_panel_or_bridge(dev->of_node, TC358775_LVDS_OUT0, + 0, &panel, NULL); + if (ret < 0) + return ret; + if (!panel) + return -ENODEV; + + tc->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(tc->panel_bridge)) + return PTR_ERR(tc->panel_bridge); + + ret = tc358775_parse_dt(dev->of_node, tc); + if (ret) + return ret; + + tc->vddio = devm_regulator_get(dev, "vddio-supply"); + if (IS_ERR(tc->vddio)) { + ret = PTR_ERR(tc->vddio); + dev_err(dev, "vddio-supply not found\n"); + return ret; + } + + tc->vdd = devm_regulator_get(dev, "vdd-supply"); + if (IS_ERR(tc->vdd)) { + ret = PTR_ERR(tc->vddio); + dev_err(dev, "vdd-supply not found\n"); + return ret; + } + + tc->stby_gpio = devm_gpiod_get(dev, "stby", GPIOD_OUT_HIGH); + if (IS_ERR(tc->stby_gpio)) { + ret = PTR_ERR(tc->stby_gpio); + dev_err(dev, "cannot get stby-gpio %d\n", ret); + return ret; + } + + tc->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(tc->reset_gpio)) { + ret = PTR_ERR(tc->reset_gpio); + dev_err(dev, "cannot get reset-gpios %d\n", ret); + return ret; + } + + tc->bridge.funcs = &tc_bridge_funcs; + tc->bridge.of_node = dev->of_node; + drm_bridge_add(&tc->bridge); + + i2c_set_clientdata(client, tc); + + return 0; +} + +static int tc_remove(struct i2c_client *client) +{ + struct tc_data *tc = i2c_get_clientdata(client); + + drm_bridge_remove(&tc->bridge); + + return 0; +} + +static const struct i2c_device_id tc358775_i2c_ids[] = { + { "tc358775", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tc358775_i2c_ids); + +static const struct of_device_id tc358775_of_ids[] = { + { .compatible = "toshiba,tc358775", }, + { } +}; +MODULE_DEVICE_TABLE(of, tc358775_of_ids); + +static struct i2c_driver tc358775_driver = { + .driver = { + .name = "tc358775", + .of_match_table = tc358775_of_ids, + }, + .id_table = tc358775_i2c_ids, + .probe = tc_probe, + .remove = tc_remove, +}; +module_i2c_driver(tc358775_driver); + +MODULE_AUTHOR("Vinay Simha BN <simhavcs@gmail.com>"); +MODULE_DESCRIPTION("TC358775 DSI/LVDS bridge driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 5068ed578e34450a285fca3f9d830361b44267ad Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Sun, 9 Aug 2020 22:34:06 +0200 Subject: [PATCH 0365/1494] drm: amdgpu: Use the correct size when allocating memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When '*sgt' is allocated, we must allocated 'sizeof(**sgt)' bytes instead of 'sizeof(*sg)'. The sizeof(*sg) is bigger than sizeof(**sgt) so this wastes memory but it won't lead to corruption. Fixes: f44ffd677fb3 ("drm/amdgpu: add support for exporting VRAM using DMA-buf v3") Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 97ad8ffe6c6c0..be6a7ec22de48 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -463,7 +463,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, unsigned int pages; int i, r; - *sgt = kmalloc(sizeof(*sg), GFP_KERNEL); + *sgt = kmalloc(sizeof(**sgt), GFP_KERNEL); if (!*sgt) return -ENOMEM; -- GitLab From 5218992251e62cedd16ff4466717ca09b7ad4b18 Mon Sep 17 00:00:00 2001 From: Felix Kuehling <Felix.Kuehling@amd.com> Date: Fri, 7 Aug 2020 18:22:27 -0400 Subject: [PATCH 0366/1494] Revert "drm/amdkfd: Fix spurious debug exception on gfx10" This reverts commit ea368183ae900e376b66d3f23da22acde48e385a. Needed due to conflicts when reverting "drm/amdkfd: Unify gfx9/gfx10 context save area layouts". Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 178 +++++++++--------- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 7 +- 2 files changed, 90 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index a5cf735daf48d..7290a30f26caa 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -911,7 +911,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf820152, + 0xbf85fff8, 0xbf820150, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1024,63 +1024,62 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xba80f801, - 0x00000000, 0xbf8a0000, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0x80788478, 0xf4211cfa, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, + 0xf4211cfa, 0xf0000000, + 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef814, 0xf4211bba, - 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef815, - 0xbefc036f, 0xbefe0370, - 0xbeff0371, 0x876f7bff, - 0x000003ff, 0xb9ef4803, - 0xb9f9f816, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e2a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0x806eff6e, - 0x00000200, 0x806e746e, - 0x826f8075, 0x876fff6f, - 0x0000ffff, 0xf4091c37, - 0xfa000050, 0xf4091d37, - 0xfa000060, 0xf4011e77, - 0xfa000074, 0xbf8cc07f, - 0x876fff6d, 0xfc000000, - 0x906f9a6f, 0x8f6f906f, - 0xbeee0380, 0x886e6f6e, - 0x876fff6d, 0x02000000, - 0x906f996f, 0x8f6f8f6f, + 0xb9eef815, 0xbefc036f, + 0xbefe0370, 0xbeff0371, + 0x876f7bff, 0x000003ff, + 0xb9ef4803, 0xb9f9f816, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e2a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0x806eff6e, 0x00000200, + 0x806e746e, 0x826f8075, + 0x876fff6f, 0x0000ffff, + 0xf4091c37, 0xfa000050, + 0xf4091d37, 0xfa000060, + 0xf4011e77, 0xfa000074, + 0xbf8cc07f, 0x876fff6d, + 0xfc000000, 0x906f9a6f, + 0x8f6f906f, 0xbeee0380, 0x886e6f6e, 0x876fff6d, - 0x01000000, 0x906f986f, - 0x8f6f996f, 0x886e6f6e, - 0x876fff7a, 0x00800000, - 0x906f976f, 0xb9eef807, - 0x876dff6d, 0x0000ffff, - 0x87fe7e7e, 0x87ea6a6a, - 0xb9faf802, 0xbe80226c, + 0x02000000, 0x906f996f, + 0x8f6f8f6f, 0x886e6f6e, + 0x876fff6d, 0x01000000, + 0x906f986f, 0x8f6f996f, + 0x886e6f6e, 0x876fff7a, + 0x00800000, 0x906f976f, + 0xb9eef807, 0x876dff6d, + 0x0000ffff, 0x87fe7e7e, + 0x87ea6a6a, 0xb9faf802, + 0xbf8a0000, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, @@ -1809,7 +1808,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013d, + 0xbf85fff8, 0xbf82013b, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1922,52 +1921,51 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xba80f801, - 0x00000000, 0xbf8a0000, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0x80788478, 0xf4211cfa, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, + 0xf4211cfa, 0xf0000000, + 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef814, 0xf4211bba, - 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef815, - 0xbefc036f, 0xbefe0370, - 0xbeff0371, 0x876f7bff, - 0x000003ff, 0xb9ef4803, - 0x876f7bff, 0xfffff800, - 0x906f8b6f, 0xb9efa2c3, - 0xb9f3f801, 0xb96e2a05, - 0x806e816e, 0xbf0d9972, - 0xbf850002, 0x8f6e896e, - 0xbf820001, 0x8f6e8a6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, + 0xb9eef815, 0xbefc036f, + 0xbefe0370, 0xbeff0371, + 0x876f7bff, 0x000003ff, + 0xb9ef4803, 0x876f7bff, + 0xfffff800, 0x906f8b6f, + 0xb9efa2c3, 0xb9f3f801, + 0xb96e2a05, 0x806e816e, + 0xbf0d9972, 0xbf850002, + 0x8f6e896e, 0xbf820001, + 0x8f6e8a6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbf8a0000, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 0f8e06a2ea8d9..4569db452160d 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -895,11 +895,6 @@ L_RESTORE_SGPR: s_cmp_eq_u32 m0, 0 //scc = (m0 < s_sgpr_save_num) ? 1 : 0 s_cbranch_scc0 L_RESTORE_SGPR_LOOP - // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. - // Clear DEBUG_EN before and restore MODE after the barrier. - s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 - s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG - /* restore HW registers */ L_RESTORE_HWREG: // HWREG SR memory offset : size(VGPR)+size(SVGPR)+size(SGPR) @@ -983,6 +978,8 @@ L_RESTORE_HWREG: s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu + s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG + s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: -- GitLab From c342d7c579f2c9f4e84552d53881acd1cf15eb14 Mon Sep 17 00:00:00 2001 From: Felix Kuehling <Felix.Kuehling@amd.com> Date: Fri, 7 Aug 2020 18:23:56 -0400 Subject: [PATCH 0367/1494] Revert "drm/amdkfd: Unify gfx9/gfx10 context save area layouts" This reverts commit 0a5baee415000a3e18730ac98e19d046c3cebbe6. The change introduced a regression on some chips. Reverting until a proper solution can be found. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 930 +++++++++--------- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 2 - 2 files changed, 464 insertions(+), 468 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 7290a30f26caa..577d901fdb636 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -680,7 +680,7 @@ static const uint32_t cwsr_trap_gfx9_hex[] = { }; static const uint32_t cwsr_trap_nv1x_hex[] = { - 0xbf820001, 0xbf8201ce, + 0xbf820001, 0xbf8201cd, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -794,256 +794,255 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbefc037e, 0xbefe037c, 0xbefc0370, 0xf4611efa, 0xf8000000, 0x80708470, - 0xbefc037e, 0x80708470, - 0xb971f801, 0xbefe037c, - 0xbefc0370, 0xf4611c7a, - 0xf8000000, 0x80708470, - 0xbefc037e, 0xb971f814, + 0xbefc037e, 0xb971f801, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, 0xbefc037e, - 0xb971f815, 0xbefe037c, + 0xb971f814, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, - 0xbefc037e, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0xbef603ff, - 0x01000000, 0xbefb0374, - 0x80747074, 0x82758075, - 0xbefc0380, 0xbf800000, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xbe8c2f0c, 0xbe8e2f0e, - 0xf469003a, 0xfa000000, - 0xf469013a, 0xfa000010, - 0xf469023a, 0xfa000020, - 0xf469033a, 0xfa000030, - 0x8074c074, 0x82758075, - 0x807c907c, 0xbf0aff7c, - 0x00000060, 0xbf85ffea, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xf469003a, 0xfa000000, - 0xf469013a, 0xfa000010, - 0xf469023a, 0xfa000020, - 0x8074b074, 0x82758075, - 0xbef4037b, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb97b4306, - 0x877bc17b, 0xbf840044, - 0xbf8a0000, 0x877aff73, - 0x04000000, 0xbf840040, - 0x8f7b867b, 0x8f7b827b, - 0xbef6037b, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef603ff, - 0x01000000, 0xd7650000, - 0x000100c1, 0xd7660000, - 0x000200c1, 0x16000084, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850012, 0xbe8303ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7c, 0xbf85fff4, - 0xbf820011, 0xbe8303ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7c, 0xbf85fff4, + 0xbefc037e, 0xb971f815, + 0xbefe037c, 0xbefc0370, + 0xf4611c7a, 0xf8000000, + 0x80708470, 0xbefc037e, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0xbef603ff, 0x01000000, + 0xbefb0374, 0x80747074, + 0x82758075, 0xbefc0380, + 0xbf800000, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xbe8c2f0c, + 0xbe8e2f0e, 0xf469003a, + 0xfa000000, 0xf469013a, + 0xfa000010, 0xf469023a, + 0xfa000020, 0xf469033a, + 0xfa000030, 0x8074c074, + 0x82758075, 0x807c907c, + 0xbf0aff7c, 0x00000060, + 0xbf85ffea, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xf469003a, + 0xfa000000, 0xf469013a, + 0xfa000010, 0xf469023a, + 0xfa000020, 0x8074b074, + 0x82758075, 0xbef4037b, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850004, 0xbef003ff, - 0x00000200, 0xbeff0380, - 0xbf820003, 0xbef003ff, - 0x00000400, 0xbeff03c1, - 0xb97b2a05, 0x807b817b, - 0x8f7b827b, 0x907c9973, + 0xbf850002, 0xbeff0380, + 0xbf820001, 0xbeff03c1, + 0xb97b4306, 0x877bc17b, + 0xbf840044, 0xbf8a0000, + 0x877aff73, 0x04000000, + 0xbf840040, 0x8f7b867b, + 0x8f7b827b, 0xbef6037b, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef603ff, 0x01000000, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x16000084, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850017, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0704000, 0x705d0000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000200, 0xbf0a7b7c, - 0xbf85ffef, 0xbf820025, + 0xbefc0380, 0xbf850012, + 0xbe8303ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff4, 0xbf820011, + 0xbe8303ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7c, + 0xbf85fff4, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850004, + 0xbef003ff, 0x00000200, + 0xbeff0380, 0xbf820003, + 0xbef003ff, 0x00000400, + 0xbeff03c1, 0xb97b2a05, + 0x807b817b, 0x8f7b827b, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850017, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840020, 0x7e008700, + 0xbf840037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, + 0x705d0000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7c, 0xbf85ffef, - 0xb97b1e06, 0x877bc17b, - 0xbf84000c, 0x8f7b837b, - 0x807b7c7b, 0xbefe03c1, - 0xbeff0380, 0x7e008700, + 0xbf820025, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840020, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0704000, 0x705d0000, - 0x807c817c, 0x8070ff70, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf820150, - 0xbef4037e, 0x8775ff7f, - 0x0000ffff, 0x8875ff75, - 0x00040000, 0xbef60380, - 0xbef703ff, 0x10807fac, - 0x876eff7f, 0x08000000, - 0x906e836e, 0x88776e77, - 0x876eff7f, 0x70000000, - 0x906e816e, 0x88776e77, - 0xb97202dc, 0x8f729972, - 0x8872727f, 0x876eff7f, - 0x04000000, 0xbf840034, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000400, 0xbf0a7b7c, + 0xbf85ffef, 0xb97b1e06, + 0x877bc17b, 0xbf84000c, + 0x8f7b837b, 0x807b7c7b, + 0xbefe03c1, 0xbeff0380, + 0x7e008700, 0xe0704000, + 0x705d0000, 0x807c817c, + 0x8070ff70, 0x00000080, + 0xbf0a7b7c, 0xbf85fff8, + 0xbf82014f, 0xbef4037e, + 0x8775ff7f, 0x0000ffff, + 0x8875ff75, 0x00040000, + 0xbef60380, 0xbef703ff, + 0x10807fac, 0x876eff7f, + 0x08000000, 0x906e836e, + 0x88776e77, 0x876eff7f, + 0x70000000, 0x906e816e, + 0x88776e77, 0xb97202dc, + 0x8f729972, 0x8872727f, + 0x876eff7f, 0x04000000, + 0xbf840034, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f4306, + 0x876fc16f, 0xbf840029, + 0x8f6f866f, 0x8f6f826f, + 0xbef6036f, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x8078ff78, + 0x00000080, 0xbef603ff, + 0x01000000, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbefc0380, 0xbf850009, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff8, + 0xbf820008, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000100, 0x8078ff78, + 0x00000100, 0xbf0a6f7c, + 0xbf85fff8, 0xbef80380, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f4306, 0x876fc16f, - 0xbf840029, 0x8f6f866f, - 0x8f6f826f, 0xbef6036f, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0x8078ff78, 0x00000080, - 0xbef603ff, 0x01000000, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850009, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff8, 0xbf820008, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000100, - 0x8078ff78, 0x00000100, - 0xbf0a6f7c, 0xbf85fff8, - 0xbef80380, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f2a05, - 0x806f816f, 0x8f6f826f, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850021, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000200, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304080, 0x785d0100, - 0xe0304100, 0x785d0200, - 0xe0304180, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000200, - 0xbf0a6f7c, 0xbf85ffee, - 0xe0304000, 0x6e5d0000, - 0xe0304080, 0x6e5d0100, - 0xe0304100, 0x6e5d0200, - 0xe0304180, 0x6e5d0300, - 0xbf820032, 0xbef603ff, + 0xb96f2a05, 0x806f816f, + 0x8f6f826f, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbf850021, 0xbef603ff, 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000400, + 0x8078ff78, 0x00000200, 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304100, - 0x785d0100, 0xe0304200, - 0x785d0200, 0xe0304300, + 0x785d0000, 0xe0304080, + 0x785d0100, 0xe0304100, + 0x785d0200, 0xe0304180, 0x785d0300, 0xbf8c3f70, 0x7e008500, 0x7e028501, 0x7e048502, 0x7e068503, 0x807c847c, 0x8078ff78, - 0x00000400, 0xbf0a6f7c, - 0xbf85ffee, 0xb96f1e06, - 0x876fc16f, 0xbf84000e, - 0x8f6f836f, 0x806f7c6f, - 0xbefe03c1, 0xbeff0380, + 0x00000200, 0xbf0a6f7c, + 0xbf85ffee, 0xe0304000, + 0x6e5d0000, 0xe0304080, + 0x6e5d0100, 0xe0304100, + 0x6e5d0200, 0xe0304180, + 0x6e5d0300, 0xbf820032, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000400, 0xbefc0384, 0xe0304000, 0x785d0000, + 0xe0304100, 0x785d0100, + 0xe0304200, 0x785d0200, + 0xe0304300, 0x785d0300, 0xbf8c3f70, 0x7e008500, - 0x807c817c, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff7, 0xbeff03c1, - 0xe0304000, 0x6e5d0000, - 0xe0304100, 0x6e5d0100, - 0xe0304200, 0x6e5d0200, - 0xe0304300, 0x6e5d0300, - 0xbf8c3f70, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef603ff, - 0x01000000, 0xbefc03ff, - 0x0000006c, 0x80f89078, - 0xf429003a, 0xf0000000, - 0xbf8cc07f, 0x80fc847c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0x80f8a078, - 0xf42d003a, 0xf0000000, - 0xbf8cc07f, 0x80fc887c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0x80f8c078, - 0xf431003a, 0xf0000000, - 0xbf8cc07f, 0x80fc907c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0xbe883108, - 0xbe8a310a, 0xbe8c310c, - 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000400, + 0xbf0a6f7c, 0xbf85ffee, + 0xb96f1e06, 0x876fc16f, + 0xbf84000e, 0x8f6f836f, + 0x806f7c6f, 0xbefe03c1, + 0xbeff0380, 0xe0304000, + 0x785d0000, 0xbf8c3f70, + 0x7e008500, 0x807c817c, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff7, + 0xbeff03c1, 0xe0304000, + 0x6e5d0000, 0xe0304100, + 0x6e5d0100, 0xe0304200, + 0x6e5d0200, 0xe0304300, + 0x6e5d0300, 0xbf8c3f70, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, + 0xbef603ff, 0x01000000, + 0xbefc03ff, 0x0000006c, + 0x80f89078, 0xf429003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc847c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0x80f8a078, 0xf42d003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc887c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0x80f8c078, 0xf431003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc907c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0xbe883108, 0xbe8a310a, + 0xbe8c310c, 0xbe8e310e, + 0xbf06807c, 0xbf84fff0, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, @@ -1576,7 +1575,7 @@ static const uint32_t cwsr_trap_arcturus_hex[] = { }; static const uint32_t cwsr_trap_gfx10_hex[] = { - 0xbf820001, 0xbf8201d0, + 0xbf820001, 0xbf8201cf, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -1658,289 +1657,288 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xd7610002, 0x0000f87a, 0x807c817c, 0xd7610002, 0x0000f87b, 0x807c817c, - 0x80708470, 0xb971f801, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xb971f814, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xb971f815, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xbeff0380, - 0xe0704000, 0x705d0200, - 0xb9702a05, 0x80708170, - 0xbf0d9973, 0xbf850002, - 0x8f708970, 0xbf820001, - 0x8f708a70, 0xb97a1e06, - 0x8f7a8a7a, 0x80707a70, - 0xbef603ff, 0x01000000, - 0xbef90380, 0xbefc0380, - 0xbf800000, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xbe8c2f0c, - 0xbe8e2f0e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0xb971f801, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xb971f814, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xb971f815, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xbeff0380, 0xe0704000, + 0x705d0200, 0xb9702a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0xbef603ff, + 0x01000000, 0xbef90380, + 0xbefc0380, 0xbf800000, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xbe8c2f0c, 0xbe8e2f0e, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, + 0x0000f20b, 0x80798179, + 0xd7610002, 0x0000f20c, 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbf840006, 0xe0704000, - 0x705d0200, 0x8070ff70, - 0x00000080, 0xbef90380, - 0x7e040280, 0x807c907c, - 0xbf0aff7c, 0x00000060, - 0xbf85ffbc, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbf840006, + 0xe0704000, 0x705d0200, + 0x8070ff70, 0x00000080, + 0xbef90380, 0x7e040280, + 0x807c907c, 0xbf0aff7c, + 0x00000060, 0xbf85ffbc, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xe0704000, - 0x705d0200, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb97b4306, - 0x877bc17b, 0xbf840044, - 0xbf8a0000, 0x877aff73, - 0x04000000, 0xbf840040, - 0x8f7b867b, 0x8f7b827b, - 0xbef6037b, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef603ff, - 0x01000000, 0xd7650000, - 0x000100c1, 0xd7660000, - 0x000200c1, 0x16000084, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850012, 0xbe8303ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7c, 0xbf85fff4, - 0xbf820011, 0xbe8303ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7c, 0xbf85fff4, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, + 0x80798179, 0xd7610002, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, + 0x80798179, 0xd7610002, + 0x0000f20b, 0x80798179, + 0xe0704000, 0x705d0200, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850004, 0xbef003ff, - 0x00000200, 0xbeff0380, - 0xbf820003, 0xbef003ff, - 0x00000400, 0xbeff03c1, - 0xb97b2a05, 0x807b817b, - 0x8f7b827b, 0x907c9973, + 0xbf850002, 0xbeff0380, + 0xbf820001, 0xbeff03c1, + 0xb97b4306, 0x877bc17b, + 0xbf840044, 0xbf8a0000, + 0x877aff73, 0x04000000, + 0xbf840040, 0x8f7b867b, + 0x8f7b827b, 0xbef6037b, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef603ff, 0x01000000, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x16000084, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850017, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0704000, 0x705d0000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000200, 0xbf0a7b7c, - 0xbf85ffef, 0xbf820025, + 0xbefc0380, 0xbf850012, + 0xbe8303ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff4, 0xbf820011, + 0xbe8303ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7c, + 0xbf85fff4, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850004, + 0xbef003ff, 0x00000200, + 0xbeff0380, 0xbf820003, + 0xbef003ff, 0x00000400, + 0xbeff03c1, 0xb97b2a05, + 0x807b817b, 0x8f7b827b, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850017, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840020, 0x7e008700, + 0xbf840037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, + 0x705d0000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7c, 0xbf85ffef, - 0xb97b1e06, 0x877bc17b, - 0xbf84000c, 0x8f7b837b, - 0x807b7c7b, 0xbefe03c1, - 0xbeff0380, 0x7e008700, + 0xbf820025, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840020, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0704000, 0x705d0000, - 0x807c817c, 0x8070ff70, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013b, - 0xbef4037e, 0x8775ff7f, - 0x0000ffff, 0x8875ff75, - 0x00040000, 0xbef60380, - 0xbef703ff, 0x10807fac, - 0x876eff7f, 0x08000000, - 0x906e836e, 0x88776e77, - 0x876eff7f, 0x70000000, - 0x906e816e, 0x88776e77, - 0xb97202dc, 0x8f729972, - 0x8872727f, 0x876eff7f, - 0x04000000, 0xbf840034, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000400, 0xbf0a7b7c, + 0xbf85ffef, 0xb97b1e06, + 0x877bc17b, 0xbf84000c, + 0x8f7b837b, 0x807b7c7b, + 0xbefe03c1, 0xbeff0380, + 0x7e008700, 0xe0704000, + 0x705d0000, 0x807c817c, + 0x8070ff70, 0x00000080, + 0xbf0a7b7c, 0xbf85fff8, + 0xbf82013a, 0xbef4037e, + 0x8775ff7f, 0x0000ffff, + 0x8875ff75, 0x00040000, + 0xbef60380, 0xbef703ff, + 0x10807fac, 0x876eff7f, + 0x08000000, 0x906e836e, + 0x88776e77, 0x876eff7f, + 0x70000000, 0x906e816e, + 0x88776e77, 0xb97202dc, + 0x8f729972, 0x8872727f, + 0x876eff7f, 0x04000000, + 0xbf840034, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f4306, + 0x876fc16f, 0xbf840029, + 0x8f6f866f, 0x8f6f826f, + 0xbef6036f, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x8078ff78, + 0x00000080, 0xbef603ff, + 0x01000000, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbefc0380, 0xbf850009, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff8, + 0xbf820008, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000100, 0x8078ff78, + 0x00000100, 0xbf0a6f7c, + 0xbf85fff8, 0xbef80380, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f4306, 0x876fc16f, - 0xbf840029, 0x8f6f866f, - 0x8f6f826f, 0xbef6036f, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0x8078ff78, 0x00000080, - 0xbef603ff, 0x01000000, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850009, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff8, 0xbf820008, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000100, - 0x8078ff78, 0x00000100, - 0xbf0a6f7c, 0xbf85fff8, - 0xbef80380, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f2a05, - 0x806f816f, 0x8f6f826f, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850021, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000200, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304080, 0x785d0100, - 0xe0304100, 0x785d0200, - 0xe0304180, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000200, - 0xbf0a6f7c, 0xbf85ffee, - 0xe0304000, 0x6e5d0000, - 0xe0304080, 0x6e5d0100, - 0xe0304100, 0x6e5d0200, - 0xe0304180, 0x6e5d0300, - 0xbf820032, 0xbef603ff, + 0xb96f2a05, 0x806f816f, + 0x8f6f826f, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbf850021, 0xbef603ff, 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000400, + 0x8078ff78, 0x00000200, 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304100, - 0x785d0100, 0xe0304200, - 0x785d0200, 0xe0304300, + 0x785d0000, 0xe0304080, + 0x785d0100, 0xe0304100, + 0x785d0200, 0xe0304180, 0x785d0300, 0xbf8c3f70, 0x7e008500, 0x7e028501, 0x7e048502, 0x7e068503, 0x807c847c, 0x8078ff78, - 0x00000400, 0xbf0a6f7c, - 0xbf85ffee, 0xb96f1e06, - 0x876fc16f, 0xbf84000e, - 0x8f6f836f, 0x806f7c6f, - 0xbefe03c1, 0xbeff0380, + 0x00000200, 0xbf0a6f7c, + 0xbf85ffee, 0xe0304000, + 0x6e5d0000, 0xe0304080, + 0x6e5d0100, 0xe0304100, + 0x6e5d0200, 0xe0304180, + 0x6e5d0300, 0xbf820032, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000400, 0xbefc0384, 0xe0304000, 0x785d0000, + 0xe0304100, 0x785d0100, + 0xe0304200, 0x785d0200, + 0xe0304300, 0x785d0300, 0xbf8c3f70, 0x7e008500, - 0x807c817c, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff7, 0xbeff03c1, - 0xe0304000, 0x6e5d0000, - 0xe0304100, 0x6e5d0100, - 0xe0304200, 0x6e5d0200, - 0xe0304300, 0x6e5d0300, - 0xbf8c3f70, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef603ff, - 0x01000000, 0xbefc03ff, - 0x0000006c, 0x80f89078, - 0xf429003a, 0xf0000000, - 0xbf8cc07f, 0x80fc847c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0x80f8a078, - 0xf42d003a, 0xf0000000, - 0xbf8cc07f, 0x80fc887c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0x80f8c078, - 0xf431003a, 0xf0000000, - 0xbf8cc07f, 0x80fc907c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0xbe883108, - 0xbe8a310a, 0xbe8c310c, - 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000400, + 0xbf0a6f7c, 0xbf85ffee, + 0xb96f1e06, 0x876fc16f, + 0xbf84000e, 0x8f6f836f, + 0x806f7c6f, 0xbefe03c1, + 0xbeff0380, 0xe0304000, + 0x785d0000, 0xbf8c3f70, + 0x7e008500, 0x807c817c, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff7, + 0xbeff03c1, 0xe0304000, + 0x6e5d0000, 0xe0304100, + 0x6e5d0100, 0xe0304200, + 0x6e5d0200, 0xe0304300, + 0x6e5d0300, 0xbf8c3f70, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, + 0xbef603ff, 0x01000000, + 0xbefc03ff, 0x0000006c, + 0x80f89078, 0xf429003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc847c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0x80f8a078, 0xf42d003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc887c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0x80f8c078, 0xf431003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc907c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0xbe883108, 0xbe8a310a, + 0xbe8c310c, 0xbe8e310e, + 0xbf06807c, 0xbf84fff0, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 4569db452160d..5b220f2a7501f 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -407,7 +407,6 @@ L_SAVE_HWREG: // Not used on Sienna_Cichlid but keep layout same for debugger. write_hwreg_to_mem(s_save_xnack_mask, s_save_buf_rsrc0, s_save_mem_offset) - s_add_u32 s_save_mem_offset, s_save_mem_offset, 4 s_getreg_b32 s_save_m0, hwreg(HW_REG_MODE) write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) @@ -913,7 +912,6 @@ L_RESTORE_HWREG: read_hwreg_from_mem(s_restore_status, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_trapsts, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_xnack_mask, s_restore_buf_rsrc0, s_restore_mem_offset) - s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4 read_hwreg_from_mem(s_restore_mode, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_flat_scratch, s_restore_buf_rsrc0, s_restore_mem_offset) s_waitcnt lgkmcnt(0) -- GitLab From b60646a20c9f61e364c86cc88f50f547361cceb3 Mon Sep 17 00:00:00 2001 From: Jay Cornwall <jay.cornwall@amd.com> Date: Fri, 24 Jul 2020 16:58:48 -0700 Subject: [PATCH 0368/1494] drm/amdkfd: Fix spurious debug exception on gfx10 s_barrier triggers a debug exception when issued with PRIV=1, DEBUG_EN=1. This causes spurious notifications to rocm-gdb. Clear MODE before issuing s_barrier and restore MODE afterwards in the context restore handler. Signed-off-by: Jay Cornwall <jay.cornwall@amd.com> Tested-by: Laurent Morichetti <laurent.morichetti@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 174 +++++++++--------- .../amd/amdkfd/cwsr_trap_handler_gfx10.asm | 7 +- 2 files changed, 93 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 577d901fdb636..affbca7c0050e 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -911,7 +911,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, 0xbf85fff8, - 0xbf82014f, 0xbef4037e, + 0xbf820151, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, 0xbef703ff, @@ -1024,61 +1024,62 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xba80f801, 0x00000000, + 0xbf8a0000, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0xb9f9f816, - 0x876f7bff, 0xfffff800, - 0x906f8b6f, 0xb9efa2c3, - 0xb9f3f801, 0xb96e2a05, - 0x806e816e, 0xbf0d9972, - 0xbf850002, 0x8f6e896e, - 0xbf820001, 0x8f6e8a6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876fff6d, - 0xfc000000, 0x906f9a6f, - 0x8f6f906f, 0xbeee0380, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0xb9f9f816, 0x876f7bff, + 0xfffff800, 0x906f8b6f, + 0xb9efa2c3, 0xb9f3f801, + 0xb96e2a05, 0x806e816e, + 0xbf0d9972, 0xbf850002, + 0x8f6e896e, 0xbf820001, + 0x8f6e8a6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876fff6d, 0xfc000000, + 0x906f9a6f, 0x8f6f906f, + 0xbeee0380, 0x886e6f6e, + 0x876fff6d, 0x02000000, + 0x906f996f, 0x8f6f8f6f, 0x886e6f6e, 0x876fff6d, - 0x02000000, 0x906f996f, - 0x8f6f8f6f, 0x886e6f6e, - 0x876fff6d, 0x01000000, - 0x906f986f, 0x8f6f996f, - 0x886e6f6e, 0x876fff7a, - 0x00800000, 0x906f976f, - 0xb9eef807, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, - 0xbf8a0000, 0xbe80226c, + 0x01000000, 0x906f986f, + 0x8f6f996f, 0x886e6f6e, + 0x876fff7a, 0x00800000, + 0x906f976f, 0xb9eef807, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, @@ -1807,7 +1808,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, 0xbf85fff8, - 0xbf82013a, 0xbef4037e, + 0xbf82013c, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, 0xbef703ff, @@ -1920,50 +1921,51 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xba80f801, 0x00000000, + 0xbf8a0000, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e2a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0x806eff6e, - 0x00000200, 0x806e746e, - 0x826f8075, 0x876fff6f, - 0x0000ffff, 0xf4091c37, - 0xfa000050, 0xf4091d37, - 0xfa000060, 0xf4011e77, - 0xfa000074, 0xbf8cc07f, - 0x876dff6d, 0x0000ffff, - 0x87fe7e7e, 0x87ea6a6a, - 0xb9faf802, 0xbf8a0000, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e2a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0x806eff6e, 0x00000200, + 0x806e746e, 0x826f8075, + 0x876fff6f, 0x0000ffff, + 0xf4091c37, 0xfa000050, + 0xf4091d37, 0xfa000060, + 0xf4011e77, 0xfa000074, + 0xbf8cc07f, 0x876dff6d, + 0x0000ffff, 0x87fe7e7e, + 0x87ea6a6a, 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 5b220f2a7501f..5081f91190b84 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -894,6 +894,11 @@ L_RESTORE_SGPR: s_cmp_eq_u32 m0, 0 //scc = (m0 < s_sgpr_save_num) ? 1 : 0 s_cbranch_scc0 L_RESTORE_SGPR_LOOP + // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. + // Clear DEBUG_EN before and restore MODE after the barrier. + s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 + s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG + /* restore HW registers */ L_RESTORE_HWREG: // HWREG SR memory offset : size(VGPR)+size(SVGPR)+size(SGPR) @@ -976,8 +981,6 @@ L_RESTORE_HWREG: s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu - s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG - s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: -- GitLab From 1d4473261966bef70ff65ebb303bae98949b8f8a Mon Sep 17 00:00:00 2001 From: Liu ChengZhe <ChengZhe.Liu@amd.com> Date: Thu, 6 Aug 2020 14:54:08 +0800 Subject: [PATCH 0369/1494] drm/amdgpu: Skip some registers config for SRIOV Some registers are not accessible to virtual function setup, so skip their initialization when in VF-SRIOV mode. v2: move SRIOV VF check into specify functions; modify commit description and comment. Signed-off-by: Liu ChengZhe <ChengZhe.Liu@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 1f6112b7fa49a..80c906a0383f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -182,6 +182,12 @@ static void gfxhub_v2_1_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -237,6 +243,12 @@ static void gfxhub_v2_1_enable_system_domain(struct amdgpu_device *adev) static void gfxhub_v2_1_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32, @@ -373,6 +385,13 @@ void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index d83912901f730..8acb3b625afe7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -181,6 +181,12 @@ static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -236,6 +242,12 @@ static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev) static void mmhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); @@ -365,6 +377,13 @@ void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); -- GitLab From 7358462f7de98f95550f27abf805d4d5c95e2a5c Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 7 Aug 2020 15:03:40 +0800 Subject: [PATCH 0370/1494] drm/amd/powerplay: correct Vega20 cached smu feature state Correct the cached smu feature state on pp_features sysfs setting. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 86d3a10379bef..303e764af11ae 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -984,10 +984,7 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) { struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - int ret = 0; + int i, ret = 0; PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, @@ -995,17 +992,8 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) "[DisableAllSMUFeatures] Failed to disable all smu features!", return ret); - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[DisableAllSMUFeatures] Failed to get enabled smc features!", - return ret); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? - true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - } + for (i = 0; i < GNLD_FEATURES_MAX; i++) + data->smu_features[i].enabled = 0; return 0; } @@ -3242,10 +3230,11 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) { - uint64_t features_enabled; - uint64_t features_to_enable; - uint64_t features_to_disable; - int ret = 0; + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint64_t features_enabled, features_to_enable, features_to_disable; + int i, ret = 0; + bool enabled; if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) return -EINVAL; @@ -3274,6 +3263,17 @@ static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return ret; } + /* Update the cached feature enablement state */ + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? + true : false; + data->smu_features[i].enabled = enabled; + } + return 0; } -- GitLab From 8d0717f422255513ae1afab2ea0b75ba9f1512a9 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 7 Aug 2020 17:01:47 +0800 Subject: [PATCH 0371/1494] drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading The UVD/VCE PG state is managed by UVD and VCE IP. It's error-prone to assume the bootup state in SMU based on the dpm status. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 303e764af11ae..c9f402edc0d64 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -1645,12 +1645,6 @@ static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) data->uvd_power_gated = true; data->vce_power_gated = true; - - if (data->smu_features[GNLD_DPM_UVD].enabled) - data->uvd_power_gated = false; - - if (data->smu_features[GNLD_DPM_VCE].enabled) - data->vce_power_gated = false; } static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -- GitLab From 5a58abf5ed4f63e0d8c6f542da1d9e2dd8dea1bc Mon Sep 17 00:00:00 2001 From: "shiwu.zhang" <shiwu.zhang@amd.com> Date: Fri, 7 Aug 2020 16:43:59 +0800 Subject: [PATCH 0372/1494] drm/amdgpu: update gc golden register for arcturus Update golden setting to improve performance on HPC and ML apps Signed-off-by: shiwu.zhang <shiwu.zhang@amd.com> Tested-by: gang.long <gang.long@amd.com> Reviewed-by: guchun.chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ef07e59cd4261..93c63ff3b35ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -691,6 +691,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_4_1_arct[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_5_ARCT, 0x3ff, 0x135), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_CONFIG, 0xffffffff, 0x011A0000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_FIFO_SIZES, 0xffffffff, 0x00000f00), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_UTCL1_CNTL1, 0x30000000, 0x30000000) }; static const struct soc15_reg_rlcg rlcg_access_gc_9_0[] = { -- GitLab From bcca6298069435fa7f23ab98f4cb635fcbd3bc20 Mon Sep 17 00:00:00 2001 From: Monk Liu <Monk.Liu@amd.com> Date: Mon, 10 Aug 2020 14:12:06 +0800 Subject: [PATCH 0373/1494] drm/amdgpu: fix reload KMD hang on GFX10 KIQ GFX10 KIQ will hang if we try below steps: modprobe amdgpu rmmod amdgpu modprobe amdgpu sched_hw_submission=4 Due to KIQ is always living there even after KMD unloaded thus when doing the realod KIQ will crash upon its register being programed by different values with the previous loading (the config like HQD addr, ring size, is easily changed if we alter the sched_hw_submission) the fix is we must inactive KIQ first before touching any of its registgers Signed-off-by: Monk Liu <Monk.Liu@amd.com> Reviewed-by: Emily Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 622f4425bf594..0702c94fcca32 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6435,6 +6435,10 @@ static int gfx_v10_0_kiq_init_register(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int j; + /* inactivate the queue */ + if (amdgpu_sriov_vf(adev)) + WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0); + /* disable wptr polling */ WREG32_FIELD15(GC, 0, CP_PQ_WPTR_POLL_CNTL, EN, 0); -- GitLab From fe04afad4ee144557fbf7196c5746cfe57fbdf47 Mon Sep 17 00:00:00 2001 From: Joshua Aberback <joshua.aberback@amd.com> Date: Thu, 16 Jul 2020 12:39:27 -0400 Subject: [PATCH 0374/1494] drm/amd/display: Adjust static-ness of resource functions [Why] Register definitions are asic-specific, so functions that use registers of a particular asic should be static, to be exposed in asic-specific function pointer structures. [How] - make register-definition-using functions static - make some functions non-static, for future use - remove duplicate function definition Signed-off-by: Joshua Aberback <joshua.aberback@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn20/dcn20_resource.h | 1 - .../drm/amd/display/dc/dcn30/dcn30_resource.c | 27 ++++++++++--------- .../drm/amd/display/dc/dcn30/dcn30_resource.h | 3 +++ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 2c1959845c29a..cdd39ee9761d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -95,7 +95,6 @@ struct display_stream_compressor *dcn20_dsc_create( struct dc_context *ctx, uint32_t inst); void dcn20_dsc_destroy(struct display_stream_compressor **dsc); -void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb); void dcn20_cap_soc_clocks( struct _vcs_dpi_soc_bounding_box_st *bb, struct pp_smu_nv_clock_table max_clocks); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index d474a61884454..aa3ea6c79c278 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -871,7 +871,7 @@ void dcn30_dpp_destroy(struct dpp **dpp) *dpp = NULL; } -struct dpp *dcn30_dpp_create( +static struct dpp *dcn30_dpp_create( struct dc_context *ctx, uint32_t inst) { @@ -889,7 +889,8 @@ struct dpp *dcn30_dpp_create( kfree(dpp); return NULL; } -struct output_pixel_processor *dcn30_opp_create( + +static struct output_pixel_processor *dcn30_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp = @@ -905,7 +906,7 @@ struct output_pixel_processor *dcn30_opp_create( return &opp->base; } -struct dce_aux *dcn30_aux_engine_create( +static struct dce_aux *dcn30_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -924,6 +925,7 @@ struct dce_aux *dcn30_aux_engine_create( return &aux_engine->base; } + #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } static const struct dce_i2c_registers i2c_hw_regs[] = { @@ -943,7 +945,7 @@ static const struct dce_i2c_mask i2c_masks = { I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) }; -struct dce_i2c_hw *dcn30_i2c_hw_create( +static struct dce_i2c_hw *dcn30_i2c_hw_create( struct dc_context *ctx, uint32_t inst) { @@ -958,6 +960,7 @@ struct dce_i2c_hw *dcn30_i2c_hw_create( return dce_i2c_hw; } + static struct mpc *dcn30_mpc_create( struct dc_context *ctx, int num_mpcc, @@ -1008,7 +1011,7 @@ struct hubbub *dcn30_hubbub_create(struct dc_context *ctx) return &hubbub3->base; } -struct timing_generator *dcn30_timing_generator_create( +static struct timing_generator *dcn30_timing_generator_create( struct dc_context *ctx, uint32_t instance) { @@ -1042,7 +1045,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_TPS4_CAPABLE = true }; -struct link_encoder *dcn30_link_encoder_create( +static struct link_encoder *dcn30_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dcn20_link_encoder *enc20 = @@ -1063,7 +1066,7 @@ struct link_encoder *dcn30_link_encoder_create( return &enc20->enc10.base; } -struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) +static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) { struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); @@ -1311,7 +1314,7 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) dcn_dccg_destroy(&pool->base.dccg); } -struct hubp *dcn30_hubp_create( +static struct hubp *dcn30_hubp_create( struct dc_context *ctx, uint32_t inst) { @@ -1330,7 +1333,7 @@ struct hubp *dcn30_hubp_create( return NULL; } -bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) { int i; uint32_t pipe_count = pool->res_cap->num_dwb; @@ -1355,7 +1358,7 @@ bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) return true; } -bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) { int i; uint32_t pipe_count = pool->res_cap->num_dwb; @@ -2292,7 +2295,7 @@ static void get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, (dcn3_0_soc.return_bus_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100)); } -static void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { unsigned int i, j; unsigned int num_states = 0; @@ -2683,7 +2686,7 @@ static bool dcn30_resource_construct( if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) - goto create_fail; + goto create_fail; /* HW Sequencer and Plane caps */ dcn30_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h index 4b4a4d81c1e3b..c9d5f94092a04 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -79,4 +79,7 @@ enum dc_status dcn30_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); + +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + #endif /* _DCN30_RESOURCE_H_ */ -- GitLab From 5396fa590df764775e83c9014330bc4112a75f63 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 27 Jul 2020 21:21:16 -0400 Subject: [PATCH 0375/1494] drm/amd/display: Fix incorrect backlight register offset for DCN [Why] Typo in backlight refactor inctroduced wrong register offset. [How] Change DCE to DCN register map for PWRSEQ_REF_DIV Cc: stable@vger.kernel.org Signed-off-by: Aric Cyr <aric.cyr@amd.com> Reviewed-by: Ashley Thomas <Ashley.Thomas2@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 70ec691e14d2d..99c68ca9c7e00 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -49,7 +49,7 @@ #define DCN_PANEL_CNTL_REG_LIST()\ DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \ DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ - DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ + DCN_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ SR(BL_PWM_CNTL), \ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ -- GitLab From ffe0fcbb20d61ccf670e17a89b0dc06be141cce0 Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Wed, 29 Jul 2020 17:49:14 -0400 Subject: [PATCH 0376/1494] drm/amd/display: Revert regression [Why] Caused pipe split regression Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 -- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 114 ------------------ .../drm/amd/display/dc/dcn20/dcn20_hwseq.h | 7 -- .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 - .../gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 - .../gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 - .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 - 7 files changed, 141 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ebbb8182228d2..5aa3b89471c31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,7 +2300,6 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { - bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2331,15 +2330,6 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && - dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ - dc->hwss.interdependent_update_lock(dc, context, true); - mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); - dc->hwss.interdependent_update_lock(dc, context, false); - if (mpcc_disconnected) - dc->hwss.wait_for_pending_cleared(dc, context); - } - for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 73eb4e76a0b1e..66180b4332f1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1624,120 +1624,6 @@ static void dcn20_program_pipe( } } -bool dcn20_disconnect_pipes( - struct dc *dc, - struct dc_state *context) -{ - int i; - struct dce_hwseq *hws = dc->hwseq; - bool mpcc_disconnected = false; - DC_LOGGER_INIT(dc->ctx->logger); - - /* Set pipe update flags and lock pipes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) - dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], - &context->res_ctx.pipe_ctx[i]); - - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - /* OTG blank before disabling all front ends */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable - && !context->res_ctx.pipe_ctx[i].top_pipe - && !context->res_ctx.pipe_ctx[i].prev_odm_pipe - && context->res_ctx.pipe_ctx[i].stream) { - hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); - } - } - - /* Disconnect mpcc */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { - hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); - DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); - mpcc_disconnected = true; - } - } - } - - if (mpcc_disconnected) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - struct dc_plane_state *plane_state = pipe_ctx->plane_state; - struct hubp *hubp = pipe_ctx->plane_res.hubp; - - if (!pipe_ctx || !plane_state || !pipe_ctx->stream) - continue; - - // Only update scaler and viewport here if we lose a pipe split. - // This is to prevent half the screen from being black when we - // unlock after disconnecting MPCC. - if (!(old_pipe && !pipe_ctx->top_pipe && - !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) - continue; - - if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { - if (pipe_ctx->update_flags.bits.scaler || - plane_state->update_flags.bits.scaling_change || - plane_state->update_flags.bits.position_change || - plane_state->update_flags.bits.per_pixel_alpha_change || - pipe_ctx->stream->update_flags.bits.scaling) { - - pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; - ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); - /* scaler configuration */ - pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( - pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); - } - - if (pipe_ctx->update_flags.bits.viewport || - (context == dc->current_state && plane_state->update_flags.bits.position_change) || - (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || - (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { - - hubp->funcs->mem_program_viewport( - hubp, - &pipe_ctx->plane_res.scl_data.viewport, - &pipe_ctx->plane_res.scl_data.viewport_c); - } - } - } - } - return mpcc_disconnected; -} - -void dcn20_wait_for_pending_cleared(struct dc *dc, - struct dc_state *context) -{ - struct pipe_ctx *pipe_ctx; - struct timing_generator *tg; - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe_ctx = &context->res_ctx.pipe_ctx[i]; - tg = pipe_ctx->stream_res.tg; - - /* - * Only wait for top pipe's tg penindg bit - * Also skip if pipe is disabled. - */ - if (pipe_ctx->top_pipe || - !pipe_ctx->stream || !pipe_ctx->plane_state || - !tg->funcs->is_tg_enabled(tg)) - continue; - - /* - * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. - * For some reason waiting for OTG_UPDATE_PENDING cleared - * seems to not trigger the update right away, and if we - * lock again before VUPDATE then we don't get a separated - * operation. - */ - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); - } -} - void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 7befd35a23596..83220e34c1a92 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -131,13 +131,6 @@ void dcn20_dccg_init(struct dce_hwseq *hws); int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); -bool dcn20_disconnect_pipes( - struct dc *dc, - struct dc_state *context); - -void dcn20_wait_for_pending_cleared(struct dc *dc, - struct dc_state *context); - #ifndef TRIM_FSFT bool dcn20_optimize_timing_for_fsft(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 55afb70d33e5b..3dde6f26de474 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,8 +34,6 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 264302b27d4ff..b187f71afa652 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,8 +35,6 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 845aaf1c816c9..9afee71604902 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,8 +35,6 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 64c1be818b0e8..3c986717dcd56 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,10 +67,6 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); - bool (*disconnect_pipes)(struct dc *dc, - struct dc_state *context); - void (*wait_for_pending_cleared)(struct dc *dc, - struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- GitLab From c0c96fc9c2ca845c2d79006c543e337a31969ac2 Mon Sep 17 00:00:00 2001 From: Xiaodong Yan <Xiaodong.Yan@amd.com> Date: Tue, 28 Jul 2020 18:12:45 +0800 Subject: [PATCH 0377/1494] drm/amd/display: mpcc black color should not be impacted by pixel encoding format [Why] The format in MPCC should be 444 [How] do not modify the mpcc black color according to pixel encoding format Signed-off-by: Xiaodong Yan <Xiaodong.Yan@amd.com> Reviewed-by: Eric Yang <eric.yang2@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a643927e272bd..57cd527896062 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2368,14 +2368,6 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) &blnd_cfg.black_color); } - /* - * The way 420 is packed, 2 channels carry Y component, 1 channel - * alternate between Cb and Cr, so both channels need the pixel - * value for Y - */ - if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - blnd_cfg.black_color.color_r_cr = blnd_cfg.black_color.color_g_y; - if (per_pixel_alpha) blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; else -- GitLab From 575da8db31572d1d8de572d0b6ffb113624c2f8f Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Wed, 29 Jul 2020 17:33:27 -0400 Subject: [PATCH 0378/1494] drm/amd/display: Fix LFC multiplier changing erratically [Why] 1. There is a calculation that is using frame_time_in_us instead of last_render_time_in_us to calculate whether choosing an LFC multiplier would cause the inserted frame duration to be outside of range. 2. We do not handle unsigned integer subtraction correctly and it underflows to a really large value, which causes some logic errors. [How] 1. Fix logic to calculate 'within range' using last_render_time_in_us 2. Split out delta_from_mid_point_delta_in_us calculation to ensure we don't underflow and wrap around Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/modules/freesync/freesync.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 81820f3d6b3b4..d988533d4af5f 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -324,22 +324,44 @@ static void apply_below_the_range(struct core_freesync *core_freesync, /* Choose number of frames to insert based on how close it * can get to the mid point of the variable range. + * - Delta for CEIL: delta_from_mid_point_in_us_1 + * - Delta for FLOOR: delta_from_mid_point_in_us_2 */ - if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us && - (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 || - mid_point_frames_floor < 2)) { + if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { + /* Check for out of range. + * If using CEIL produces a value that is out of range, + * then we are forced to use FLOOR. + */ + frames_to_insert = mid_point_frames_floor; + } else if (mid_point_frames_floor < 2) { + /* Check if FLOOR would result in non-LFC. In this case + * choose to use CEIL + */ + frames_to_insert = mid_point_frames_ceil; + } else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + /* If choosing CEIL results in a frame duration that is + * closer to the mid point of the range. + * Choose CEIL + */ frames_to_insert = mid_point_frames_ceil; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - - delta_from_mid_point_in_us_1; } else { + /* If choosing FLOOR results in a frame duration that is + * closer to the mid point of the range. + * Choose FLOOR + */ frames_to_insert = mid_point_frames_floor; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - - delta_from_mid_point_in_us_2; } /* Prefer current frame multiplier when BTR is enabled unless it drifts * too far from the midpoint */ + if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - + delta_from_mid_point_in_us_1; + } else { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - + delta_from_mid_point_in_us_2; + } if (in_out_vrr->btr.frames_to_insert != 0 && delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) { if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < -- GitLab From 073e7cd56d04110792a7a16b344d8b462178cadb Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Wed, 29 Jul 2020 17:43:10 -0400 Subject: [PATCH 0379/1494] drm/amd/display: Switch to immediate mode for updating infopackets [Why] Using FRAME_UPDATE will result in infopacket to be potentially updated one frame late. In commit stream scenarios for previously active stream, some stale infopacket data from previous config might be erroneously sent out on initial frame after stream is re-enabled. [How] Switch to using IMMEDIATE_UPDATE mode Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Ashley Thomas <Ashley.Thomas2@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/dcn10/dcn10_stream_encoder.c | 16 ++++++++-------- .../amd/display/dc/dcn10/dcn10_stream_encoder.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 07b2f9399671d..842abb4c475bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -121,35 +121,35 @@ void enc1_update_generic_info_packet( switch (packet_index) { case 0: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC0_FRAME_UPDATE, 1); + AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); break; case 1: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC1_FRAME_UPDATE, 1); + AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); break; case 2: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC2_FRAME_UPDATE, 1); + AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); break; case 3: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC3_FRAME_UPDATE, 1); + AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); break; case 4: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_FRAME_UPDATE, 1); + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); break; case 5: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC5_FRAME_UPDATE, 1); + AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); break; case 6: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC6_FRAME_UPDATE, 1); + AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); break; case 7: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_FRAME_UPDATE, 1); + AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index ed385b1477be7..30eae7459d509 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -281,7 +281,14 @@ struct dcn10_stream_enc_registers { SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ @@ -345,7 +352,14 @@ struct dcn10_stream_enc_registers { type AFMT_GENERIC2_FRAME_UPDATE;\ type AFMT_GENERIC3_FRAME_UPDATE;\ type AFMT_GENERIC4_FRAME_UPDATE;\ + type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ type AFMT_GENERIC5_FRAME_UPDATE;\ type AFMT_GENERIC6_FRAME_UPDATE;\ type AFMT_GENERIC7_FRAME_UPDATE;\ -- GitLab From 81b437f57e35a6caa3a4304e6fff0eba0a9f3266 Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Wed, 29 Jul 2020 23:08:59 -0400 Subject: [PATCH 0380/1494] drm/amd/display: Disconnect pipe separetely when disable pipe split [Why] When changing pixel formats for HDR (e.g. ARGB -> FP16) there are configurations that change from 2 pipes to 1 pipe. In these cases, it seems that disconnecting MPCC and doing a surface update at the same time(after unlocking) causes some registers to be updated slightly faster than others after unlocking (e.g. if the pixel format is updated to FP16 before the new surface address is programmed, we get corruption on the screen because the pixel formats aren't matching). We separate disconnecting MPCC from the rest of the pipe programming sequence to prevent this. [How] Move MPCC disconnect into separate operation than the rest of the pipe programming. Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 146 ++++++++++++++++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 6 + .../gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 2 + .../gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 + .../gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 + .../gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 8 files changed, 174 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5aa3b89471c31..ebbb8182228d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,6 +2300,7 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { + bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2330,6 +2331,15 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && + dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ + dc->hwss.interdependent_update_lock(dc, context, true); + mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); + } + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 57cd527896062..95e9d05f884b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2752,6 +2752,152 @@ static struct pipe_ctx *dcn10_find_top_pipe_for_stream( return NULL; } +bool dcn10_disconnect_pipes( + struct dc *dc, + struct dc_state *context) +{ + bool found_stream = false; + int i, j; + struct dce_hwseq *hws = dc->hwseq; + struct dc_state *old_ctx = dc->current_state; + bool mpcc_disconnected = false; + struct pipe_ctx *old_pipe; + struct pipe_ctx *new_pipe; + DC_LOGGER_INIT(dc->ctx->logger); + + /* Set pipe update flags and lock pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + new_pipe = &context->res_ctx.pipe_ctx[i]; + new_pipe->update_flags.raw = 0; + + if (!old_pipe->plane_state && !new_pipe->plane_state) + continue; + + if (old_pipe->plane_state && !new_pipe->plane_state) + new_pipe->update_flags.bits.disable = 1; + + /* Check for scl update */ + if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data))) + new_pipe->update_flags.bits.scaler = 1; + + /* Check for vp update */ + if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect)) + || memcmp(&old_pipe->plane_res.scl_data.viewport_c, + &new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect))) + new_pipe->update_flags.bits.viewport = 1; + + } + + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + /* Disconnect mpcc here only if losing pipe split*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && + old_ctx->res_ctx.pipe_ctx[i].top_pipe) { + + /* Find the top pipe in the new ctx for the bottom pipe that we + * want to remove by comparing the streams. If both pipes are being + * disabled then do it in the regular pipe programming sequence + */ + for (j = 0; j < dc->res_pool->pipe_count; j++) { + if (old_ctx->res_ctx.pipe_ctx[i].top_pipe->stream == context->res_ctx.pipe_ctx[j].stream && + !context->res_ctx.pipe_ctx[j].top_pipe && + !context->res_ctx.pipe_ctx[j].update_flags.bits.disable) { + found_stream = true; + break; + } + } + + // Disconnect if the top pipe lost it's pipe split + if (found_stream && !context->res_ctx.pipe_ctx[j].bottom_pipe) { + hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); + mpcc_disconnected = true; + } + } + found_stream = false; + } + } + + if (mpcc_disconnected) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + + if (!pipe_ctx || !plane_state || !pipe_ctx->stream) + continue; + + // Only update scaler and viewport here if we lose a pipe split. + // This is to prevent half the screen from being black when we + // unlock after disconnecting MPCC. + if (!(old_pipe && !pipe_ctx->top_pipe && + !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) + continue; + + if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { + if (pipe_ctx->update_flags.bits.scaler || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change || + plane_state->update_flags.bits.per_pixel_alpha_change || + pipe_ctx->stream->update_flags.bits.scaling) { + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; + ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); + /* scaler configuration */ + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + } + + if (pipe_ctx->update_flags.bits.viewport || + (context == dc->current_state && plane_state->update_flags.bits.position_change) || + (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || + (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { + + hubp->funcs->mem_program_viewport( + hubp, + &pipe_ctx->plane_res.scl_data.viewport, + &pipe_ctx->plane_res.scl_data.viewport_c); + } + } + } + } + return mpcc_disconnected; +} + +void dcn10_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *pipe_ctx; + struct timing_generator *tg; + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + tg = pipe_ctx->stream_res.tg; + + /* + * Only wait for top pipe's tg penindg bit + * Also skip if pipe is disabled. + */ + if (pipe_ctx->top_pipe || + !pipe_ctx->stream || !pipe_ctx->plane_state || + !tg->funcs->is_tg_enabled(tg)) + continue; + + /* + * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. + * For some reason waiting for OTG_UPDATE_PENDING cleared + * seems to not trigger the update right away, and if we + * lock again before VUPDATE then we don't get a separated + * operation. + */ + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + } +} + void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 6d891166da8a4..e5691e4990231 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -194,6 +194,12 @@ void dcn10_get_surface_visual_confirm_color( void dcn10_get_hdr_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); +bool dcn10_disconnect_pipes( + struct dc *dc, + struct dc_state *context); + +void dcn10_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context); void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx); void dcn10_verify_allow_pstate_change_high(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 5c98b71c1d47a..a1d1559bb5d73 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 3dde6f26de474..966e1790b9bfd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index b187f71afa652..2ba880c3943c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 9afee71604902..19daa456e3bfe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 3c986717dcd56..64c1be818b0e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,10 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); + bool (*disconnect_pipes)(struct dc *dc, + struct dc_state *context); + void (*wait_for_pending_cleared)(struct dc *dc, + struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- GitLab From 57321eae08d67c6cce0030b37812b64417569f12 Mon Sep 17 00:00:00 2001 From: Stylon Wang <stylon.wang@amd.com> Date: Tue, 28 Jul 2020 15:10:35 +0800 Subject: [PATCH 0381/1494] drm/amd/display: Fix EDID parsing after resume from suspend [Why] Resuming from suspend, CEA blocks from EDID are not parsed and no video modes can support YUV420. When this happens, output bpc cannot go over 8-bit with 4K modes on HDMI. [How] In amdgpu_dm_update_connector_after_detect(), drm_add_edid_modes() is called after drm_connector_update_edid_property() to fully parse EDID and update display info. Cc: stable@vger.kernel.org Signed-off-by: Stylon Wang <stylon.wang@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8f27bebf46337..68b88c97014b7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2202,6 +2202,7 @@ void amdgpu_dm_update_connector_after_detect( drm_connector_update_edid_property(connector, aconnector->edid); + drm_add_edid_modes(connector, aconnector->edid); if (aconnector->dc_link->aux_mode) drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, -- GitLab From 8db2d634ed29eeaed56fdbeaf63da7ae9e65280b Mon Sep 17 00:00:00 2001 From: Jaehyun Chung <jaehyun.chung@amd.com> Date: Thu, 30 Jul 2020 16:31:29 -0400 Subject: [PATCH 0382/1494] drm/amd/display: Blank stream before destroying HDCP session [Why] Stream disable sequence incorretly destroys HDCP session while stream is not blanked and while audio is not muted. This sequence causes a flash of corruption during mode change and an audio click. [How] Change sequence to blank stream before destroying HDCP session. Audio will also be muted by blanking the stream. Cc: stable@vger.kernel.org Signed-off-by: Jaehyun Chung <jaehyun.chung@amd.com> Reviewed-by: Alvin Lee <Alvin.Lee2@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4bd6e03a7ef37..117d8aaf2a9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,12 +3286,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } + dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif - dc->hwss.blank_stream(pipe_ctx); - if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- GitLab From fbd7cda0e61e25a5714d7b3b4dd3524271bc2245 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa <daniel@octaforge.org> Date: Sat, 8 Aug 2020 22:42:35 +0200 Subject: [PATCH 0383/1494] drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal GFP_KERNEL may and will sleep, and this is being executed in a non-preemptible context; this will mess things up since it's called inbetween DC_FP_START/END, and rescheduling will result in the DC_FP_END later being called in a different context (or just crashing if any floating point/vector registers/instructions are used after the call is resumed in a different context). Signed-off-by: Daniel Kolesa <daniel@octaforge.org> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 991eddd109522..c31d1f30e505d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3141,7 +3141,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co int vlevel = 0; int pipe_split_from[MAX_PIPES]; int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); DC_LOGGER_INIT(dc->ctx->logger); BW_VAL_TRACE_COUNT(); -- GitLab From c38d444e44badc557cf29fdfdfb823604890ccfa Mon Sep 17 00:00:00 2001 From: Daniel Kolesa <daniel@octaforge.org> Date: Sat, 8 Aug 2020 22:44:58 +0200 Subject: [PATCH 0384/1494] drm/amd/display: add DCN support for aarch64 This adds ARM64 support into the DCN. This mainly enables support for Navi graphics cards. The dcn10 changes haven't been tested, since I don't have the relevant hardware available, but there is no way to conditionally disable them, so I've done them anyway. Signed-off-by: Daniel Kolesa <daniel@octaforge.org> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/Kconfig | 2 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 7 ++ .../gpu/drm/amd/display/dc/clk_mgr/Makefile | 7 ++ drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 7 ++ .../drm/amd/display/dc/dcn10/dcn10_resource.c | 81 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 4 + drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 4 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 13 +++ drivers/gpu/drm/amd/display/dc/dsc/Makefile | 5 ++ drivers/gpu/drm/amd/display/dc/os_types.h | 4 + 10 files changed, 102 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 77569097a480a..f24abf428534e 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -6,7 +6,7 @@ config DRM_AMD_DC bool "AMD DC - Enable new display engine" default y select SND_HDA_COMPONENT if SND_HDA_CORE - select DRM_AMD_DC_DCN if (X86 || PPC64) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS) + select DRM_AMD_DC_DCN if (X86 || PPC64 || (ARM64 && KERNEL_MODE_NEON)) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS) help Choose this option if you want to use the new display engine support for AMDGPU. This adds required support for Vega and diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4674aca8f2069..64f515d744103 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -33,6 +33,10 @@ ifdef CONFIG_PPC64 calcs_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +calcs_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -53,6 +57,9 @@ endif CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_ccflags) CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_ccflags) CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_rcflags) BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 52b1ce775a1e8..1a495759a0343 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -104,6 +104,13 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute) endif +# prevent build errors: +# ...: '-mgeneral-regs-only' is incompatible with the use of floating-point types +# this file is unused on arm64, just like on ppc64 +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := -mgeneral-regs-only +endif + AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 62ad1a11bff9c..733e6e6e43bd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -31,4 +31,11 @@ DCN10 = dcn10_init.o dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) +# fix: +# ...: '-mgeneral-regs-only' is incompatible with the use of floating-point types +# aarch64 does not support soft-float, so use hard-float and handle this in code +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn10/dcn10_resource.o := -mgeneral-regs-only +endif + AMD_DISPLAY_FILES += $(AMD_DAL_DCN10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 17d5cb422025e..07571f84e0f87 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1331,6 +1331,47 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } +/* + * Some architectures don't support soft-float (e.g. aarch64), on those + * this function has to be called with hardfloat enabled, make sure not + * to inline it so whatever fp stuff is done stays inside + */ +static noinline void dcn10_resource_construct_fp( + struct dc *dc) +{ + if (dc->ctx->dce_version == DCN_VERSION_1_01) { + struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; + struct dcn_ip_params *dcn_ip = dc->dcn_ip; + struct display_mode_lib *dml = &dc->dml; + + dml->ip.max_num_dpp = 3; + /* TODO how to handle 23.84? */ + dcn_soc->dram_clock_change_latency = 23; + dcn_ip->max_num_dpp = 3; + } + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc->urgent_latency = 3; + dc->debug.disable_dmcu = true; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + } + + + dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc->number_of_channels < 3); + if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc->number_of_channels = 2; + + if (dc->dcn_soc->number_of_channels == 1) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + } + } +} + static bool dcn10_resource_construct( uint8_t num_virtual_links, struct dc *dc, @@ -1482,37 +1523,15 @@ static bool dcn10_resource_construct( memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); - if (dc->ctx->dce_version == DCN_VERSION_1_01) { - struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; - struct dcn_ip_params *dcn_ip = dc->dcn_ip; - struct display_mode_lib *dml = &dc->dml; - - dml->ip.max_num_dpp = 3; - /* TODO how to handle 23.84? */ - dcn_soc->dram_clock_change_latency = 23; - dcn_ip->max_num_dpp = 3; - } - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->urgent_latency = 3; - dc->debug.disable_dmcu = true; - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; - } - - - dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc->number_of_channels < 3); - if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc->number_of_channels = 2; - - if (dc->dcn_soc->number_of_channels == 1) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; - dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; - } - } +#if defined(CONFIG_ARM64) + /* Aarch64 does not support -msoft-float/-mfloat-abi=soft */ + DC_FP_START(); + dcn10_resource_construct_fp(dc); + DC_FP_END(); +#else + /* Other architectures we build for build this with soft-float */ + dcn10_resource_construct_fp(dc); +#endif pool->base.pp_smu = dcn10_pp_smu_create(ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 5fcaf78334ff9..624cb1341ef14 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -17,6 +17,10 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index 07684d3e375ab..51a2f3d4c194b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -13,6 +13,10 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 417331438c306..dbc7e2abe3795 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -33,6 +33,10 @@ ifdef CONFIG_PPC64 dml_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +dml_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -60,6 +64,13 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_rcflags) endif ifdef CONFIG_DRM_AMD_DC_DCN3_0 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) -Wframe-larger-than=2048 @@ -67,6 +78,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) endif CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_rcflags) DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile index ea29cf95d470b..f2624a1156e5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile @@ -10,6 +10,10 @@ ifdef CONFIG_PPC64 dsc_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +dsc_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -28,6 +32,7 @@ endif endif CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags) DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index c3bbfe397e8df..330acaaed79ae 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -55,6 +55,10 @@ #include <asm/fpu/api.h> #define DC_FP_START() kernel_fpu_begin() #define DC_FP_END() kernel_fpu_end() +#elif defined(CONFIG_ARM64) +#include <asm/neon.h> +#define DC_FP_START() kernel_neon_begin() +#define DC_FP_END() kernel_neon_end() #elif defined(CONFIG_PPC64) #include <asm/switch_to.h> #include <asm/cputable.h> -- GitLab From 200b86f9891b87ff1709e1dca4efe9d2ee06154d Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 10 Aug 2020 11:55:32 -0400 Subject: [PATCH 0385/1494] drm/amdgpu/display: drop unused function This is not longer used as of the latest rework of this code so drop it to avoid a unused function warning. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 68b88c97014b7..031b7eb553569 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2827,24 +2827,6 @@ dm_atomic_get_new_state(struct drm_atomic_state *state) return NULL; } -static struct dm_atomic_state * -dm_atomic_get_old_state(struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; - struct drm_private_obj *obj; - struct drm_private_state *old_obj_state; - int i; - - for_each_old_private_obj_in_state(state, obj, old_obj_state, i) { - if (obj->funcs == dm->atomic_obj.funcs) - return to_dm_atomic_state(old_obj_state); - } - - return NULL; -} - static struct drm_private_state * dm_atomic_duplicate_state(struct drm_private_obj *obj) { -- GitLab From d6e6dfb287443b4197afde4632784ba640944648 Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 10 Aug 2020 20:59:19 +0800 Subject: [PATCH 0386/1494] drm/amd/display: convert to use le16_add_cpu() Convert cpu_to_le16(le16_to_cpu(E1) + E2) to use le16_add_cpu(). Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/bios/command_table.c | 4 +--- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 5815983caaf80..070459e3e4070 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -1877,9 +1877,7 @@ static enum bp_result set_crtc_using_dtd_timing_v3( * but it is 4 either from Edid data (spec CEA 861) * or CEA timing table. */ - params.usV_SyncOffset = - cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1); - + le16_add_cpu(¶ms.usV_SyncOffset, 1); } } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index bed91572f82a6..e8f52eb8ef0d8 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -569,10 +569,7 @@ static enum bp_result set_crtc_using_dtd_timing_v3( * but it is 4 either from Edid data (spec CEA 861) * or CEA timing table. */ - params.v_syncoffset = - cpu_to_le16(le16_to_cpu(params.v_syncoffset) + - 1); - + le16_add_cpu(¶ms.v_syncoffset, 1); } } -- GitLab From a343160235f59b5baacaecba7b7ee14abe8ae034 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Mon, 10 Aug 2020 15:39:20 +1000 Subject: [PATCH 0387/1494] drm/vmwgfx/ttm: fix the non-THP cleanup path. I fixed the init path, but missed the cleanup path. Fixes: e0830704de7c ("drm/vmwgfx: takedown vram manager") Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200810054110.4192239-1-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index a68ae0204bf52..2c4858ea89b1c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -639,7 +639,7 @@ static void vmw_vram_manager_fini(struct vmw_private *dev_priv) #ifdef CONFIG_TRANSPARENT_HUGEPAGE vmw_thp_fini(dev_priv); #else - ttm_bo_man_fini(&dev_priv->bdev, TTM_PL_VRAM); + ttm_range_man_fini(&dev_priv->bdev, TTM_PL_VRAM); #endif } -- GitLab From e5b92773287c3eb3108a44785986a6c997866df8 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@intel.com> Date: Fri, 24 Apr 2020 18:20:51 +0530 Subject: [PATCH 0388/1494] drm: report dp downstream port type as a subconnector property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, downstream port type is only reported in debugfs. This information should be considered important since it reflects the actual physical connector type. Some userspace (e.g. window compositors) may want to show this info to a user. The 'subconnector' property is already utilized for DVI-I and TV-out for reporting connector subtype. The initial motivation for this feature came from i2c test [1]. It is supposed to be skipped on VGA connectors, but it cannot detect VGA over DP and fails instead. v2: - Ville: utilized drm_dp_is_branch() - Ville: implement DP 1.0 downstream type info - Replaced create_dp_properties with add_dp_subconnector_property - Added dp_set_subconnector_property helper v4: - Ville: add DP1.0 best assumption about subconnector - Ville: assume DVI is DVI-D - Ville: reuse Writeback enum value for Virtual subconnector - Renamed #defines: HDMI -> HDMIA, DP -> DisplayPort v5: rebase v6: - Jani Nikula: renamed a function name - Jani Nikula: addressed the issues with documentation [1]: https://bugs.freedesktop.org/show_bug.cgi?id=104097 Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Jeevan B <jeevan.b@intel.com> Signed-off-by: Oleg Vasilev <oleg.vasilev@intel.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1587732655-17544-1-git-send-email-jeevan.b@intel.com --- drivers/gpu/drm/drm_connector.c | 49 ++++++++++++++++++++++- drivers/gpu/drm/drm_dp_helper.c | 71 +++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 3 ++ include/drm/drm_dp_helper.h | 8 ++++ include/drm/drm_mode_config.h | 6 +++ include/uapi/drm/drm_mode.h | 21 ++++++---- 6 files changed, 148 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 00e40a26a8004..3d48ad1c36823 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -850,7 +850,7 @@ static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ }; @@ -867,7 +867,7 @@ static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { - { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ @@ -876,6 +876,19 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, drm_tv_subconnector_enum_list) +static const struct drm_prop_enum_list drm_dp_subconnector_enum_list[] = { + { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I, TV-out and DP */ + { DRM_MODE_SUBCONNECTOR_VGA, "VGA" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_HDMIA, "HDMI" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_DisplayPort, "DP" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_Wireless, "Wireless" }, /* DP */ + { DRM_MODE_SUBCONNECTOR_Native, "Native" }, /* DP */ +}; + +DRM_ENUM_NAME_FN(drm_get_dp_subconnector_name, + drm_dp_subconnector_enum_list) + static const struct drm_prop_enum_list hdmi_colorspaces[] = { /* For Default case, driver will set the colorspace */ { DRM_MODE_COLORIMETRY_DEFAULT, "Default" }, @@ -1217,6 +1230,14 @@ static const struct drm_prop_enum_list dp_colorspaces[] = { * can also expose this property to external outputs, in which case they * must support "None", which should be the default (since external screens * have a built-in scaler). + * + * subconnector: + * This property is used by DVI-I, TVout and DisplayPort to indicate different + * connector subtypes. Enum values more or less match with those from main + * connector types. + * For DVI-I and TVout there is also a matching property "select subconnector" + * allowing to switch between signal types. + * DP subconnector corresponds to a downstream port. */ int drm_connector_create_standard_properties(struct drm_device *dev) @@ -1305,6 +1326,30 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); +/** + * drm_connector_attach_dp_subconnector_property - create subconnector property for DP + * @connector: drm_connector to attach property + * + * Called by a driver when DP connector is created. + */ +void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector) +{ + struct drm_mode_config *mode_config = &connector->dev->mode_config; + + if (!mode_config->dp_subconnector_property) + mode_config->dp_subconnector_property = + drm_property_create_enum(connector->dev, + DRM_MODE_PROP_IMMUTABLE, + "subconnector", + drm_dp_subconnector_enum_list, + ARRAY_SIZE(drm_dp_subconnector_enum_list)); + + drm_object_attach_property(&connector->base, + mode_config->dp_subconnector_property, + DRM_MODE_SUBCONNECTOR_Unknown); +} +EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); + /** * DOC: HDMI connector properties * diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index a3c82e726057a..4c21cf69dad5a 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -597,6 +597,77 @@ void drm_dp_downstream_debug(struct seq_file *m, } EXPORT_SYMBOL(drm_dp_downstream_debug); +/** + * drm_dp_subconnector_type() - get DP branch device type + * + */ +enum drm_mode_subconnector +drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + int type; + if (!drm_dp_is_branch(dpcd)) + return DRM_MODE_SUBCONNECTOR_Native; + /* DP 1.0 approach */ + if (dpcd[DP_DPCD_REV] == DP_DPCD_REV_10) { + type = dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_TYPE_MASK; + + switch (type) { + case DP_DWN_STRM_PORT_TYPE_TMDS: + /* Can be HDMI or DVI-D, DVI-D is a safer option */ + return DRM_MODE_SUBCONNECTOR_DVID; + case DP_DWN_STRM_PORT_TYPE_ANALOG: + /* Can be VGA or DVI-A, VGA is more popular */ + return DRM_MODE_SUBCONNECTOR_VGA; + case DP_DWN_STRM_PORT_TYPE_DP: + return DRM_MODE_SUBCONNECTOR_DisplayPort; + case DP_DWN_STRM_PORT_TYPE_OTHER: + default: + return DRM_MODE_SUBCONNECTOR_Unknown; + } + } + type = port_cap[0] & DP_DS_PORT_TYPE_MASK; + + switch (type) { + case DP_DS_PORT_TYPE_DP: + case DP_DS_PORT_TYPE_DP_DUALMODE: + return DRM_MODE_SUBCONNECTOR_DisplayPort; + case DP_DS_PORT_TYPE_VGA: + return DRM_MODE_SUBCONNECTOR_VGA; + case DP_DS_PORT_TYPE_DVI: + return DRM_MODE_SUBCONNECTOR_DVID; + case DP_DS_PORT_TYPE_HDMI: + return DRM_MODE_SUBCONNECTOR_HDMIA; + case DP_DS_PORT_TYPE_WIRELESS: + return DRM_MODE_SUBCONNECTOR_Wireless; + case DP_DS_PORT_TYPE_NON_EDID: + default: + return DRM_MODE_SUBCONNECTOR_Unknown; + } +} +EXPORT_SYMBOL(drm_dp_subconnector_type); + +/** + * drm_mode_set_dp_subconnector_property - set subconnector for DP connector + * + * Called by a driver on every detect event. + */ +void drm_dp_set_subconnector_property(struct drm_connector *connector, + enum drm_connector_status status, + const u8 *dpcd, + const u8 port_cap[4]) +{ + enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + if (status == connector_status_connected) + subconnector = drm_dp_subconnector_type(dpcd, port_cap); + drm_object_property_set_value(&connector->base, + connector->dev->mode_config.dp_subconnector_property, + subconnector); +} +EXPORT_SYMBOL(drm_dp_set_subconnector_property); + /* * I2C-over-AUX implementation */ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index af145608b5ede..928136556174c 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1604,10 +1604,13 @@ const char *drm_get_dvi_i_subconnector_name(int val); const char *drm_get_dvi_i_select_name(int val); const char *drm_get_tv_subconnector_name(int val); const char *drm_get_tv_select_name(int val); +const char *drm_get_dp_subconnector_name(int val); const char *drm_get_content_protection_name(int val); const char *drm_get_hdcp_content_type_name(int val); int drm_mode_create_dvi_i_properties(struct drm_device *dev); +void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector); + int drm_mode_create_tv_margin_properties(struct drm_device *dev); int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index e47dc22ebf503..5c28199248626 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -26,6 +26,7 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/types.h> +#include <drm/drm_connector.h> /* * Unless otherwise noted, all values are from the DP 1.1a spec. Note that @@ -1619,6 +1620,13 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], struct drm_dp_aux *aux); +enum drm_mode_subconnector +drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +void drm_dp_set_subconnector_property(struct drm_connector *connector, + enum drm_connector_status status, + const u8 *dpcd, + const u8 port_cap[4]); void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index ffb9852a06386..f768c7cf7de31 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -680,6 +680,12 @@ struct drm_mode_config { */ struct drm_property *dvi_i_select_subconnector_property; + /** + * @dp_subconnector_property: Optional DP property to differentiate + * between different DP downstream port types. + */ + struct drm_property *dp_subconnector_property; + /** * @tv_subconnector_property: Optional TV property to differentiate * between different TV connector types. diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index deea447e5f22a..863eda0482652 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -332,14 +332,19 @@ struct drm_mode_get_encoder { /* This is for connectors with multiple signal types. */ /* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ enum drm_mode_subconnector { - DRM_MODE_SUBCONNECTOR_Automatic = 0, - DRM_MODE_SUBCONNECTOR_Unknown = 0, - DRM_MODE_SUBCONNECTOR_DVID = 3, - DRM_MODE_SUBCONNECTOR_DVIA = 4, - DRM_MODE_SUBCONNECTOR_Composite = 5, - DRM_MODE_SUBCONNECTOR_SVIDEO = 6, - DRM_MODE_SUBCONNECTOR_Component = 8, - DRM_MODE_SUBCONNECTOR_SCART = 9, + DRM_MODE_SUBCONNECTOR_Automatic = 0, /* DVI-I, TV */ + DRM_MODE_SUBCONNECTOR_Unknown = 0, /* DVI-I, TV, DP */ + DRM_MODE_SUBCONNECTOR_VGA = 1, /* DP */ + DRM_MODE_SUBCONNECTOR_DVID = 3, /* DVI-I DP */ + DRM_MODE_SUBCONNECTOR_DVIA = 4, /* DVI-I */ + DRM_MODE_SUBCONNECTOR_Composite = 5, /* TV */ + DRM_MODE_SUBCONNECTOR_SVIDEO = 6, /* TV */ + DRM_MODE_SUBCONNECTOR_Component = 8, /* TV */ + DRM_MODE_SUBCONNECTOR_SCART = 9, /* TV */ + DRM_MODE_SUBCONNECTOR_DisplayPort = 10, /* DP */ + DRM_MODE_SUBCONNECTOR_HDMIA = 11, /* DP */ + DRM_MODE_SUBCONNECTOR_Native = 15, /* DP */ + DRM_MODE_SUBCONNECTOR_Wireless = 18, /* DP */ }; #define DRM_MODE_CONNECTOR_Unknown 0 -- GitLab From fb82313462bac5567a564d4c725dcf8152d6dc46 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@intel.com> Date: Fri, 24 Apr 2020 18:20:52 +0530 Subject: [PATCH 0389/1494] drm/i915: utilize subconnector property for DP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. v2: updates to match previous commit changes v3: rebase v4: renamed a function call Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: intel-gfx@lists.freedesktop.org Signed-off-by: Jeevan B <jeevan.b@intel.com> Signed-off-by: Oleg Vasilev <oleg.vasilev@intel.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Reviewed-by: Jani Nikula <jani.nikula@intel.com> #and acked for merging Tested-by: Oleg Vasilev <oleg.vasilev@intel.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1587732655-17544-2-git-send-email-jeevan.b@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cc525fda441af..f2c6d835a12fa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6256,6 +6256,11 @@ intel_dp_detect(struct drm_connector *connector, */ intel_display_power_flush_work(dev_priv); + if (!intel_dp_is_edp(intel_dp)) + drm_dp_set_subconnector_property(connector, + status, + intel_dp->dpcd, + intel_dp->downstream_ports); return status; } @@ -7350,6 +7355,9 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect struct drm_i915_private *dev_priv = to_i915(connector->dev); enum port port = dp_to_dig_port(intel_dp)->base.port; + if (!intel_dp_is_edp(intel_dp)) + drm_connector_attach_dp_subconnector_property(connector); + if (!IS_G4X(dev_priv) && port != PORT_A) intel_attach_force_audio_property(connector); -- GitLab From 65bf2cf95d3ade4b56c35b17bb955a64b7f4b019 Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@intel.com> Date: Fri, 24 Apr 2020 18:20:54 +0530 Subject: [PATCH 0390/1494] drm/amdgpu: utilize subconnector property for DP through atombios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. v2: rebase v3: renamed a function call Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Christian König <christian.koenig@amd.com> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com> Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Jeevan B <jeevan.b@intel.com> Signed-off-by: Oleg Vasilev <oleg.vasilev@intel.com> Reviewed-by: Emil Velikov <emil.velikov@collabora.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1587732655-17544-4-git-send-email-jeevan.b@intel.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 1 + drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index f355d9a752d29..8955c4fed8cbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -26,6 +26,7 @@ #include <drm/drm_edid.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_dp_helper.h> #include <drm/drm_probe_helper.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" @@ -1405,6 +1406,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) pm_runtime_put_autosuspend(connector->dev->dev); } + drm_dp_set_subconnector_property(&amdgpu_connector->base, + ret, + amdgpu_dig_connector->dpcd, + amdgpu_dig_connector->downstream_ports); return ret; } @@ -1951,6 +1956,11 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (has_aux) amdgpu_atombios_dp_aux_init(amdgpu_connector); + if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector_type == DRM_MODE_CONNECTOR_eDP) { + drm_connector_attach_dp_subconnector_property(&amdgpu_connector->base); + } + return; failed: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 37ba07e2feb54..04a430e0e2e1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -469,6 +469,7 @@ struct amdgpu_encoder { struct amdgpu_connector_atom_dig { /* displayport */ u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; u8 dp_sink_type; int dp_clock; int dp_lane_count; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 9b74cfdba7b8c..900b2727f432a 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -328,6 +328,22 @@ static void amdgpu_atombios_dp_probe_oui(struct amdgpu_connector *amdgpu_connect buf[0], buf[1], buf[2]); } +static void amdgpu_atombios_dp_ds_ports(struct amdgpu_connector *amdgpu_connector) +{ + struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv; + int ret; + + if (dig_connector->dpcd[DP_DPCD_REV] > 0x10) { + ret = drm_dp_dpcd_read(&amdgpu_connector->ddc_bus->aux, + DP_DOWNSTREAM_PORT_0, + dig_connector->downstream_ports, + DP_MAX_DOWNSTREAM_PORTS); + if (ret) + memset(dig_connector->downstream_ports, 0, + DP_MAX_DOWNSTREAM_PORTS); + } +} + int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) { struct amdgpu_connector_atom_dig *dig_connector = amdgpu_connector->con_priv; @@ -343,7 +359,7 @@ int amdgpu_atombios_dp_get_dpcd(struct amdgpu_connector *amdgpu_connector) dig_connector->dpcd); amdgpu_atombios_dp_probe_oui(amdgpu_connector); - + amdgpu_atombios_dp_ds_ports(amdgpu_connector); return 0; } -- GitLab From 0f877894a330edd4f3bc9ec07a1686ee2d86668d Mon Sep 17 00:00:00 2001 From: Oleg Vasilev <oleg.vasilev@intel.com> Date: Fri, 24 Apr 2020 18:20:55 +0530 Subject: [PATCH 0391/1494] drm/amdgpu: utilize subconnector property for DP through DisplayManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since DP-specific information is stored in driver's structures, every driver needs to implement subconnector property by itself. Display Core already has the subconnector information, we only need to expose it through DRM property. v2:rebase v3: renamed a function call Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Christian König <christian.koenig@amd.com> Cc: David (ChunMing) Zhou <David1.Zhou@amd.com> Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Jeevan B <jeevan.b@intel.com> Signed-off-by: Oleg Vasilev <oleg.vasilev@intel.com> Tested-by: Oleg Vasilev <oleg.vasilev@intel.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1587732655-17544-5-git-send-email-jeevan.b@intel.com --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 ++++++++++++++++++- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 ++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 34731eca5816e..85df5218e053d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -121,6 +121,42 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU); static int amdgpu_dm_init(struct amdgpu_device *adev); static void amdgpu_dm_fini(struct amdgpu_device *adev); +static enum drm_mode_subconnector get_subconnector_type(struct dc_link *link) +{ + switch (link->dpcd_caps.dongle_type) { + case DISPLAY_DONGLE_NONE: + return DRM_MODE_SUBCONNECTOR_Native; + case DISPLAY_DONGLE_DP_VGA_CONVERTER: + return DRM_MODE_SUBCONNECTOR_VGA; + case DISPLAY_DONGLE_DP_DVI_CONVERTER: + case DISPLAY_DONGLE_DP_DVI_DONGLE: + return DRM_MODE_SUBCONNECTOR_DVID; + case DISPLAY_DONGLE_DP_HDMI_CONVERTER: + case DISPLAY_DONGLE_DP_HDMI_DONGLE: + return DRM_MODE_SUBCONNECTOR_HDMIA; + case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE: + default: + return DRM_MODE_SUBCONNECTOR_Unknown; + } +} + +static void update_subconnector_property(struct amdgpu_dm_connector *aconnector) +{ + struct dc_link *link = aconnector->dc_link; + struct drm_connector *connector = &aconnector->base; + enum drm_mode_subconnector subconnector = DRM_MODE_SUBCONNECTOR_Unknown; + + if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + return; + + if (aconnector->dc_sink) + subconnector = get_subconnector_type(link); + + drm_object_property_set_value(&connector->base, + connector->dev->mode_config.dp_subconnector_property, + subconnector); +} + /* * initializes drm_device display related structures, based on the information * provided by DAL. The drm strcutures are: drm_crtc, drm_connector, @@ -2069,7 +2105,6 @@ void amdgpu_dm_update_connector_after_detect( if (aconnector->mst_mgr.mst_state == true) return; - sink = aconnector->dc_link->local_sink; if (sink) dc_sink_retain(sink); @@ -2195,6 +2230,8 @@ void amdgpu_dm_update_connector_after_detect( mutex_unlock(&dev->mode_config.mutex); + update_subconnector_property(aconnector); + if (sink) dc_sink_release(sink); } @@ -4720,6 +4757,8 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force) else connected = (aconnector->base.force == DRM_FORCE_ON); + update_subconnector_property(aconnector); + return (connected ? connector_status_connected : connector_status_disconnected); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ae0a7ef1d595a..f08c1b0703c16 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -26,6 +26,7 @@ #include <linux/version.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_dp_mst_helper.h> +#include <drm/drm_dp_helper.h> #include "dm_services.h" #include "amdgpu.h" #include "amdgpu_dm.h" @@ -432,6 +433,8 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, 16, 4, aconnector->connector_id); + + drm_connector_attach_dp_subconnector_property(&aconnector->base); } int dm_mst_get_pbn_divider(struct dc_link *link) -- GitLab From 0cf0ee983b14af5e2160fa677b2eeb4c5dbb03ad Mon Sep 17 00:00:00 2001 From: Arunpravin <apaneers@amd.com> Date: Thu, 6 Aug 2020 14:34:33 +0530 Subject: [PATCH 0392/1494] drm/amdgpu: Enable P2P dmabuf over XGMI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Access the exported P2P dmabuf over XGMI, if available. Otherwise, fall back to the existing PCIe method. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Arunpravin <apaneers@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 34 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 19 ++++++++++-- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 43d8ed7dbd001..b3a62d5ba4e21 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -35,6 +35,7 @@ #include "amdgpu_display.h" #include "amdgpu_gem.h" #include "amdgpu_dma_buf.h" +#include "amdgpu_xgmi.h" #include <drm/amdgpu_drm.h> #include <linux/dma-buf.h> #include <linux/dma-fence-array.h> @@ -595,3 +596,36 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, obj->import_attach = attach; return obj; } + +/** + * amdgpu_dmabuf_is_xgmi_accessible - Check if xgmi available for P2P transfer + * + * @adev: amdgpu_device pointer of the importer + * @bo: amdgpu buffer object + * + * Returns: + * True if dmabuf accessible over xgmi, false otherwise. + */ +bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct amdgpu_bo *bo) +{ + struct drm_gem_object *obj = &bo->tbo.base; + struct drm_gem_object *gobj; + + if (obj->import_attach) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + + if (dma_buf->ops != &amdgpu_dmabuf_ops) + /* No XGMI with non AMD GPUs */ + return false; + + gobj = dma_buf->priv; + bo = gem_to_amdgpu_bo(gobj); + } + + if (amdgpu_xgmi_same_hive(adev, amdgpu_ttm_adev(bo->tbo.bdev)) && + (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)) + return true; + + return false; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index ec447a7b6b283..2c5c84a06bb93 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -29,6 +29,8 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, int flags); struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); +bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct amdgpu_bo *bo); void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 71e005cf29522..771c27478bb12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -28,6 +28,7 @@ #include <linux/dma-fence-array.h> #include <linux/interval_tree_generic.h> #include <linux/idr.h> +#include <linux/dma-buf.h> #include <drm/amdgpu_drm.h> #include "amdgpu.h" @@ -35,6 +36,7 @@ #include "amdgpu_amdkfd.h" #include "amdgpu_gmc.h" #include "amdgpu_xgmi.h" +#include "amdgpu_dma_buf.h" /** * DOC: GPUVM @@ -1778,15 +1780,24 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, nodes = NULL; resv = vm->root.base.bo->tbo.base.resv; } else { + struct drm_gem_object *obj = &bo->tbo.base; struct ttm_dma_tt *ttm; + resv = bo->tbo.base.resv; + if (obj->import_attach && bo_va->is_xgmi) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + struct drm_gem_object *gobj = dma_buf->priv; + struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); + + if (abo->tbo.mem.mem_type == TTM_PL_VRAM) + bo = gem_to_amdgpu_bo(gobj); + } mem = &bo->tbo.mem; nodes = mem->mm_node; if (mem->mem_type == TTM_PL_TT) { ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); pages_addr = ttm->dma_address; } - resv = bo->tbo.base.resv; } if (bo) { @@ -2132,8 +2143,10 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, INIT_LIST_HEAD(&bo_va->valids); INIT_LIST_HEAD(&bo_va->invalids); - if (bo && amdgpu_xgmi_same_hive(adev, amdgpu_ttm_adev(bo->tbo.bdev)) && - (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)) { + if (!bo) + return bo_va; + + if (amdgpu_dmabuf_is_xgmi_accessible(adev, bo)) { bo_va->is_xgmi = true; /* Power up XGMI if it can be potentially used */ amdgpu_xgmi_set_pstate(adev, AMDGPU_XGMI_PSTATE_MAX_VEGA20); -- GitLab From d2f6a8f454b67ccfa64d1f2e7e2a570bc72313e2 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 00:43:22 +0200 Subject: [PATCH 0393/1494] drm/panel-notatek-nt35510: Fix MTP read init In order to successfully read ID of the MTP panel the panel MTP control page must be unlocked. Previously this wasn't encountered because in the setup with this panel the power wasn't ever really dropped. When power gets dropped from the panel, MTP needs to be unlocked. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Cc: newbytee@protonmail.com Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200808224322.1507713-1-linus.walleij@linaro.org --- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index e67d0955e2152..64c8cf2bae7ca 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -376,6 +376,10 @@ struct nt35510 { }; /* Manufacturer command has strictly this byte sequence */ +static const u8 nt35510_mauc_mtp_read_param[] = { 0xAA, 0x55, 0x25, 0x01 }; +static const u8 nt35510_mauc_mtp_read_setting[] = { 0x01, 0x02, 0x00, 0x20, + 0x33, 0x13, 0x00, 0x40, + 0x00, 0x00, 0x23, 0x02 }; static const u8 nt35510_mauc_select_page_0[] = { 0x55, 0xAA, 0x52, 0x08, 0x00 }; static const u8 nt35510_mauc_select_page_1[] = { 0x55, 0xAA, 0x52, 0x08, 0x01 }; static const u8 nt35510_vgh_on[] = { 0x01 }; @@ -698,6 +702,18 @@ static int nt35510_power_on(struct nt35510 *nt) usleep_range(120000, 140000); } + ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_PARAM, + ARRAY_SIZE(nt35510_mauc_mtp_read_param), + nt35510_mauc_mtp_read_param); + if (ret) + return ret; + + ret = nt35510_send_long(nt, dsi, MCS_CMD_MTP_READ_SETTING, + ARRAY_SIZE(nt35510_mauc_mtp_read_setting), + nt35510_mauc_mtp_read_setting); + if (ret) + return ret; + ret = nt35510_read_id(nt); if (ret) return ret; -- GitLab From ed7d94597fad747ff0be4a0045da79e7ddd6eba0 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 12 Aug 2020 15:42:58 +0800 Subject: [PATCH 0394/1494] drm/hisilicon: Remove the unused include statements Remove some unused include statements. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597218179-3938-2-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 3 --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 5 ----- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 2 -- 3 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index cc70e836522f0..66132eb232ed9 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -17,9 +17,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_vram_helper.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_print.h> -#include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include "hibmc_drm_drv.h" diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index b8d839a1c4598..54f61444ef881 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -11,18 +11,13 @@ * Jianhua Li <lijianhua@huawei.com> */ -#include <linux/console.h> -#include <linux/module.h> #include <linux/pci.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_gem_vram_helper.h> #include <drm/drm_irq.h> #include <drm/drm_managed.h> -#include <drm/drm_print.h> -#include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> #include "hibmc_drm_drv.h" diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 2ca69c38491ab..ed12f61cf46ea 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -11,10 +11,8 @@ * Jianhua Li <lijianhua@huawei.com> */ -#include <drm/drm_gem_vram_helper.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_crtc_helper.h> #include <drm/drm_print.h> #include "hibmc_drm_drv.h" -- GitLab From 13b0d4a9ae0c2d650993c48be797992eaf621332 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 12 Aug 2020 15:42:59 +0800 Subject: [PATCH 0395/1494] drm/hisilicon: Code refactoring for hibmc_drv_de The memory used to be allocated with devres helpers and released automatically. In rare circumstances, the memory's release could have happened before the DRM device got released, which would have caused memory corruption of some kind. Now we're embedding the data structures in struct hibmc_drm_private. The whole release problem has been resolved, because struct hibmc_drm_private is allocated with drmm_kzalloc and always released with the DRM device. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597218179-3938-3-git-send-email-tiantao6@hisilicon.com --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 55 +++++-------------- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 + 2 files changed, 15 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 66132eb232ed9..d9062a3f5b82d 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -157,37 +157,6 @@ static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = { .atomic_update = hibmc_plane_atomic_update, }; -static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv) -{ - struct drm_device *dev = priv->dev; - struct drm_plane *plane; - int ret = 0; - - plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL); - if (!plane) { - DRM_ERROR("failed to alloc memory when init plane\n"); - return ERR_PTR(-ENOMEM); - } - /* - * plane init - * TODO: Now only support primary plane, overlay planes - * need to do. - */ - ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs, - channel_formats1, - ARRAY_SIZE(channel_formats1), - NULL, - DRM_PLANE_TYPE_PRIMARY, - NULL); - if (ret) { - DRM_ERROR("failed to init plane: %d\n", ret); - return ERR_PTR(ret); - } - - drm_plane_helper_add(plane, &hibmc_plane_helper_funcs); - return plane; -} - static void hibmc_crtc_dpms(struct drm_crtc *crtc, int dpms) { struct hibmc_drm_private *priv = crtc->dev->dev_private; @@ -534,22 +503,24 @@ static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = { int hibmc_de_init(struct hibmc_drm_private *priv) { struct drm_device *dev = priv->dev; - struct drm_crtc *crtc; - struct drm_plane *plane; + struct drm_crtc *crtc = &priv->crtc; + struct drm_plane *plane = &priv->primary_plane; int ret; - plane = hibmc_plane_init(priv); - if (IS_ERR(plane)) { - DRM_ERROR("failed to create plane: %ld\n", PTR_ERR(plane)); - return PTR_ERR(plane); - } + ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs, + channel_formats1, + ARRAY_SIZE(channel_formats1), + NULL, + DRM_PLANE_TYPE_PRIMARY, + NULL); - crtc = devm_kzalloc(dev->dev, sizeof(*crtc), GFP_KERNEL); - if (!crtc) { - DRM_ERROR("failed to alloc memory when init crtc\n"); - return -ENOMEM; + if (ret) { + DRM_ERROR("failed to init plane: %d\n", ret); + return ret; } + drm_plane_helper_add(plane, &hibmc_plane_helper_funcs); + ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &hibmc_crtc_funcs, NULL); if (ret) { diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index a6837637af2a4..197485e2fe0b2 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -28,6 +28,8 @@ struct hibmc_drm_private { /* drm */ struct drm_device *dev; + struct drm_plane primary_plane; + struct drm_crtc crtc; struct drm_encoder encoder; struct drm_connector connector; bool mode_config_initialized; -- GitLab From e92ae67d6ed881e9c6d6d432eb6b5817f150a115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 3 Aug 2020 15:06:38 +0200 Subject: [PATCH 0396/1494] drm/ttm: rename ttm_resource_manager_func callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The names get/put are associated with reference counting in the Linux kernel, use alloc/free instead. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/384340/?series=80346&rev=1 --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 6 +++--- drivers/gpu/drm/nouveau/nouveau_ttm.c | 12 ++++++------ drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++---- drivers/gpu/drm/ttm/ttm_range_manager.c | 16 ++++++++-------- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 4 ++-- include/drm/ttm/ttm_bo_driver.h | 18 +++++++++--------- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 010518148ef89..bab8feed46da5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -311,7 +311,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, } static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { - .get_node = amdgpu_gtt_mgr_new, - .put_node = amdgpu_gtt_mgr_del, + .alloc = amdgpu_gtt_mgr_new, + .free = amdgpu_gtt_mgr_del, .debug = amdgpu_gtt_mgr_debug }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 7882efd275d19..ff70ae00e602c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -606,7 +606,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, } static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = { - .get_node = amdgpu_vram_mgr_new, - .put_node = amdgpu_vram_mgr_del, - .debug = amdgpu_vram_mgr_debug + .alloc = amdgpu_vram_mgr_new, + .free = amdgpu_vram_mgr_del, + .debug = amdgpu_vram_mgr_debug }; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index e6a30865a00bb..53c6f88273228 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -64,8 +64,8 @@ nouveau_vram_manager_new(struct ttm_resource_manager *man, } const struct ttm_resource_manager_func nouveau_vram_manager = { - .get_node = nouveau_vram_manager_new, - .put_node = nouveau_manager_del, + .alloc = nouveau_vram_manager_new, + .free = nouveau_manager_del, }; static int @@ -87,8 +87,8 @@ nouveau_gart_manager_new(struct ttm_resource_manager *man, } const struct ttm_resource_manager_func nouveau_gart_manager = { - .get_node = nouveau_gart_manager_new, - .put_node = nouveau_manager_del, + .alloc = nouveau_gart_manager_new, + .free = nouveau_manager_del, }; static int @@ -119,8 +119,8 @@ nv04_gart_manager_new(struct ttm_resource_manager *man, } const struct ttm_resource_manager_func nv04_gart_manager = { - .get_node = nv04_gart_manager_new, - .put_node = nouveau_manager_del, + .alloc = nv04_gart_manager_new, + .free = nouveau_manager_del, }; int diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ad09329b62d30..ae71c3ab6cc44 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -846,20 +846,20 @@ static int ttm_bo_mem_get(struct ttm_buffer_object *bo, struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); mem->mm_node = NULL; - if (!man->func || !man->func->get_node) + if (!man->func || !man->func->alloc) return 0; - return man->func->get_node(man, bo, place, mem); + return man->func->alloc(man, bo, place, mem); } void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_resource *mem) { struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); - if (!man->func || !man->func->put_node) + if (!man->func || !man->func->free) return; - man->func->put_node(man, mem); + man->func->free(man, mem); mem->mm_node = NULL; mem->mem_type = TTM_PL_SYSTEM; } diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index 274a05ca13d3b..770c8988c1397 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -54,10 +54,10 @@ static inline struct ttm_range_manager *to_range_manager(struct ttm_resource_man return container_of(man, struct ttm_range_manager, manager); } -static int ttm_range_man_get_node(struct ttm_resource_manager *man, - struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_resource *mem) +static int ttm_range_man_alloc(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *mem) { struct ttm_range_manager *rman = to_range_manager(man); struct drm_mm *mm = &rman->mm; @@ -95,8 +95,8 @@ static int ttm_range_man_get_node(struct ttm_resource_manager *man, return ret; } -static void ttm_range_man_put_node(struct ttm_resource_manager *man, - struct ttm_resource *mem) +static void ttm_range_man_free(struct ttm_resource_manager *man, + struct ttm_resource *mem) { struct ttm_range_manager *rman = to_range_manager(man); @@ -181,7 +181,7 @@ static void ttm_range_man_debug(struct ttm_resource_manager *man, } static const struct ttm_resource_manager_func ttm_range_manager_func = { - .get_node = ttm_range_man_get_node, - .put_node = ttm_range_man_put_node, + .alloc = ttm_range_man_alloc, + .free = ttm_range_man_free, .debug = ttm_range_man_debug }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index 3fea7a6c7cfaf..bb76acb5b0fcf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -156,6 +156,6 @@ void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type) } static const struct ttm_resource_manager_func vmw_gmrid_manager_func = { - .get_node = vmw_gmrid_man_get_node, - .put_node = vmw_gmrid_man_put_node, + .alloc = vmw_gmrid_man_get_node, + .free = vmw_gmrid_man_put_node, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index f594e2e6ab7ec..3c00a9e7cfcc8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -177,7 +177,7 @@ static void vmw_thp_debug(struct ttm_resource_manager *man, } const struct ttm_resource_manager_func vmw_thp_func = { - .get_node = vmw_thp_get_node, - .put_node = vmw_thp_put_node, + .alloc = vmw_thp_get_node, + .free = vmw_thp_put_node, .debug = vmw_thp_debug }; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index eb1c3312e1758..bfdda61edadb8 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -49,7 +49,7 @@ struct ttm_resource_manager; struct ttm_resource_manager_func { /** - * struct ttm_resource_manager member get_node + * struct ttm_resource_manager_func member alloc * * @man: Pointer to a memory type manager. * @bo: Pointer to the buffer object we're allocating space for. @@ -76,13 +76,13 @@ struct ttm_resource_manager_func { * an implementation can and must use either a mutex or a spinlock to * protect any data structures managing the space. */ - int (*get_node)(struct ttm_resource_manager *man, - struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_resource *mem); + int (*alloc)(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *mem); /** - * struct ttm_resource_manager member put_node + * struct ttm_resource_manager_func member free * * @man: Pointer to a memory type manager. * @mem: Pointer to a struct ttm_resource to be filled in. @@ -91,11 +91,11 @@ struct ttm_resource_manager_func { * and that are identified by @mem::mm_node and @mem::start. May not * be called from within atomic context. */ - void (*put_node)(struct ttm_resource_manager *man, - struct ttm_resource *mem); + void (*free)(struct ttm_resource_manager *man, + struct ttm_resource *mem); /** - * struct ttm_resource_manager member debug + * struct ttm_resource_manager_func member debug * * @man: Pointer to a memory type manager. * @printer: Prefix to be used in printout to identify the caller. -- GitLab From b2458726b38cb69f3da3677dbdf53e47af0e8792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 3 Aug 2020 16:25:15 +0200 Subject: [PATCH 0397/1494] drm/ttm: give resource functions their own [ch] files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a separate object we work within TTM. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/384338/?series=80346&rev=1 --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +- drivers/gpu/drm/radeon/radeon_ttm.c | 4 +- drivers/gpu/drm/ttm/Makefile | 3 +- drivers/gpu/drm/ttm/ttm_bo.c | 124 +--------- drivers/gpu/drm/ttm/ttm_bo_util.c | 4 +- drivers/gpu/drm/ttm/ttm_resource.c | 151 ++++++++++++ include/drm/ttm/ttm_bo_api.h | 70 +----- include/drm/ttm/ttm_bo_driver.h | 189 --------------- include/drm/ttm/ttm_resource.h | 263 +++++++++++++++++++++ 11 files changed, 446 insertions(+), 376 deletions(-) create mode 100644 drivers/gpu/drm/ttm/ttm_resource.c create mode 100644 include/drm/ttm/ttm_resource.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 43f4966331dd9..b36d94f57d428 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -381,7 +381,7 @@ int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev, if (cpu_addr) amdgpu_bo_kunmap(*bo_ptr); - ttm_bo_mem_put(&(*bo_ptr)->tbo, &(*bo_ptr)->tbo.mem); + ttm_resource_free(&(*bo_ptr)->tbo, &(*bo_ptr)->tbo.mem); for (i = 0; i < (*bo_ptr)->placement.num_placement; ++i) { (*bo_ptr)->placements[i].fpfn = offset >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 67d2eef2f9ebd..462402fcd1a41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -578,7 +578,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, /* move BO (in tmp_mem) to new_mem */ r = ttm_bo_move_ttm(bo, ctx, new_mem); out_cleanup: - ttm_bo_mem_put(bo, &tmp_mem); + ttm_resource_free(bo, &tmp_mem); return r; } @@ -625,7 +625,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, goto out_cleanup; } out_cleanup: - ttm_bo_mem_put(bo, &tmp_mem); + ttm_resource_free(bo, &tmp_mem); return r; } @@ -1203,11 +1203,11 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) gtt->offset = (u64)tmp.start << PAGE_SHIFT; r = amdgpu_ttm_gart_bind(adev, bo, flags); if (unlikely(r)) { - ttm_bo_mem_put(bo, &tmp); + ttm_resource_free(bo, &tmp); return r; } - ttm_bo_mem_put(bo, &bo->mem); + ttm_resource_free(bo, &bo->mem); bo->mem = tmp; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 604a743236964..29d7d7e100f72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1191,7 +1191,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, ret = ttm_bo_move_ttm(bo, &ctx, new_reg); out: - ttm_bo_mem_put(bo, &tmp_reg); + ttm_resource_free(bo, &tmp_reg); return ret; } @@ -1227,7 +1227,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, goto out; out: - ttm_bo_mem_put(bo, &tmp_reg); + ttm_resource_free(bo, &tmp_reg); return ret; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 3355b69b13d14..31f4cf211b6af 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -271,7 +271,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, } r = ttm_bo_move_ttm(bo, &ctx, new_mem); out_cleanup: - ttm_bo_mem_put(bo, &tmp_mem); + ttm_resource_free(bo, &tmp_mem); return r; } @@ -309,7 +309,7 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, goto out_cleanup; } out_cleanup: - ttm_bo_mem_put(bo, &tmp_mem); + ttm_resource_free(bo, &tmp_mem); return r; } diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index e54326e6cea4a..90c0da88cc986 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile @@ -4,7 +4,8 @@ ttm-y := ttm_memory.o ttm_tt.o ttm_bo.o \ ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ - ttm_execbuf_util.o ttm_page_alloc.o ttm_range_manager.o + ttm_execbuf_util.o ttm_page_alloc.o ttm_range_manager.o \ + ttm_resource.o ttm-$(CONFIG_AGP) += ttm_agp_backend.o ttm-$(CONFIG_DRM_TTM_DMA_PAGE_POOL) += ttm_page_alloc_dma.o diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ae71c3ab6cc44..55890314316b9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -77,19 +77,6 @@ static inline int ttm_mem_type_from_place(const struct ttm_place *place, return 0; } -void ttm_resource_manager_debug(struct ttm_resource_manager *man, - struct drm_printer *p) -{ - drm_printf(p, " use_type: %d\n", man->use_type); - drm_printf(p, " use_tt: %d\n", man->use_tt); - drm_printf(p, " size: %llu\n", man->size); - drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); - drm_printf(p, " default_caching: 0x%08X\n", man->default_caching); - if (man->func && man->func->debug) - (*man->func->debug)(man, p); -} -EXPORT_SYMBOL(ttm_resource_manager_debug); - static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, struct ttm_placement *placement) { @@ -363,7 +350,7 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) ttm_tt_destroy(bo->ttm); bo->ttm = NULL; - ttm_bo_mem_put(bo, &bo->mem); + ttm_resource_free(bo, &bo->mem); } static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo) @@ -678,7 +665,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, if (unlikely(ret)) { if (ret != -ERESTARTSYS) pr_err("Buffer eviction failed\n"); - ttm_bo_mem_put(bo, &evict_mem); + ttm_resource_free(bo, &evict_mem); goto out; } bo->evicted = true; @@ -767,11 +754,11 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, return r == -EDEADLK ? -EBUSY : r; } -static int ttm_mem_evict_first(struct ttm_bo_device *bdev, - struct ttm_resource_manager *man, - const struct ttm_place *place, - struct ttm_operation_ctx *ctx, - struct ww_acquire_ctx *ticket) +int ttm_mem_evict_first(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man, + const struct ttm_place *place, + struct ttm_operation_ctx *ctx, + struct ww_acquire_ctx *ticket) { struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; bool locked = false; @@ -839,32 +826,6 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, return ret; } -static int ttm_bo_mem_get(struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_resource *mem) -{ - struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); - - mem->mm_node = NULL; - if (!man->func || !man->func->alloc) - return 0; - - return man->func->alloc(man, bo, place, mem); -} - -void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_resource *mem) -{ - struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, mem->mem_type); - - if (!man->func || !man->func->free) - return; - - man->func->free(man, mem); - mem->mm_node = NULL; - mem->mem_type = TTM_PL_SYSTEM; -} -EXPORT_SYMBOL(ttm_bo_mem_put); - /** * Add the last move fence to the BO and reserve a new shared slot. */ @@ -915,7 +876,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, ticket = dma_resv_locking_ctx(bo->base.resv); do { - ret = ttm_bo_mem_get(bo, place, mem); + ret = ttm_resource_alloc(bo, place, mem); if (likely(!ret)) break; if (unlikely(ret != -ENOSPC)) @@ -1056,7 +1017,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, goto error; type_found = true; - ret = ttm_bo_mem_get(bo, place, mem); + ret = ttm_resource_alloc(bo, place, mem); if (ret == -ENOSPC) continue; if (unlikely(ret)) @@ -1065,7 +1026,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, man = ttm_manager_type(bdev, mem->mem_type); ret = ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu); if (unlikely(ret)) { - ttm_bo_mem_put(bo, mem); + ttm_resource_free(bo, mem); if (ret == -EBUSY) continue; @@ -1132,7 +1093,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, ret = ttm_bo_handle_move_mem(bo, &mem, false, ctx); out_unlock: if (ret) - ttm_bo_mem_put(bo, &mem); + ttm_resource_free(bo, &mem); return ret; } @@ -1404,52 +1365,6 @@ int ttm_bo_create(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_bo_create); -int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, - struct ttm_resource_manager *man) -{ - struct ttm_operation_ctx ctx = { - .interruptible = false, - .no_wait_gpu = false, - .flags = TTM_OPT_FLAG_FORCE_ALLOC - }; - struct ttm_bo_global *glob = &ttm_bo_glob; - struct dma_fence *fence; - int ret; - unsigned i; - - /* - * Can't use standard list traversal since we're unlocking. - */ - - spin_lock(&glob->lru_lock); - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - while (!list_empty(&man->lru[i])) { - spin_unlock(&glob->lru_lock); - ret = ttm_mem_evict_first(bdev, man, NULL, &ctx, - NULL); - if (ret) - return ret; - spin_lock(&glob->lru_lock); - } - } - spin_unlock(&glob->lru_lock); - - spin_lock(&man->move_lock); - fence = dma_fence_get(man->move); - spin_unlock(&man->move_lock); - - if (fence) { - ret = dma_fence_wait(fence, false); - dma_fence_put(fence); - if (ret) - return ret; - } - - return 0; -} -EXPORT_SYMBOL(ttm_resource_manager_force_list_clean); - - int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) { struct ttm_resource_manager *man = ttm_manager_type(bdev, mem_type); @@ -1468,23 +1383,6 @@ int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) } EXPORT_SYMBOL(ttm_bo_evict_mm); -void ttm_resource_manager_init(struct ttm_resource_manager *man, - unsigned long p_size) -{ - unsigned i; - - man->use_io_reserve_lru = false; - mutex_init(&man->io_reserve_mutex); - spin_lock_init(&man->move_lock); - INIT_LIST_HEAD(&man->io_reserve_lru); - man->size = p_size; - - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) - INIT_LIST_HEAD(&man->lru[i]); - man->move = NULL; -} -EXPORT_SYMBOL(ttm_resource_manager_init); - static void ttm_bo_global_kobj_release(struct kobject *kobj) { struct ttm_bo_global *glob = diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 496158acd5b95..12be2d3fcc813 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -47,7 +47,7 @@ struct ttm_transfer_obj { void ttm_bo_free_old_node(struct ttm_buffer_object *bo) { - ttm_bo_mem_put(bo, &bo->mem); + ttm_resource_free(bo, &bo->mem); } int ttm_bo_move_ttm(struct ttm_buffer_object *bo, @@ -398,7 +398,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, * On error, keep the mm node! */ if (!ret) - ttm_bo_mem_put(bo, &old_copy); + ttm_resource_free(bo, &old_copy); return ret; } EXPORT_SYMBOL(ttm_bo_move_memcpy); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c new file mode 100644 index 0000000000000..33b642532e5ca --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -0,0 +1,151 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#include <drm/ttm/ttm_resource.h> +#include <drm/ttm/ttm_bo_driver.h> + +int ttm_resource_alloc(struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *res) +{ + struct ttm_resource_manager *man = + ttm_manager_type(bo->bdev, res->mem_type); + + res->mm_node = NULL; + if (!man->func || !man->func->alloc) + return 0; + + return man->func->alloc(man, bo, place, res); +} + +void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource *res) +{ + struct ttm_resource_manager *man = + ttm_manager_type(bo->bdev, res->mem_type); + + if (man->func && man->func->free) + man->func->free(man, res); + + res->mm_node = NULL; + res->mem_type = TTM_PL_SYSTEM; +} +EXPORT_SYMBOL(ttm_resource_free); + +/** + * ttm_resource_manager_init + * + * @man: memory manager object to init + * @p_size: size managed area in pages. + * + * Initialise core parts of a manager object. + */ +void ttm_resource_manager_init(struct ttm_resource_manager *man, + unsigned long p_size) +{ + unsigned i; + + man->use_io_reserve_lru = false; + mutex_init(&man->io_reserve_mutex); + spin_lock_init(&man->move_lock); + INIT_LIST_HEAD(&man->io_reserve_lru); + man->size = p_size; + + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) + INIT_LIST_HEAD(&man->lru[i]); + man->move = NULL; +} +EXPORT_SYMBOL(ttm_resource_manager_init); + +/* + * ttm_resource_manager_force_list_clean + * + * @bdev - device to use + * @man - manager to use + * + * Force all the objects out of a memory manager until clean. + * Part of memory manager cleanup sequence. + */ +int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man) +{ + struct ttm_operation_ctx ctx = { + .interruptible = false, + .no_wait_gpu = false, + .flags = TTM_OPT_FLAG_FORCE_ALLOC + }; + struct ttm_bo_global *glob = &ttm_bo_glob; + struct dma_fence *fence; + int ret; + unsigned i; + + /* + * Can't use standard list traversal since we're unlocking. + */ + + spin_lock(&glob->lru_lock); + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + while (!list_empty(&man->lru[i])) { + spin_unlock(&glob->lru_lock); + ret = ttm_mem_evict_first(bdev, man, NULL, &ctx, + NULL); + if (ret) + return ret; + spin_lock(&glob->lru_lock); + } + } + spin_unlock(&glob->lru_lock); + + spin_lock(&man->move_lock); + fence = dma_fence_get(man->move); + spin_unlock(&man->move_lock); + + if (fence) { + ret = dma_fence_wait(fence, false); + dma_fence_put(fence); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(ttm_resource_manager_force_list_clean); + +/** + * ttm_resource_manager_debug + * + * @man: manager type to dump. + * @p: printer to use for debug. + */ +void ttm_resource_manager_debug(struct ttm_resource_manager *man, + struct drm_printer *p) +{ + drm_printf(p, " use_type: %d\n", man->use_type); + drm_printf(p, " use_tt: %d\n", man->use_tt); + drm_printf(p, " size: %llu\n", man->size); + drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); + drm_printf(p, " default_caching: 0x%08X\n", man->default_caching); + if (man->func && man->func->debug) + (*man->func->debug)(man, p); +} +EXPORT_SYMBOL(ttm_resource_manager_debug); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 770ad2195875d..dbb276abcf6a2 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -42,6 +42,8 @@ #include <linux/bitmap.h> #include <linux/dma-resv.h> +#include "ttm_resource.h" + struct ttm_bo_global; struct ttm_bo_device; @@ -54,57 +56,6 @@ struct ttm_place; struct ttm_lru_bulk_move; -struct ttm_resource_manager; - -/** - * struct ttm_bus_placement - * - * @addr: mapped virtual address - * @base: bus base address - * @is_iomem: is this io memory ? - * @size: size in byte - * @offset: offset from the base address - * @io_reserved_vm: The VM system has a refcount in @io_reserved_count - * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve - * - * Structure indicating the bus placement of an object. - */ -struct ttm_bus_placement { - void *addr; - phys_addr_t base; - unsigned long size; - unsigned long offset; - bool is_iomem; - bool io_reserved_vm; - uint64_t io_reserved_count; -}; - - -/** - * struct ttm_resource - * - * @mm_node: Memory manager node. - * @size: Requested size of memory region. - * @num_pages: Actual size of memory region in pages. - * @page_alignment: Page alignment. - * @placement: Placement flags. - * @bus: Placement on io bus accessible to the CPU - * - * Structure indicating the placement and space resources used by a - * buffer object. - */ - -struct ttm_resource { - void *mm_node; - unsigned long start; - unsigned long size; - unsigned long num_pages; - uint32_t page_alignment; - uint32_t mem_type; - uint32_t placement; - struct ttm_bus_placement bus; -}; - /** * enum ttm_bo_type * @@ -533,17 +484,6 @@ int ttm_bo_create(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_alignment, bool interruptible, struct ttm_buffer_object **p_bo); -/** - * ttm_resource_manager_init - * - * @man: memory manager object to init - * @p_size: size managed area in pages. - * - * Initialise core parts of a manager object. - */ -void ttm_resource_manager_init(struct ttm_resource_manager *man, - unsigned long p_size); - /** * ttm_bo_evict_mm * @@ -680,6 +620,12 @@ static inline bool ttm_bo_uses_embedded_gem_object(struct ttm_buffer_object *bo) return bo->base.dev != NULL; } +int ttm_mem_evict_first(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man, + const struct ttm_place *place, + struct ttm_operation_ctx *ctx, + struct ww_acquire_ctx *ticket); + /* Default number of pre-faulted pages in the TTM fault handler */ #define TTM_BO_VM_NUM_PREFAULT 16 diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index bfdda61edadb8..27b4a1e928757 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -43,131 +43,6 @@ #include "ttm_placement.h" #include "ttm_tt.h" -#define TTM_MAX_BO_PRIORITY 4U - -struct ttm_resource_manager; - -struct ttm_resource_manager_func { - /** - * struct ttm_resource_manager_func member alloc - * - * @man: Pointer to a memory type manager. - * @bo: Pointer to the buffer object we're allocating space for. - * @placement: Placement details. - * @flags: Additional placement flags. - * @mem: Pointer to a struct ttm_resource to be filled in. - * - * This function should allocate space in the memory type managed - * by @man. Placement details if - * applicable are given by @placement. If successful, - * @mem::mm_node should be set to a non-null value, and - * @mem::start should be set to a value identifying the beginning - * of the range allocated, and the function should return zero. - * If the memory region accommodate the buffer object, @mem::mm_node - * should be set to NULL, and the function should return 0. - * If a system error occurred, preventing the request to be fulfilled, - * the function should return a negative error code. - * - * Note that @mem::mm_node will only be dereferenced by - * struct ttm_resource_manager functions and optionally by the driver, - * which has knowledge of the underlying type. - * - * This function may not be called from within atomic context, so - * an implementation can and must use either a mutex or a spinlock to - * protect any data structures managing the space. - */ - int (*alloc)(struct ttm_resource_manager *man, - struct ttm_buffer_object *bo, - const struct ttm_place *place, - struct ttm_resource *mem); - - /** - * struct ttm_resource_manager_func member free - * - * @man: Pointer to a memory type manager. - * @mem: Pointer to a struct ttm_resource to be filled in. - * - * This function frees memory type resources previously allocated - * and that are identified by @mem::mm_node and @mem::start. May not - * be called from within atomic context. - */ - void (*free)(struct ttm_resource_manager *man, - struct ttm_resource *mem); - - /** - * struct ttm_resource_manager_func member debug - * - * @man: Pointer to a memory type manager. - * @printer: Prefix to be used in printout to identify the caller. - * - * This function is called to print out the state of the memory - * type manager to aid debugging of out-of-memory conditions. - * It may not be called from within atomic context. - */ - void (*debug)(struct ttm_resource_manager *man, - struct drm_printer *printer); -}; - -/** - * struct ttm_resource_manager - * - * @use_type: The memory type is enabled. - * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory - * managed by this memory type. - * @gpu_offset: If used, the GPU offset of the first managed page of - * fixed memory or the first managed location in an aperture. - * @size: Size of the managed region. - * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, - * as defined in ttm_placement_common.h - * @default_caching: The default caching policy used for a buffer object - * placed in this memory type if the user doesn't provide one. - * @func: structure pointer implementing the range manager. See above - * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures - * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions - * reserved by the TTM vm system. - * @io_reserve_lru: Optional lru list for unreserving io mem regions. - * @move_lock: lock for move fence - * static information. bdev::driver::io_mem_free is never used. - * @lru: The lru list for this memory type. - * @move: The fence of the last pipelined move operation. - * - * This structure is used to identify and manage memory types for a device. - */ - - - -struct ttm_resource_manager { - /* - * No protection. Constant from start. - */ - bool use_type; - bool use_tt; - uint64_t size; - uint32_t available_caching; - uint32_t default_caching; - const struct ttm_resource_manager_func *func; - struct mutex io_reserve_mutex; - bool use_io_reserve_lru; - spinlock_t move_lock; - - /* - * Protected by @io_reserve_mutex: - */ - - struct list_head io_reserve_lru; - - /* - * Protected by the global->lru_lock. - */ - - struct list_head lru[TTM_MAX_BO_PRIORITY]; - - /* - * Protected by @move_lock. - */ - struct dma_fence *move; -}; - /** * struct ttm_bo_driver * @@ -537,8 +412,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_resource *mem, struct ttm_operation_ctx *ctx); -void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_resource *mem); - int ttm_bo_device_release(struct ttm_bo_device *bdev); /** @@ -675,59 +548,6 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) dma_resv_unlock(bo->base.resv); } -/** - * ttm_resource_manager_set_used - * - * @man: A memory manager object. - * @used: usage state to set. - * - * Set the manager in use flag. If disabled the manager is no longer - * used for object placement. - */ -static inline void ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) -{ - man->use_type = used; -} - -/** - * ttm_resource_manager_used - * - * @man: Manager to get used state for - * - * Get the in use flag for a manager. - * Returns: - * true is used, false if not. - */ -static inline bool ttm_resource_manager_used(struct ttm_resource_manager *man) -{ - return man->use_type; -} - -/** - * ttm_resource_manager_cleanup - * - * @man: A memory manager object. - * - * Cleanup the move fences from the memory manager object. - */ -static inline void ttm_resource_manager_cleanup(struct ttm_resource_manager *man) -{ - dma_fence_put(man->move); - man->move = NULL; -} - -/* - * ttm_resource_manager_force_list_clean - * - * @bdev - device to use - * @man - manager to use - * - * Force all the objects out of a memory manager until clean. - * Part of memory manager cleanup sequence. - */ -int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, - struct ttm_resource_manager *man); - /* * ttm_bo_util.c */ @@ -874,13 +694,4 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, int ttm_range_man_fini(struct ttm_bo_device *bdev, unsigned type); -/** - * ttm_resource_manager_debug - * - * @man: manager type to dump. - * @p: printer to use for debug. - */ -void ttm_resource_manager_debug(struct ttm_resource_manager *man, - struct drm_printer *p); - #endif diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h new file mode 100644 index 0000000000000..bac22a56f6cdb --- /dev/null +++ b/include/drm/ttm/ttm_resource.h @@ -0,0 +1,263 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#ifndef _TTM_RESOURCE_H_ +#define _TTM_RESOURCE_H_ + +#include <linux/types.h> +#include <linux/mutex.h> +#include <linux/dma-fence.h> +#include <drm/drm_print.h> + +#define TTM_MAX_BO_PRIORITY 4U + +struct ttm_bo_device; +struct ttm_resource_manager; +struct ttm_resource; +struct ttm_place; +struct ttm_buffer_object; + +struct ttm_resource_manager_func { + /** + * struct ttm_resource_manager_func member alloc + * + * @man: Pointer to a memory type manager. + * @bo: Pointer to the buffer object we're allocating space for. + * @placement: Placement details. + * @flags: Additional placement flags. + * @mem: Pointer to a struct ttm_resource to be filled in. + * + * This function should allocate space in the memory type managed + * by @man. Placement details if + * applicable are given by @placement. If successful, + * @mem::mm_node should be set to a non-null value, and + * @mem::start should be set to a value identifying the beginning + * of the range allocated, and the function should return zero. + * If the memory region accommodate the buffer object, @mem::mm_node + * should be set to NULL, and the function should return 0. + * If a system error occurred, preventing the request to be fulfilled, + * the function should return a negative error code. + * + * Note that @mem::mm_node will only be dereferenced by + * struct ttm_resource_manager functions and optionally by the driver, + * which has knowledge of the underlying type. + * + * This function may not be called from within atomic context, so + * an implementation can and must use either a mutex or a spinlock to + * protect any data structures managing the space. + */ + int (*alloc)(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *mem); + + /** + * struct ttm_resource_manager_func member free + * + * @man: Pointer to a memory type manager. + * @mem: Pointer to a struct ttm_resource to be filled in. + * + * This function frees memory type resources previously allocated + * and that are identified by @mem::mm_node and @mem::start. May not + * be called from within atomic context. + */ + void (*free)(struct ttm_resource_manager *man, + struct ttm_resource *mem); + + /** + * struct ttm_resource_manager_func member debug + * + * @man: Pointer to a memory type manager. + * @printer: Prefix to be used in printout to identify the caller. + * + * This function is called to print out the state of the memory + * type manager to aid debugging of out-of-memory conditions. + * It may not be called from within atomic context. + */ + void (*debug)(struct ttm_resource_manager *man, + struct drm_printer *printer); +}; + +/** + * struct ttm_resource_manager + * + * @use_type: The memory type is enabled. + * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory + * managed by this memory type. + * @gpu_offset: If used, the GPU offset of the first managed page of + * fixed memory or the first managed location in an aperture. + * @size: Size of the managed region. + * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, + * as defined in ttm_placement_common.h + * @default_caching: The default caching policy used for a buffer object + * placed in this memory type if the user doesn't provide one. + * @func: structure pointer implementing the range manager. See above + * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures + * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions + * reserved by the TTM vm system. + * @io_reserve_lru: Optional lru list for unreserving io mem regions. + * @move_lock: lock for move fence + * static information. bdev::driver::io_mem_free is never used. + * @lru: The lru list for this memory type. + * @move: The fence of the last pipelined move operation. + * + * This structure is used to identify and manage memory types for a device. + */ +struct ttm_resource_manager { + /* + * No protection. Constant from start. + */ + bool use_type; + bool use_tt; + uint64_t size; + uint32_t available_caching; + uint32_t default_caching; + const struct ttm_resource_manager_func *func; + struct mutex io_reserve_mutex; + bool use_io_reserve_lru; + spinlock_t move_lock; + + /* + * Protected by @io_reserve_mutex: + */ + + struct list_head io_reserve_lru; + + /* + * Protected by the global->lru_lock. + */ + + struct list_head lru[TTM_MAX_BO_PRIORITY]; + + /* + * Protected by @move_lock. + */ + struct dma_fence *move; +}; + +/** + * struct ttm_bus_placement + * + * @addr: mapped virtual address + * @base: bus base address + * @is_iomem: is this io memory ? + * @size: size in byte + * @offset: offset from the base address + * @io_reserved_vm: The VM system has a refcount in @io_reserved_count + * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve + * + * Structure indicating the bus placement of an object. + */ +struct ttm_bus_placement { + void *addr; + phys_addr_t base; + unsigned long size; + unsigned long offset; + bool is_iomem; + bool io_reserved_vm; + uint64_t io_reserved_count; +}; + +/** + * struct ttm_resource + * + * @mm_node: Memory manager node. + * @size: Requested size of memory region. + * @num_pages: Actual size of memory region in pages. + * @page_alignment: Page alignment. + * @placement: Placement flags. + * @bus: Placement on io bus accessible to the CPU + * + * Structure indicating the placement and space resources used by a + * buffer object. + */ +struct ttm_resource { + void *mm_node; + unsigned long start; + unsigned long size; + unsigned long num_pages; + uint32_t page_alignment; + uint32_t mem_type; + uint32_t placement; + struct ttm_bus_placement bus; +}; + +/** + * ttm_resource_manager_set_used + * + * @man: A memory manager object. + * @used: usage state to set. + * + * Set the manager in use flag. If disabled the manager is no longer + * used for object placement. + */ +static inline void +ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) +{ + man->use_type = used; +} + +/** + * ttm_resource_manager_used + * + * @man: Manager to get used state for + * + * Get the in use flag for a manager. + * Returns: + * true is used, false if not. + */ +static inline bool ttm_resource_manager_used(struct ttm_resource_manager *man) +{ + return man->use_type; +} + +/** + * ttm_resource_manager_cleanup + * + * @man: A memory manager object. + * + * Cleanup the move fences from the memory manager object. + */ +static inline void +ttm_resource_manager_cleanup(struct ttm_resource_manager *man) +{ + dma_fence_put(man->move); + man->move = NULL; +} + +int ttm_resource_alloc(struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource *res); +void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource *res); + +void ttm_resource_manager_init(struct ttm_resource_manager *man, + unsigned long p_size); + +int ttm_resource_manager_force_list_clean(struct ttm_bo_device *bdev, + struct ttm_resource_manager *man); + +void ttm_resource_manager_debug(struct ttm_resource_manager *man, + struct drm_printer *p); + +#endif -- GitLab From 82dd18096c718962379e61cd8a7a0dc219db174f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 5 Aug 2020 14:35:10 +0200 Subject: [PATCH 0398/1494] drm/radeon: drop superflous AGP handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The object flags created in radeon_ttm_placement_from_domain take care that we use the correct caching for AGP, this is just superflous. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/384336/?series=80346&rev=1 --- drivers/gpu/drm/radeon/radeon_ttm.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 31f4cf211b6af..290c8b4798533 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -76,26 +76,9 @@ static int radeon_ttm_init_vram(struct radeon_device *rdev) static int radeon_ttm_init_gtt(struct radeon_device *rdev) { - uint32_t available_caching, default_caching; - - available_caching = TTM_PL_MASK_CACHING; - default_caching = TTM_PL_FLAG_CACHED; - -#if IS_ENABLED(CONFIG_AGP) - if (rdev->flags & RADEON_IS_AGP) { - if (!rdev->ddev->agp) { - DRM_ERROR("AGP is not enabled\n"); - return -EINVAL; - } - available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - default_caching = TTM_PL_FLAG_WC; - } -#endif - return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_TT, - available_caching, - default_caching, true, + TTM_PL_MASK_CACHING, + TTM_PL_FLAG_CACHED, true, rdev->mc.gtt_size >> PAGE_SHIFT); } -- GitLab From 97722439eeed2f2e4c1a1d862faa0ee7bc2783c3 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 9 Aug 2020 12:57:04 +0200 Subject: [PATCH 0399/1494] dt-bindings: Add DT bindings for Toshiba TC358762 DSI-to-DPI bridge Add DT bindings for Toshiba TC358762 DSI-to-DPI bridge, this one is used in the Raspberry Pi 7" touchscreen display unit. Signed-off-by: Marek Vasut <marex@denx.de> Reviewed-by: Rob Herring <robh@kernel.org> Cc: dri-devel@lists.freedesktop.org Cc: Eric Anholt <eric@anholt.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Signed-off-by: Sam Ravnborg <sam.ravnborg@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200809105705.6334-1-marex@denx.de --- .../display/bridge/toshiba,tc358762.yaml | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.yaml new file mode 100644 index 0000000000000..195025e6803cd --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358762.yaml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/toshiba,tc358762.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Toshiba TC358762 MIPI DSI to MIPI DPI bridge + +maintainers: + - Marek Vasut <marex@denx.de> + +description: | + The TC358762 is bridge device which converts MIPI DSI to MIPI DPI. + +properties: + compatible: + enum: + - toshiba,tc358762 + + reg: + maxItems: 1 + description: virtual channel number of a DSI peripheral + + vddc-supply: + description: Regulator for 1.2V internal core power. + + ports: + type: object + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + port@0: + type: object + additionalProperties: false + + description: | + Video port for MIPI DSI input + + properties: + reg: + const: 0 + + patternProperties: + endpoint: + type: object + additionalProperties: false + + properties: + remote-endpoint: true + + required: + - reg + + port@1: + type: object + additionalProperties: false + + description: | + Video port for MIPI DPI output (panel or connector). + + properties: + reg: + const: 1 + + patternProperties: + endpoint: + type: object + additionalProperties: false + + properties: + remote-endpoint: true + + required: + - reg + + required: + - "#address-cells" + - "#size-cells" + - port@0 + - port@1 + +required: + - compatible + - reg + - vddc-supply + - ports + +additionalProperties: false + +examples: + - | + i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + bridge@0 { + reg = <0>; + compatible = "toshiba,tc358762"; + vddc-supply = <&vcc_1v2_reg>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + bridge_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + + port@1 { + reg = <1>; + bridge_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + }; + }; + +... -- GitLab From 1930d19cb49930b7d5be0379be9f88fcbeba9976 Mon Sep 17 00:00:00 2001 From: Marek Vasut <marex@denx.de> Date: Sun, 9 Aug 2020 12:57:05 +0200 Subject: [PATCH 0400/1494] drm/bridge: tc358762: Add basic driver for Toshiba TC358762 DSI-to-DPI bridge Add very basic driver for Toshiba TC358762 DSI-to-DPI bridge, derived from tc358764 driver and panel-raspberrypi-touchscreen. This driver is meant to replace the panel-raspberrypi-touchscreen too, as the bridge connection can be described in DT too. Signed-off-by: Marek Vasut <marex@denx.de> Cc: dri-devel@lists.freedesktop.org Cc: Eric Anholt <eric@anholt.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: devicetree@vger.kernel.org Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam.ravnborg@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200809105705.6334-2-marex@denx.de --- drivers/gpu/drm/bridge/Kconfig | 8 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/tc358762.c | 280 ++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 drivers/gpu/drm/bridge/tc358762.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index e8672cfa2a2f7..3e11af4e9f63e 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -166,6 +166,14 @@ config DRM_THINE_THC63LVD1024 help Thine THC63LVD1024 LVDS/parallel converter driver. +config DRM_TOSHIBA_TC358762 + tristate "TC358762 DSI/DPI bridge" + depends on OF + select DRM_MIPI_DSI + select DRM_PANEL_BRIDGE + help + Toshiba TC358762 DSI/DPI bridge driver. + config DRM_TOSHIBA_TC358764 tristate "TC358764 DSI/LVDS bridge" depends on OF diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 5f65f3d212212..c589a6a7cbe1d 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_DRM_SII902X) += sii902x.o obj-$(CONFIG_DRM_SII9234) += sii9234.o obj-$(CONFIG_DRM_SIMPLE_BRIDGE) += simple-bridge.o obj-$(CONFIG_DRM_THINE_THC63LVD1024) += thc63lvd1024.o +obj-$(CONFIG_DRM_TOSHIBA_TC358762) += tc358762.o obj-$(CONFIG_DRM_TOSHIBA_TC358764) += tc358764.o obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o obj-$(CONFIG_DRM_TOSHIBA_TC358768) += tc358768.o diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c new file mode 100644 index 0000000000000..1bfdfc6affafe --- /dev/null +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Marek Vasut <marex@denx.de> + * + * Based on tc358764.c by + * Andrzej Hajda <a.hajda@samsung.com> + * Maciej Purski <m.purski@samsung.com> + * + * Based on rpi_touchscreen.c by + * Eric Anholt <eric@anholt.net> + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_graph.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +/* PPI layer registers */ +#define PPI_STARTPPI 0x0104 /* START control bit */ +#define PPI_LPTXTIMECNT 0x0114 /* LPTX timing signal */ +#define PPI_D0S_ATMR 0x0144 +#define PPI_D1S_ATMR 0x0148 +#define PPI_D0S_CLRSIPOCOUNT 0x0164 /* Assertion timer for Lane 0 */ +#define PPI_D1S_CLRSIPOCOUNT 0x0168 /* Assertion timer for Lane 1 */ +#define PPI_START_FUNCTION 1 + +/* DSI layer registers */ +#define DSI_STARTDSI 0x0204 /* START control bit of DSI-TX */ +#define DSI_LANEENABLE 0x0210 /* Enables each lane */ +#define DSI_RX_START 1 + +/* LCDC/DPI Host Registers */ +#define LCDCTRL 0x0420 + +/* SPI Master Registers */ +#define SPICMR 0x0450 +#define SPITCR 0x0454 + +/* System Controller Registers */ +#define SYSCTRL 0x0464 + +/* System registers */ +#define LPX_PERIOD 3 + +/* Lane enable PPI and DSI register bits */ +#define LANEENABLE_CLEN BIT(0) +#define LANEENABLE_L0EN BIT(1) +#define LANEENABLE_L1EN BIT(2) + +struct tc358762 { + struct device *dev; + struct drm_bridge bridge; + struct drm_connector connector; + struct regulator *regulator; + struct drm_bridge *panel_bridge; + bool pre_enabled; + int error; +}; + +static int tc358762_clear_error(struct tc358762 *ctx) +{ + int ret = ctx->error; + + ctx->error = 0; + return ret; +} + +static void tc358762_write(struct tc358762 *ctx, u16 addr, u32 val) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + ssize_t ret; + u8 data[6]; + + if (ctx->error) + return; + + data[0] = addr; + data[1] = addr >> 8; + data[2] = val; + data[3] = val >> 8; + data[4] = val >> 16; + data[5] = val >> 24; + + ret = mipi_dsi_generic_write(dsi, data, sizeof(data)); + if (ret < 0) + ctx->error = ret; +} + +static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge) +{ + return container_of(bridge, struct tc358762, bridge); +} + +static int tc358762_init(struct tc358762 *ctx) +{ + tc358762_write(ctx, DSI_LANEENABLE, + LANEENABLE_L0EN | LANEENABLE_CLEN); + tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5); + tc358762_write(ctx, PPI_D1S_CLRSIPOCOUNT, 5); + tc358762_write(ctx, PPI_D0S_ATMR, 0); + tc358762_write(ctx, PPI_D1S_ATMR, 0); + tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD); + + tc358762_write(ctx, SPICMR, 0x00); + tc358762_write(ctx, LCDCTRL, 0x00100150); + tc358762_write(ctx, SYSCTRL, 0x040f); + msleep(100); + + tc358762_write(ctx, PPI_STARTPPI, PPI_START_FUNCTION); + tc358762_write(ctx, DSI_STARTDSI, DSI_RX_START); + + msleep(100); + + return tc358762_clear_error(ctx); +} + +static void tc358762_post_disable(struct drm_bridge *bridge) +{ + struct tc358762 *ctx = bridge_to_tc358762(bridge); + int ret; + + /* + * The post_disable hook might be called multiple times. + * We want to avoid regulator imbalance below. + */ + if (!ctx->pre_enabled) + return; + + ctx->pre_enabled = false; + + ret = regulator_disable(ctx->regulator); + if (ret < 0) + dev_err(ctx->dev, "error disabling regulators (%d)\n", ret); +} + +static void tc358762_pre_enable(struct drm_bridge *bridge) +{ + struct tc358762 *ctx = bridge_to_tc358762(bridge); + int ret; + + ret = regulator_enable(ctx->regulator); + if (ret < 0) + dev_err(ctx->dev, "error enabling regulators (%d)\n", ret); + + ret = tc358762_init(ctx); + if (ret < 0) + dev_err(ctx->dev, "error initializing bridge (%d)\n", ret); + + ctx->pre_enabled = true; +} + +static int tc358762_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct tc358762 *ctx = bridge_to_tc358762(bridge); + + return drm_bridge_attach(bridge->encoder, ctx->panel_bridge, + bridge, flags); +} + +static const struct drm_bridge_funcs tc358762_bridge_funcs = { + .post_disable = tc358762_post_disable, + .pre_enable = tc358762_pre_enable, + .attach = tc358762_attach, +}; + +static int tc358762_parse_dt(struct tc358762 *ctx) +{ + struct drm_bridge *panel_bridge; + struct device *dev = ctx->dev; + struct drm_panel *panel; + int ret; + + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); + if (ret) + return ret; + + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + ctx->panel_bridge = panel_bridge; + + return 0; +} + +static int tc358762_configure_regulators(struct tc358762 *ctx) +{ + ctx->regulator = devm_regulator_get(ctx->dev, "vddc"); + if (IS_ERR(ctx->regulator)) + return PTR_ERR(ctx->regulator); + + return 0; +} + +static int tc358762_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct tc358762 *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(struct tc358762), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, ctx); + + ctx->dev = dev; + ctx->pre_enabled = false; + + /* TODO: Find out how to get dual-lane mode working */ + dsi->lanes = 1; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | + MIPI_DSI_MODE_LPM; + + ret = tc358762_parse_dt(ctx); + if (ret < 0) + return ret; + + ret = tc358762_configure_regulators(ctx); + if (ret < 0) + return ret; + + ctx->bridge.funcs = &tc358762_bridge_funcs; + ctx->bridge.type = DRM_MODE_CONNECTOR_DPI; + ctx->bridge.of_node = dev->of_node; + + drm_bridge_add(&ctx->bridge); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + drm_bridge_remove(&ctx->bridge); + dev_err(dev, "failed to attach dsi\n"); + } + + return ret; +} + +static int tc358762_remove(struct mipi_dsi_device *dsi) +{ + struct tc358762 *ctx = mipi_dsi_get_drvdata(dsi); + + mipi_dsi_detach(dsi); + drm_bridge_remove(&ctx->bridge); + + return 0; +} + +static const struct of_device_id tc358762_of_match[] = { + { .compatible = "toshiba,tc358762" }, + { } +}; +MODULE_DEVICE_TABLE(of, tc358762_of_match); + +static struct mipi_dsi_driver tc358762_driver = { + .probe = tc358762_probe, + .remove = tc358762_remove, + .driver = { + .name = "tc358762", + .of_match_table = tc358762_of_match, + }, +}; +module_mipi_dsi_driver(tc358762_driver); + +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("MIPI-DSI based Driver for TC358762 DSI/DPI Bridge"); +MODULE_LICENSE("GPL v2"); -- GitLab From 70c7fe17f370c03e90868cbf24c09a6c5db9c536 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Thu, 13 Aug 2020 11:39:15 +0800 Subject: [PATCH 0401/1494] drm/hisilicon: Fix build error of no type of module_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing include to fix build error: hibmc_drm_drv.c:385:1: warning: data definition has no type or storage class [enabled by default] hibmc_drm_drv.c:385:1: error: type defaults to ‘int’ in declaration of ‘module_init’ [-Werror=implicit-int] hibmc_drm_drv.c:385:1: warning: parameter names (without types) in function of ‘module_exit’ [-Werror=implicit-int] hibmc_drm_drv.c:385:292:1: warning: parameter names (without types) in function declaration [enabled by default] Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597289955-27381-1-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 1ae360d9cca24..2b4f82163b99e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -11,6 +11,7 @@ * Jianhua Li <lijianhua@huawei.com> */ +#include <linux/module.h> #include <linux/pci.h> #include <drm/drm_atomic_helper.h> -- GitLab From ea66a9be7e93e5a87f1cdb37b4246882f7c73e45 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Wed, 29 Jul 2020 11:09:14 +0200 Subject: [PATCH 0402/1494] drm/mcde: Rename flow function The function mcde_display_send_one_frame() has a historical name that stems from being implemented when the driver only supported single frame updates. Rename it mcde_start_flow() so that it reflects the current usage. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200729090915.252730-1-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 4d2290f88edb5..363fa5ca4b45f 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -968,7 +968,7 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) dev_info(drm->dev, "MCDE display is disabled\n"); } -static void mcde_display_send_one_frame(struct mcde *mcde) +static void mcde_start_flow(struct mcde *mcde) { /* Request a TE ACK */ if (mcde->te_sync) @@ -1066,7 +1066,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, * is not active yet. */ if (mcde->flow_active == 0) - mcde_display_send_one_frame(mcde); + mcde_start_flow(mcde); } dev_info_once(mcde->dev, "sent first display update\n"); } else { -- GitLab From 709c27730a11d6681297d733eb8ee18166e9c38a Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Wed, 29 Jul 2020 11:09:15 +0200 Subject: [PATCH 0403/1494] drm/mcde: Fix display data flow control Revamp the way that the flow of data to the display is defined. I realized that the hardware supports something like 5 different modes of flow: oneshot, command with TE IRQ, command with BTA (bus turn around) and TE IRQ, video with TE IRQ and video without TE IRQ instead synchronizing to the output of the MCDE DSI formatter. Like before the selection of the type of flow is done from the DSI driver when we attach it to the MCDE and we get to know what the display wants. The new video mode synchronization method from the MCDE DSI formatter is used on some upstream devices such as Golden. This is the new default for video mode: stateless panels do not as a rule generate TE IRQs. Another semantic change is that we stop sending a TE request before every command when sending data to a display in command mode: this should only be explicitly requested when using BTA, according to the vendor driver. This has been tested and works fine with the command mode displays I have. (All that are supported upstream.) Reported-by: Stephan Gerhold <stephan@gerhold.net> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Stephan Gerhold <stephan@gerhold.net> Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200729090915.252730-2-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_display.c | 113 ++++++++++++++++++---------- drivers/gpu/drm/mcde/mcde_drm.h | 26 ++++++- drivers/gpu/drm/mcde/mcde_drv.c | 3 - drivers/gpu/drm/mcde/mcde_dsi.c | 19 ++++- 4 files changed, 111 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index 363fa5ca4b45f..cac660ac88031 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -89,7 +89,7 @@ void mcde_display_irq(struct mcde *mcde) * the update function is called, then we disable the * flow on the channel once we get the TE IRQ. */ - if (mcde->oneshot_mode) { + if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) { spin_lock(&mcde->flow_lock); if (--mcde->flow_active == 0) { dev_dbg(mcde->dev, "TE0 IRQ\n"); @@ -498,19 +498,47 @@ static void mcde_configure_channel(struct mcde *mcde, enum mcde_channel ch, } /* Set up channel 0 sync (based on chnl_update_registers()) */ - if (mcde->video_mode || mcde->te_sync) + switch (mcde->flow_mode) { + case MCDE_COMMAND_ONESHOT_FLOW: + /* Oneshot is achieved with software sync */ + val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE + << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; + break; + case MCDE_COMMAND_TE_FLOW: val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; - else - val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SOFTWARE + val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 + << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; + break; + case MCDE_COMMAND_BTA_TE_FLOW: + val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE + << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; + /* + * TODO: + * The vendor driver uses the formatter as sync source + * for BTA TE mode. Test to use TE if you have a panel + * that uses this mode. + */ + val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER + << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; + break; + case MCDE_VIDEO_TE_FLOW: + val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; - - if (mcde->te_sync) val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_TE0 << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; - else + break; + case MCDE_VIDEO_FORMATTER_FLOW: + val = MCDE_CHNLXSYNCHMOD_SRC_SYNCH_HARDWARE + << MCDE_CHNLXSYNCHMOD_SRC_SYNCH_SHIFT; val |= MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_FORMATTER << MCDE_CHNLXSYNCHMOD_OUT_SYNCH_SRC_SHIFT; + break; + default: + dev_err(mcde->dev, "unknown flow mode %d\n", + mcde->flow_mode); + break; + } writel(val, mcde->regs + sync); @@ -920,7 +948,11 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, mcde_configure_dsi_formatter(mcde, MCDE_DSI_FORMATTER_0, formatter_frame, pkt_size); - if (mcde->te_sync) { + switch (mcde->flow_mode) { + case MCDE_COMMAND_TE_FLOW: + case MCDE_COMMAND_BTA_TE_FLOW: + case MCDE_VIDEO_TE_FLOW: + /* We are using TE in some comination */ if (mode->flags & DRM_MODE_FLAG_NVSYNC) val = MCDE_VSCRC_VSPOL; else @@ -930,16 +962,22 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, val = readl(mcde->regs + MCDE_CRC); val |= MCDE_CRC_SYCEN0; writel(val, mcde->regs + MCDE_CRC); + break; + default: + /* No TE capture */ + break; } drm_crtc_vblank_on(crtc); - if (mcde->video_mode) + if (mcde_flow_is_video(mcde)) { /* * Keep FIFO permanently enabled in video mode, * otherwise MCDE will stop feeding data to the panel. */ mcde_enable_fifo(mcde, MCDE_FIFO_A); + dev_dbg(mcde->dev, "started MCDE video FIFO flow\n"); + } dev_info(drm->dev, "MCDE display is enabled\n"); } @@ -970,38 +1008,36 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) static void mcde_start_flow(struct mcde *mcde) { - /* Request a TE ACK */ - if (mcde->te_sync) + /* Request a TE ACK only in TE+BTA mode */ + if (mcde->flow_mode == MCDE_COMMAND_BTA_TE_FLOW) mcde_dsi_te_request(mcde->mdsi); /* Enable FIFO A flow */ mcde_enable_fifo(mcde, MCDE_FIFO_A); - if (mcde->te_sync) { + /* + * If oneshot mode is enabled, the flow will be disabled + * when the TE0 IRQ arrives in the interrupt handler. Otherwise + * updates are continuously streamed to the display after this + * point. + */ + + if (mcde->flow_mode == MCDE_COMMAND_ONESHOT_FLOW) { + /* Trigger a software sync out on channel 0 */ + writel(MCDE_CHNLXSYNCHSW_SW_TRIG, + mcde->regs + MCDE_CHNL0SYNCHSW); + /* - * If oneshot mode is enabled, the flow will be disabled - * when the TE0 IRQ arrives in the interrupt handler. Otherwise - * updates are continuously streamed to the display after this - * point. + * Disable FIFO A flow again: since we are using TE sync we + * need to wait for the FIFO to drain before we continue + * so repeated calls to this function will not cause a mess + * in the hardware by pushing updates will updates are going + * on already. */ - dev_dbg(mcde->dev, "sent TE0 framebuffer update\n"); - return; + mcde_disable_fifo(mcde, MCDE_FIFO_A, true); } - /* Trigger a software sync out on channel 0 */ - writel(MCDE_CHNLXSYNCHSW_SW_TRIG, - mcde->regs + MCDE_CHNL0SYNCHSW); - - /* - * Disable FIFO A flow again: since we are using TE sync we - * need to wait for the FIFO to drain before we continue - * so repeated calls to this function will not cause a mess - * in the hardware by pushing updates will updates are going - * on already. - */ - mcde_disable_fifo(mcde, MCDE_FIFO_A, true); - - dev_dbg(mcde->dev, "sent SW framebuffer update\n"); + dev_dbg(mcde->dev, "started MCDE FIFO flow\n"); } static void mcde_set_extsrc(struct mcde *mcde, u32 buffer_address) @@ -1060,15 +1096,10 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, */ if (fb) { mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); - if (!mcde->video_mode) { - /* - * Send a single frame using software sync if the flow - * is not active yet. - */ - if (mcde->flow_active == 0) - mcde_start_flow(mcde); - } - dev_info_once(mcde->dev, "sent first display update\n"); + dev_info_once(mcde->dev, "first update of display contents\n"); + /* The flow is already active in video mode */ + if (!mcde_flow_is_video(mcde) && mcde->flow_active == 0) + mcde_start_flow(mcde); } else { /* * If an update is receieved before the MCDE is enabled diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index 679c2c4e6d9de..3e406d7834650 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -9,6 +9,22 @@ #ifndef _MCDE_DRM_H_ #define _MCDE_DRM_H_ +enum mcde_flow_mode { + /* One-shot mode: flow stops after one frame */ + MCDE_COMMAND_ONESHOT_FLOW, + /* Command mode with tearing effect (TE) IRQ sync */ + MCDE_COMMAND_TE_FLOW, + /* + * Command mode with bus turn-around (BTA) and tearing effect + * (TE) IRQ sync. + */ + MCDE_COMMAND_BTA_TE_FLOW, + /* Video mode with tearing effect (TE) sync IRQ */ + MCDE_VIDEO_TE_FLOW, + /* Video mode with the formatter itself as sync source */ + MCDE_VIDEO_FORMATTER_FLOW, +}; + struct mcde { struct drm_device drm; struct device *dev; @@ -18,9 +34,7 @@ struct mcde { struct drm_simple_display_pipe pipe; struct mipi_dsi_device *mdsi; s16 stride; - bool te_sync; - bool video_mode; - bool oneshot_mode; + enum mcde_flow_mode flow_mode; unsigned int flow_active; spinlock_t flow_lock; /* Locks the channel flow control */ @@ -36,6 +50,12 @@ struct mcde { #define to_mcde(dev) container_of(dev, struct mcde, drm) +static inline bool mcde_flow_is_video(struct mcde *mcde) +{ + return (mcde->flow_mode == MCDE_VIDEO_TE_FLOW || + mcde->flow_mode == MCDE_VIDEO_FORMATTER_FLOW); +} + bool mcde_dsi_irq(struct mipi_dsi_device *mdsi); void mcde_dsi_te_request(struct mipi_dsi_device *mdsi); extern struct platform_driver mcde_dsi_driver; diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 82137ab76cfcb..13418a15f8df2 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -305,9 +305,6 @@ static int mcde_probe(struct platform_device *pdev) mcde->dev = dev; platform_set_drvdata(pdev, drm); - /* Enable continuous updates: this is what Linux' framebuffer expects */ - mcde->oneshot_mode = false; - /* First obtain and turn on the main power */ mcde->epod = devm_regulator_get(dev, "epod"); if (IS_ERR(mcde->epod)) { diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index 981923caa7e66..a342e898298b8 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -148,9 +148,22 @@ static void mcde_dsi_attach_to_mcde(struct mcde_dsi *d) { d->mcde->mdsi = d->mdsi; - d->mcde->video_mode = !!(d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO); - /* Enable use of the TE signal for all command mode panels */ - d->mcde->te_sync = !d->mcde->video_mode; + /* + * Select the way the DSI data flow is pushing to the display: + * currently we just support video or command mode depending + * on the type of display. Video mode defaults to using the + * formatter itself for synchronization (stateless video panel). + * + * FIXME: add flags to struct mipi_dsi_device .flags to indicate + * displays that require BTA (bus turn around) so we can handle + * such displays as well. Figure out how to properly handle + * single frame on-demand updates with DRM for command mode + * displays (MCDE_COMMAND_ONESHOT_FLOW). + */ + if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) + d->mcde->flow_mode = MCDE_VIDEO_FORMATTER_FLOW; + else + d->mcde->flow_mode = MCDE_COMMAND_TE_FLOW; } static int mcde_dsi_host_attach(struct mipi_dsi_host *host, -- GitLab From 44c3867a56e3cdda4b7ea4e4983c4fdafd45b3c9 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 00:31:19 +0200 Subject: [PATCH 0404/1494] drm/mcde: Improve pixel fetcher FIFO depth setting The pixel fetcher FIFO depth was just hardcoded to 48 which works fine as long as the framebuffer is 32BPP and the DSI output is RGB888. We will need more elaborate handling for some buffer formats and displays, so start to improve this function by setting reasonable defaults for 32, 24 and 16 BPP framebuffers. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: newbytee@protonmail.com Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200808223122.1492124-1-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_display.c | 34 +++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index cac660ac88031..cbc7c0c4955ad 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -333,7 +333,7 @@ static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl, enum mcde_extsrc src, enum mcde_channel ch, const struct drm_display_mode *mode, - u32 format) + u32 format, int cpp) { u32 val; u32 conf1; @@ -342,6 +342,7 @@ static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl, u32 ljinc; u32 cr; u32 comp; + u32 pixel_fetcher_watermark; switch (ovl) { case MCDE_OVERLAY_0: @@ -426,8 +427,33 @@ static void mcde_configure_overlay(struct mcde *mcde, enum mcde_overlay ovl, format); break; } - /* The default watermark level for overlay 0 is 48 */ - val |= 48 << MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT; + + /* + * Pixel fetch watermark level is max 0x1FFF pixels. + * Two basic rules should be followed: + * 1. The value should be at least 256 bits. + * 2. The sum of all active overlays pixelfetch watermark level + * multiplied with bits per pixel, should be lower than the + * size of input_fifo_size in bits. + * 3. The value should be a multiple of a line (256 bits). + */ + switch (cpp) { + case 2: + pixel_fetcher_watermark = 128; + break; + case 3: + pixel_fetcher_watermark = 96; + break; + case 4: + pixel_fetcher_watermark = 48; + break; + default: + pixel_fetcher_watermark = 48; + break; + } + dev_dbg(mcde->dev, "pixel fetcher watermark level %d pixels\n", + pixel_fetcher_watermark); + val |= pixel_fetcher_watermark << MCDE_OVLXCONF2_PIXELFETCHERWATERMARKLEVEL_SHIFT; writel(val, mcde->regs + conf2); /* Number of bytes to fetch per line */ @@ -932,7 +958,7 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, * channel 0 */ mcde_configure_overlay(mcde, MCDE_OVERLAY_0, MCDE_EXTSRC_0, - MCDE_CHANNEL_0, mode, format); + MCDE_CHANNEL_0, mode, format, cpp); /* * Configure pixel-per-line and line-per-frame for channel 0 and then -- GitLab From f6fd1d70609ca691ee5dc0d2748b6eeaa57a9535 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 00:31:20 +0200 Subject: [PATCH 0405/1494] drm/mcde: Support using DSI in LP mode It is possible to set a flag in the struct mipi_dsi_device so the panel is handled in low power (LP) mode. Some displays only support this mode and it is also good for testing. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: newbytee@protonmail.com Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200808223122.1492124-2-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_dsi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index a342e898298b8..5cea8cbf084c7 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -812,10 +812,11 @@ static void mcde_dsi_start(struct mcde_dsi *d) /* Command mode, clear IF1 ID */ val = readl(d->regs + DSI_CMD_MODE_CTL); /* - * If we enable low-power mode here, with - * val |= DSI_CMD_MODE_CTL_IF1_LP_EN + * If we enable low-power mode here, * then display updates become really slow. */ + if (d->mdsi->mode_flags & MIPI_DSI_MODE_LPM) + val |= DSI_CMD_MODE_CTL_IF1_LP_EN; val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK; writel(val, d->regs + DSI_CMD_MODE_CTL); @@ -904,10 +905,11 @@ static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) /* Command mode, clear IF1 ID */ val = readl(d->regs + DSI_CMD_MODE_CTL); /* - * If we enable low-power mode here with - * val |= DSI_CMD_MODE_CTL_IF1_LP_EN + * If we enable low-power mode here * the display updates become really slow. */ + if (d->mdsi->mode_flags & MIPI_DSI_MODE_LPM) + val |= DSI_CMD_MODE_CTL_IF1_LP_EN; val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK; writel(val, d->regs + DSI_CMD_MODE_CTL); } -- GitLab From c4842d4d0f744bf419a1b011fa3ce0ed98fcdc10 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 00:31:21 +0200 Subject: [PATCH 0406/1494] drm/mcde: Fix display pipeline restart To make sure that the MCDE is in a reasonable state during set-up, perform a reset by power cycling the block by dropping the on-chip regulator reference after probe. The display subsystem (DSS) has no dedicated reset line so dropping the EPOD regulator is the only real way of resetting it. We introduce code to enable and disable the regulator in the display enable/disable callbacks. We move the generic MCDE setup such as muxing of DPI signals and masking of interrupts to the display handling. When we drop the power to the whole display subsystem, not only MCDE but also the DSI links lose their state. Therefore we move the DSI block reset and hardware initialization code to the mcde_dsi_bridge_pre_enable() callback so this happens every time we start up the bridge, as we may have lost the power. We move the final disablement of the interrupts and clocks to the mcde_dsi_bridge_post_disable() callback rather than have it in the mcde_dsi_bridge_disable() callback, as some control messages may still be sent over the DSI host after the bridge has been shut down. This (together with a patch for the corresponding panel) makes the Samsung GT-S7710 successfully disable and re-enable its display, cutting all power while disabled and re-initializing the hardware when coming back up. Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Cc: newbytee@protonmail.com Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200808223122.1492124-3-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_display.c | 41 +++++++++++++++ drivers/gpu/drm/mcde/mcde_drm.h | 39 +++++++++++++++ drivers/gpu/drm/mcde/mcde_drv.c | 78 +++++++---------------------- drivers/gpu/drm/mcde/mcde_dsi.c | 57 +++++++++++++-------- 4 files changed, 133 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index cbc7c0c4955ad..d608cc894e011 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -7,6 +7,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/dma-buf.h> +#include <linux/regulator/consumer.h> #include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> @@ -879,6 +880,14 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, u32 formatter_frame; u32 pkt_div; u32 val; + int ret; + + /* This powers up the entire MCDE block and the DSI hardware */ + ret = regulator_enable(mcde->epod); + if (ret) { + dev_err(drm->dev, "can't re-enable EPOD regulator\n"); + return; + } dev_info(drm->dev, "enable MCDE, %d x %d format %s\n", mode->hdisplay, mode->vdisplay, @@ -889,6 +898,26 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, return; } + /* Set up the main control, watermark level at 7 */ + val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT; + /* 24 bits DPI: connect LSB Ch B to D[0:7] */ + val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT; + /* TV out: connect LSB Ch B to D[8:15] */ + val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT; + /* Don't care about this muxing */ + val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT; + /* 24 bits DPI: connect MID Ch B to D[24:31] */ + val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT; + /* 5: 24 bits DPI: connect MSB Ch B to D[32:39] */ + val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT; + /* Syncmux bits zero: DPI channel A and B on output pins A and B resp */ + writel(val, mcde->regs + MCDE_CONF0); + + /* Clear any pending interrupts */ + mcde_display_disable_irqs(mcde); + writel(0, mcde->regs + MCDE_IMSCERR); + writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR); + dev_info(drm->dev, "output in %s mode, format %dbpp\n", (mcde->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD", @@ -1005,6 +1034,11 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, dev_dbg(mcde->dev, "started MCDE video FIFO flow\n"); } + /* Enable automatic clock gating */ + val = readl(mcde->regs + MCDE_CR); + val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN; + writel(val, mcde->regs + MCDE_CR); + dev_info(drm->dev, "MCDE display is enabled\n"); } @@ -1014,6 +1048,7 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) struct drm_device *drm = crtc->dev; struct mcde *mcde = to_mcde(drm); struct drm_pending_vblank_event *event; + int ret; drm_crtc_vblank_off(crtc); @@ -1029,6 +1064,12 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) spin_unlock_irq(&crtc->dev->event_lock); } + ret = regulator_disable(mcde->epod); + if (ret) + dev_err(drm->dev, "can't disable EPOD regulator\n"); + /* Make sure we are powered down (before we may power up again) */ + usleep_range(50000, 70000); + dev_info(drm->dev, "MCDE display is disabled\n"); } diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index 3e406d7834650..9f197f4e9ced6 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -9,6 +9,45 @@ #ifndef _MCDE_DRM_H_ #define _MCDE_DRM_H_ +/* Shared basic registers */ +#define MCDE_CR 0x00000000 +#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_SHIFT 0 +#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_MASK 0x0000003F +#define MCDE_CR_IFIFOCTRLEN BIT(15) +#define MCDE_CR_UFRECOVERY_MODE_V422 BIT(16) +#define MCDE_CR_WRAP_MODE_V422_SHIFT BIT(17) +#define MCDE_CR_AUTOCLKG_EN BIT(30) +#define MCDE_CR_MCDEEN BIT(31) + +#define MCDE_CONF0 0x00000004 +#define MCDE_CONF0_SYNCMUX0 BIT(0) +#define MCDE_CONF0_SYNCMUX1 BIT(1) +#define MCDE_CONF0_SYNCMUX2 BIT(2) +#define MCDE_CONF0_SYNCMUX3 BIT(3) +#define MCDE_CONF0_SYNCMUX4 BIT(4) +#define MCDE_CONF0_SYNCMUX5 BIT(5) +#define MCDE_CONF0_SYNCMUX6 BIT(6) +#define MCDE_CONF0_SYNCMUX7 BIT(7) +#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT 12 +#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_MASK 0x00007000 +#define MCDE_CONF0_OUTMUX0_SHIFT 16 +#define MCDE_CONF0_OUTMUX0_MASK 0x00070000 +#define MCDE_CONF0_OUTMUX1_SHIFT 19 +#define MCDE_CONF0_OUTMUX1_MASK 0x00380000 +#define MCDE_CONF0_OUTMUX2_SHIFT 22 +#define MCDE_CONF0_OUTMUX2_MASK 0x01C00000 +#define MCDE_CONF0_OUTMUX3_SHIFT 25 +#define MCDE_CONF0_OUTMUX3_MASK 0x0E000000 +#define MCDE_CONF0_OUTMUX4_SHIFT 28 +#define MCDE_CONF0_OUTMUX4_MASK 0x70000000 + +#define MCDE_SSP 0x00000008 +#define MCDE_AIS 0x00000100 +#define MCDE_IMSCERR 0x00000110 +#define MCDE_RISERR 0x00000120 +#define MCDE_MISERR 0x00000130 +#define MCDE_SISERR 0x00000140 + enum mcde_flow_mode { /* One-shot mode: flow stops after one frame */ MCDE_COMMAND_ONESHOT_FLOW, diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 13418a15f8df2..c592957ed07fc 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -63,6 +63,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/delay.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> @@ -82,44 +83,6 @@ #define DRIVER_DESC "DRM module for MCDE" -#define MCDE_CR 0x00000000 -#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_SHIFT 0 -#define MCDE_CR_IFIFOEMPTYLINECOUNT_V422_MASK 0x0000003F -#define MCDE_CR_IFIFOCTRLEN BIT(15) -#define MCDE_CR_UFRECOVERY_MODE_V422 BIT(16) -#define MCDE_CR_WRAP_MODE_V422_SHIFT BIT(17) -#define MCDE_CR_AUTOCLKG_EN BIT(30) -#define MCDE_CR_MCDEEN BIT(31) - -#define MCDE_CONF0 0x00000004 -#define MCDE_CONF0_SYNCMUX0 BIT(0) -#define MCDE_CONF0_SYNCMUX1 BIT(1) -#define MCDE_CONF0_SYNCMUX2 BIT(2) -#define MCDE_CONF0_SYNCMUX3 BIT(3) -#define MCDE_CONF0_SYNCMUX4 BIT(4) -#define MCDE_CONF0_SYNCMUX5 BIT(5) -#define MCDE_CONF0_SYNCMUX6 BIT(6) -#define MCDE_CONF0_SYNCMUX7 BIT(7) -#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT 12 -#define MCDE_CONF0_IFIFOCTRLWTRMRKLVL_MASK 0x00007000 -#define MCDE_CONF0_OUTMUX0_SHIFT 16 -#define MCDE_CONF0_OUTMUX0_MASK 0x00070000 -#define MCDE_CONF0_OUTMUX1_SHIFT 19 -#define MCDE_CONF0_OUTMUX1_MASK 0x00380000 -#define MCDE_CONF0_OUTMUX2_SHIFT 22 -#define MCDE_CONF0_OUTMUX2_MASK 0x01C00000 -#define MCDE_CONF0_OUTMUX3_SHIFT 25 -#define MCDE_CONF0_OUTMUX3_MASK 0x0E000000 -#define MCDE_CONF0_OUTMUX4_SHIFT 28 -#define MCDE_CONF0_OUTMUX4_MASK 0x70000000 - -#define MCDE_SSP 0x00000008 -#define MCDE_AIS 0x00000100 -#define MCDE_IMSCERR 0x00000110 -#define MCDE_RISERR 0x00000120 -#define MCDE_MISERR 0x00000130 -#define MCDE_SISERR 0x00000140 - #define MCDE_PID 0x000001FC #define MCDE_PID_METALFIX_VERSION_SHIFT 0 #define MCDE_PID_METALFIX_VERSION_MASK 0x000000FF @@ -293,7 +256,6 @@ static int mcde_probe(struct platform_device *pdev) struct component_match *match = NULL; struct resource *res; u32 pid; - u32 val; int irq; int ret; int i; @@ -402,27 +364,7 @@ static int mcde_probe(struct platform_device *pdev) goto clk_disable; } - /* Set up the main control, watermark level at 7 */ - val = 7 << MCDE_CONF0_IFIFOCTRLWTRMRKLVL_SHIFT; - /* 24 bits DPI: connect LSB Ch B to D[0:7] */ - val |= 3 << MCDE_CONF0_OUTMUX0_SHIFT; - /* TV out: connect LSB Ch B to D[8:15] */ - val |= 3 << MCDE_CONF0_OUTMUX1_SHIFT; - /* Don't care about this muxing */ - val |= 0 << MCDE_CONF0_OUTMUX2_SHIFT; - /* 24 bits DPI: connect MID Ch B to D[24:31] */ - val |= 4 << MCDE_CONF0_OUTMUX3_SHIFT; - /* 5: 24 bits DPI: connect MSB Ch B to D[32:39] */ - val |= 5 << MCDE_CONF0_OUTMUX4_SHIFT; - /* Syncmux bits zero: DPI channel A and B on output pins A and B resp */ - writel(val, mcde->regs + MCDE_CONF0); - - /* Enable automatic clock gating */ - val = readl(mcde->regs + MCDE_CR); - val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN; - writel(val, mcde->regs + MCDE_CR); - - /* Clear any pending interrupts */ + /* Disable and clear any pending interrupts */ mcde_display_disable_irqs(mcde); writel(0, mcde->regs + MCDE_IMSCERR); writel(0xFFFFFFFF, mcde->regs + MCDE_RISERR); @@ -452,12 +394,28 @@ static int mcde_probe(struct platform_device *pdev) ret = PTR_ERR(match); goto clk_disable; } + + /* + * Perform an invasive reset of the MCDE and all blocks by + * cutting the power to the subsystem, then bring it back up + * later when we enable the display as a result of + * component_master_add_with_match(). + */ + ret = regulator_disable(mcde->epod); + if (ret) { + dev_err(dev, "can't disable EPOD regulator\n"); + return ret; + } + /* Wait 50 ms so we are sure we cut the power */ + usleep_range(50000, 70000); + ret = component_master_add_with_match(&pdev->dev, &mcde_drm_comp_ops, match); if (ret) { dev_err(dev, "failed to add component master\n"); goto clk_disable; } + return 0; clk_disable: diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index 5cea8cbf084c7..ae3d146912f21 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -43,6 +43,7 @@ struct mcde_dsi { struct drm_bridge *bridge_out; struct mipi_dsi_host dsi_host; struct mipi_dsi_device *mdsi; + const struct drm_display_mode *mode; struct clk *hs_clk; struct clk *lp_clk; unsigned long hs_freq; @@ -885,7 +886,25 @@ static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) dev_info(d->dev, "DSI HS clock rate %lu Hz\n", d->hs_freq); + /* Assert RESET through the PRCMU, active low */ + /* FIXME: which DSI block? */ + regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET, + PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0); + + usleep_range(100, 200); + + /* De-assert RESET again */ + regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET, + PRCM_DSI_SW_RESET_DSI0_SW_RESETN, + PRCM_DSI_SW_RESET_DSI0_SW_RESETN); + + /* Start up the hardware */ + mcde_dsi_start(d); + if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { + /* Set up the video mode from the DRM mode */ + mcde_dsi_setup_video_mode(d, d->mode); + /* Put IF1 into video mode */ val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); val |= DSI_MCTL_MAIN_DATA_CTL_IF1_MODE; @@ -926,13 +945,12 @@ static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, return; } + d->mode = mode; + dev_info(d->dev, "set DSI master to %dx%d %u Hz %s mode\n", mode->hdisplay, mode->vdisplay, mode->clock * 1000, (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD" ); - - if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) - mcde_dsi_setup_video_mode(d, mode); } static void mcde_dsi_wait_for_command_mode_stop(struct mcde_dsi *d) @@ -981,9 +999,6 @@ static void mcde_dsi_bridge_disable(struct drm_bridge *bridge) struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); u32 val; - /* Disable all error interrupts */ - writel(0, d->regs + DSI_VID_MODE_STS_CTL); - if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { /* Stop video mode */ val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); @@ -994,8 +1009,20 @@ static void mcde_dsi_bridge_disable(struct drm_bridge *bridge) /* Stop command mode */ mcde_dsi_wait_for_command_mode_stop(d); } +} - /* Stop clocks */ +static void mcde_dsi_bridge_post_disable(struct drm_bridge *bridge) +{ + struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); + + /* + * Stop clocks and terminate any DSI traffic here so the panel can + * send commands to shut down the display using DSI direct write until + * this point. + */ + + /* Disable all error interrupts */ + writel(0, d->regs + DSI_VID_MODE_STS_CTL); clk_disable_unprepare(d->hs_clk); clk_disable_unprepare(d->lp_clk); } @@ -1028,6 +1055,7 @@ static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = { .disable = mcde_dsi_bridge_disable, .enable = mcde_dsi_bridge_enable, .pre_enable = mcde_dsi_bridge_pre_enable, + .post_disable = mcde_dsi_bridge_post_disable, }; static int mcde_dsi_bind(struct device *dev, struct device *master, @@ -1063,21 +1091,6 @@ static int mcde_dsi_bind(struct device *dev, struct device *master, return PTR_ERR(d->lp_clk); } - /* Assert RESET through the PRCMU, active low */ - /* FIXME: which DSI block? */ - regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET, - PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0); - - usleep_range(100, 200); - - /* De-assert RESET again */ - regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET, - PRCM_DSI_SW_RESET_DSI0_SW_RESETN, - PRCM_DSI_SW_RESET_DSI0_SW_RESETN); - - /* Start up the hardware */ - mcde_dsi_start(d); - /* Look for a panel as a child to this node */ for_each_available_child_of_node(dev->of_node, child) { panel = of_drm_find_panel(child); -- GitLab From 42bac89a1730a32ed8415b745affc7de0be28e45 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 00:31:22 +0200 Subject: [PATCH 0407/1494] drm/mcde: Enable the DSI link with display The MCDE DSI link hardware which is modeled like a bridge in DRM, connected further to the panel bridge, creating a pipeline. We have been using the .pre_enable(), .enable(), .disable() and .post_disable() callbacks from the bridge to set this up in a chained manner: first the display controller goes online and then in successive order each bridge in the pipeline. Inside DRM it works like this: drm_atomic_helper_commit_tail() drm_atomic_helper_commit_modeset_enables() struct drm_crtc_helper_funcs .atomic_enable() struct drm_simple_display_pipe_funcs .enable() MCDE display enable call drm_atomic_bridge_chain_enable() struct drm_bridge_funcs .pre_enable() mcde_dsi_bridge_pre_enable() panel_bridge_pre_enable() struct drm_panel_funcs .prepare() struct drm_bridge_funcs .enable() mcde_dsi_bridge_enable() panel_bridge_enable() struct drm_panel_funcs .enable() A similar sequence is executed for disabling. Unfortunately this is not what the hardware needs: at a certain stage in the enablement of the display controller the DSI link needs to come up to support video mode, else something (like a FIFO flow) locks up the hardware and we never get picture. Fix this by simply leaving the pre|enable and post|disable callbacks unused, and establish two cross-calls from the display controller to bring up the DSI link at the right place in the display bring-up sequence and vice versa in the shutdown sequence. For command mode displays, it works just fine to also enable the display flow early. The only time we hold it back right now is in one-shot mode, on-demand display updates. When combined with the previous patch and some patches for the S6E63M0 display controller to support DSI mode, this gives working display on the Samsung GT-I8190 (Golden) phone. It has also been tested working on the Samsung GT-S7710 (Skomer) phone. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: newbytee@protonmail.com Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200808223122.1492124-4-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_display.c | 36 +++++++++++++++++------ drivers/gpu/drm/mcde/mcde_drm.h | 2 ++ drivers/gpu/drm/mcde/mcde_dsi.c | 44 +++++++++++------------------ 3 files changed, 47 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_display.c b/drivers/gpu/drm/mcde/mcde_display.c index d608cc894e011..c271e5bf042ed 100644 --- a/drivers/gpu/drm/mcde/mcde_display.c +++ b/drivers/gpu/drm/mcde/mcde_display.c @@ -999,6 +999,16 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, mcde_configure_fifo(mcde, MCDE_FIFO_A, MCDE_DSI_FORMATTER_0, fifo_wtrmrk); + /* + * This brings up the DSI bridge which is tightly connected + * to the MCDE DSI formatter. + * + * FIXME: if we want to use another formatter, such as DPI, + * we need to be more elaborate here and select the appropriate + * bridge. + */ + mcde_dsi_enable(mcde->bridge); + /* Configure the DSI formatter 0 for the DSI panel output */ mcde_configure_dsi_formatter(mcde, MCDE_DSI_FORMATTER_0, formatter_frame, pkt_size); @@ -1025,16 +1035,20 @@ static void mcde_display_enable(struct drm_simple_display_pipe *pipe, drm_crtc_vblank_on(crtc); - if (mcde_flow_is_video(mcde)) { - /* - * Keep FIFO permanently enabled in video mode, - * otherwise MCDE will stop feeding data to the panel. - */ + /* + * If we're using oneshot mode we don't start the flow + * until each time the display is given an update, and + * then we disable it immediately after. For all other + * modes (command or video) we start the FIFO flow + * right here. This is necessary for the hardware to + * behave right. + */ + if (mcde->flow_mode != MCDE_COMMAND_ONESHOT_FLOW) { mcde_enable_fifo(mcde, MCDE_FIFO_A); dev_dbg(mcde->dev, "started MCDE video FIFO flow\n"); } - /* Enable automatic clock gating */ + /* Enable MCDE with automatic clock gating */ val = readl(mcde->regs + MCDE_CR); val |= MCDE_CR_MCDEEN | MCDE_CR_AUTOCLKG_EN; writel(val, mcde->regs + MCDE_CR); @@ -1055,6 +1069,9 @@ static void mcde_display_disable(struct drm_simple_display_pipe *pipe) /* Disable FIFO A flow */ mcde_disable_fifo(mcde, MCDE_FIFO_A, true); + /* This disables the DSI bridge */ + mcde_dsi_disable(mcde->bridge); + event = crtc->state->event; if (event) { crtc->state->event = NULL; @@ -1164,8 +1181,11 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe, if (fb) { mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0)); dev_info_once(mcde->dev, "first update of display contents\n"); - /* The flow is already active in video mode */ - if (!mcde_flow_is_video(mcde) && mcde->flow_active == 0) + /* + * Usually the flow is already active, unless we are in + * oneshot mode, then we need to kick the flow right here. + */ + if (mcde->flow_active == 0) mcde_start_flow(mcde); } else { /* diff --git a/drivers/gpu/drm/mcde/mcde_drm.h b/drivers/gpu/drm/mcde/mcde_drm.h index 9f197f4e9ced6..8253e2f9993ec 100644 --- a/drivers/gpu/drm/mcde/mcde_drm.h +++ b/drivers/gpu/drm/mcde/mcde_drm.h @@ -97,6 +97,8 @@ static inline bool mcde_flow_is_video(struct mcde *mcde) bool mcde_dsi_irq(struct mipi_dsi_device *mdsi); void mcde_dsi_te_request(struct mipi_dsi_device *mdsi); +void mcde_dsi_enable(struct drm_bridge *bridge); +void mcde_dsi_disable(struct drm_bridge *bridge); extern struct platform_driver mcde_dsi_driver; void mcde_display_irq(struct mcde *mcde); diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index ae3d146912f21..ae70f76bfb89a 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -826,23 +826,11 @@ static void mcde_dsi_start(struct mcde_dsi *d) dev_info(d->dev, "DSI link enabled\n"); } - -static void mcde_dsi_bridge_enable(struct drm_bridge *bridge) -{ - struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); - u32 val; - - if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) { - /* Enable video mode */ - val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); - val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN; - writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); - } - - dev_info(d->dev, "enable DSI master\n"); -}; - -static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) +/* + * Notice that this is called from inside the display controller + * and not from the bridge callbacks. + */ +void mcde_dsi_enable(struct drm_bridge *bridge) { struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); unsigned long hs_freq, lp_freq; @@ -920,6 +908,11 @@ static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC; val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA; writel(val, d->regs + DSI_VID_MODE_STS_CTL); + + /* Enable video mode */ + val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL); + val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN; + writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL); } else { /* Command mode, clear IF1 ID */ val = readl(d->regs + DSI_CMD_MODE_CTL); @@ -932,6 +925,8 @@ static void mcde_dsi_bridge_pre_enable(struct drm_bridge *bridge) val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK; writel(val, d->regs + DSI_CMD_MODE_CTL); } + + dev_info(d->dev, "enabled MCDE DSI master\n"); } static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge, @@ -994,7 +989,11 @@ static void mcde_dsi_wait_for_video_mode_stop(struct mcde_dsi *d) } } -static void mcde_dsi_bridge_disable(struct drm_bridge *bridge) +/* + * Notice that this is called from inside the display controller + * and not from the bridge callbacks. + */ +void mcde_dsi_disable(struct drm_bridge *bridge) { struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); u32 val; @@ -1009,11 +1008,6 @@ static void mcde_dsi_bridge_disable(struct drm_bridge *bridge) /* Stop command mode */ mcde_dsi_wait_for_command_mode_stop(d); } -} - -static void mcde_dsi_bridge_post_disable(struct drm_bridge *bridge) -{ - struct mcde_dsi *d = bridge_to_mcde_dsi(bridge); /* * Stop clocks and terminate any DSI traffic here so the panel can @@ -1052,10 +1046,6 @@ static int mcde_dsi_bridge_attach(struct drm_bridge *bridge, static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = { .attach = mcde_dsi_bridge_attach, .mode_set = mcde_dsi_bridge_mode_set, - .disable = mcde_dsi_bridge_disable, - .enable = mcde_dsi_bridge_enable, - .pre_enable = mcde_dsi_bridge_pre_enable, - .post_disable = mcde_dsi_bridge_post_disable, }; static int mcde_dsi_bind(struct device *dev, struct device *master, -- GitLab From f098f168e91ca915c6cf8aa316136af647792f2f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Thu, 13 Aug 2020 01:02:44 +0300 Subject: [PATCH 0408/1494] drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel The OrtusTech COM43H4M85ULC panel is a 18-bit RGB panel, set the bus format to MEDIA_BUS_FMT_RGB666_1X18. Fixes: 725c9d40f3fe ("drm/panel: Add support for OrtusTech COM43H4M85ULC panel") Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Sam Ravnborg <sam.ravnborg@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200812220244.24500-1-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/panel/panel-simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index ef8df838fe14f..ef04fd75babd3 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3018,7 +3018,7 @@ static const struct panel_desc ortustech_com43h4m85ulc = { .width = 56, .height = 93, }, - .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_format = MEDIA_BUS_FMT_RGB666_1X18, .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, .connector_type = DRM_MODE_CONNECTOR_DPI, }; -- GitLab From f75e94d86829e92a758a26fc5bbdb4c9eba86260 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Tue, 4 Aug 2020 15:00:53 +0800 Subject: [PATCH 0409/1494] drm/amdgpu: bypass querying ras error count registers Once ras recovery is issued by ras sync flood interrupt or ras controller interrupt, add this guard to bypass or execute ras error count register harvest of all IPs. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 22 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 ++ drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 48 +++++++++++++------------ 3 files changed, 41 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 1a55f6f492fdb..fbe464c68e5b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1547,17 +1547,19 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) struct list_head device_list, *device_list_handle = NULL; struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, false); - /* Build list of devices to query RAS related errors */ - if (hive && adev->gmc.xgmi.num_physical_nodes > 1) - device_list_handle = &hive->device_list; - else { - INIT_LIST_HEAD(&device_list); - list_add_tail(&adev->gmc.xgmi.head, &device_list); - device_list_handle = &device_list; - } + if (!ras->disable_ras_err_cnt_harvest) { + /* Build list of devices to query RAS related errors */ + if (hive && adev->gmc.xgmi.num_physical_nodes > 1) { + device_list_handle = &hive->device_list; + } else { + INIT_LIST_HEAD(&device_list); + list_add_tail(&adev->gmc.xgmi.head, &device_list); + device_list_handle = &device_list; + } - list_for_each_entry(remote_adev, device_list_handle, gmc.xgmi.head) { - amdgpu_ras_log_on_err_counter(remote_adev); + list_for_each_entry(remote_adev, + device_list_handle, gmc.xgmi.head) + amdgpu_ras_log_on_err_counter(remote_adev); } if (amdgpu_device_should_recover_gpu(ras->adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 70a6fca736178..6b8d7bb83bb3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -343,6 +343,9 @@ struct amdgpu_ras { /* bad page count threshold */ uint32_t bad_page_cnt_threshold; + + /* disable ras error count harvest in recovery */ + bool disable_ras_err_cnt_harvest; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index e629156173d31..eadc9526d33fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -302,6 +302,7 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device uint32_t bif_doorbell_intr_cntl; struct ras_manager *obj = amdgpu_ras_find_obj(adev, adev->nbio.ras_if); struct ras_err_data err_data = {0, 0, 0, NULL}; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); if (REG_GET_FIELD(bif_doorbell_intr_cntl, @@ -312,28 +313,31 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device RAS_CNTLR_INTERRUPT_CLEAR, 1); WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); - /* - * clear error status after ras_controller_intr according to - * hw team and count ue number for query - */ - nbio_v7_4_query_ras_error_count(adev, &err_data); - - /* logging on error counter and printing for awareness */ - obj->err_data.ue_count += err_data.ue_count; - obj->err_data.ce_count += err_data.ce_count; - - if (err_data.ce_count) - dev_info(adev->dev, "%ld correctable hardware " - "errors detected in %s block, " - "no user action is needed.\n", - obj->err_data.ce_count, - adev->nbio.ras_if->name); - - if (err_data.ue_count) - dev_info(adev->dev, "%ld uncorrectable hardware " - "errors detected in %s block\n", - obj->err_data.ue_count, - adev->nbio.ras_if->name); + if (!ras->disable_ras_err_cnt_harvest) { + /* + * clear error status after ras_controller_intr + * according to hw team and count ue number + * for query + */ + nbio_v7_4_query_ras_error_count(adev, &err_data); + + /* logging on error cnt and printing for awareness */ + obj->err_data.ue_count += err_data.ue_count; + obj->err_data.ce_count += err_data.ce_count; + + if (err_data.ce_count) + dev_info(adev->dev, "%ld correctable hardware " + "errors detected in %s block, " + "no user action is needed.\n", + obj->err_data.ce_count, + adev->nbio.ras_if->name); + + if (err_data.ue_count) + dev_info(adev->dev, "%ld uncorrectable hardware " + "errors detected in %s block\n", + obj->err_data.ue_count, + adev->nbio.ras_if->name); + } dev_info(adev->dev, "RAS controller interrupt triggered " "by NBIF error\n"); -- GitLab From 66459e1db2f8b6f7cdfe0d091345b56d12348d0d Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Tue, 4 Aug 2020 15:05:01 +0800 Subject: [PATCH 0410/1494] drm/amdgpu: add debugfs node to toggle ras error cnt harvest Before ras recovery is issued, user could operate this debugfs node to enable/disable the harvest of all RAS IPs' ras error count registers, which will help keep hardware's registers' status instead of cleaning up them. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fbe464c68e5b4..2d1fad1abf7a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1215,6 +1215,13 @@ static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) */ debugfs_create_bool("auto_reboot", S_IWUGO | S_IRUGO, con->dir, &con->reboot); + + /* + * User could set this not to clean up hardware's error count register + * of RAS IPs during ras recovery. + */ + debugfs_create_bool("disable_ras_err_cnt_harvest", 0644, + con->dir, &con->disable_ras_err_cnt_harvest); } void amdgpu_ras_debugfs_create(struct amdgpu_device *adev, -- GitLab From d58fe3cf11a86e59183c8b91c50ae2cde24a2128 Mon Sep 17 00:00:00 2001 From: "Tianci.Yin" <tianci.yin@amd.com> Date: Fri, 19 Jun 2020 16:01:11 +0800 Subject: [PATCH 0411/1494] drm/amdgpu: add interface amdgpu_gfx_init_spm_golden for Navi1x On Navi1x, the SPM golden settings are lost after GFXOFF enter/exit, so reconfiguration is needed. Make the configuration code as an interface for future use. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Feifei Xu <Feifei.Xu@amd.com> Signed-off-by: Tianci.Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 34 ++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 1e7a2b0997c56..a611e78dd4bac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -216,6 +216,7 @@ struct amdgpu_gfx_funcs { int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if); int (*query_ras_error_count) (struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count) (struct amdgpu_device *adev); + void (*init_spm_golden)(struct amdgpu_device *adev); }; struct sq_work { @@ -324,6 +325,7 @@ struct amdgpu_gfx { #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) #define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance)) #define amdgpu_gfx_select_me_pipe_q(adev, me, pipe, q, vmid) (adev)->gfx.funcs->select_me_pipe_q((adev), (me), (pipe), (q), (vmid)) +#define amdgpu_gfx_init_spm_golden(adev) (adev)->gfx.funcs->init_spm_golden((adev)) /** * amdgpu_gfx_create_bitmask - create a bitmask diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 0702c94fcca32..d851fe80eaf4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3307,6 +3307,29 @@ static void gfx_v10_0_set_kiq_pm4_funcs(struct amdgpu_device *adev) adev->gfx.kiq.pmf = &gfx_v10_0_kiq_pm4_funcs; } +static void gfx_v10_0_init_spm_golden_registers(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_NAVI10: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_0_nv10, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_0_nv10)); + break; + case CHIP_NAVI14: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_1_nv14, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_nv14)); + break; + case CHIP_NAVI12: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_1_2_nv12, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_2_nv12)); + break; + default: + break; + } +} + static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) { switch (adev->asic_type) { @@ -3317,9 +3340,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_0_nv10, (const u32)ARRAY_SIZE(golden_settings_gc_10_0_nv10)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_0_nv10, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_0_nv10)); break; case CHIP_NAVI14: soc15_program_register_sequence(adev, @@ -3328,9 +3348,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_1_nv14, (const u32)ARRAY_SIZE(golden_settings_gc_10_1_nv14)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_1_nv14, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_nv14)); break; case CHIP_NAVI12: soc15_program_register_sequence(adev, @@ -3339,9 +3356,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_1_2_nv12, (const u32)ARRAY_SIZE(golden_settings_gc_10_1_2_nv12)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_1_2_nv12, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_2_nv12)); break; case CHIP_SIENNA_CICHLID: soc15_program_register_sequence(adev, @@ -3360,6 +3374,7 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) default: break; } + gfx_v10_0_init_spm_golden_registers(adev); } static void gfx_v10_0_scratch_init(struct amdgpu_device *adev) @@ -4149,6 +4164,7 @@ static const struct amdgpu_gfx_funcs gfx_v10_0_gfx_funcs = { .read_wave_sgprs = &gfx_v10_0_read_wave_sgprs, .read_wave_vgprs = &gfx_v10_0_read_wave_vgprs, .select_me_pipe_q = &gfx_v10_0_select_me_pipe_q, + .init_spm_golden = &gfx_v10_0_init_spm_golden_registers, }; static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev) -- GitLab From 425a78f43b34a6bebc5c2746eb09a3b45a45a286 Mon Sep 17 00:00:00 2001 From: "Tianci.Yin" <tianci.yin@amd.com> Date: Mon, 20 Jul 2020 15:47:37 +0800 Subject: [PATCH 0412/1494] drm/amdgpu: reconfigure spm golden settings on Navi1x after GFXOFF exit(v3) On Navi1x, the SPM golden settings are lost after GFXOFF enter/exit, so reconfigure the golden settings after GFXOFF exit. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Tianci.Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 0cd9de69932bc..8ccd17d02cc60 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -560,8 +560,14 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable) if (enable && !adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) { schedule_delayed_work(&adev->gfx.gfx_off_delay_work, GFX_OFF_DELAY_ENABLE); } else if (!enable && adev->gfx.gfx_off_state) { - if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) + if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) { adev->gfx.gfx_off_state = false; + + if (adev->gfx.funcs->init_spm_golden) { + dev_dbg(adev->dev, "GFXOFF is disabled, re-init SPM golden settings\n"); + amdgpu_gfx_init_spm_golden(adev); + } + } } mutex_unlock(&adev->gfx.gfx_off_mutex); -- GitLab From a189d0ae0cd68643204cbe9b11e824414b2b06c9 Mon Sep 17 00:00:00 2001 From: Wenhui Sheng <Wenhui.Sheng@amd.com> Date: Thu, 23 Jul 2020 10:57:06 +0800 Subject: [PATCH 0413/1494] drm/amdgpu: add RAP TA header file The RAP TA contains tests used to verify if RAP(Register Access Policy), or otherwise known as Security Policy is applied correctly by PSP BL&TOS. The RAP test is a measure to ensure that we reduce the avenue of complexity and mistakes when dealing with RAP in post-si execution, where debugging failures related to RAP is quite difficult and expensive. v2: add introduction for RAP TA Signed-off-by: Wenhui Sheng <Wenhui.Sheng@amd.com> Reviewed-by: Guchun Chen <Guchun.Chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/ta_rap_if.h | 84 ++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/ta_rap_if.h diff --git a/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h b/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h new file mode 100644 index 0000000000000..f14833fae07c8 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _TA_RAP_IF_H +#define _TA_RAP_IF_H + +/* Responses have bit 31 set */ +#define RSP_ID_MASK (1U << 31) +#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK) + +enum ta_rap_status { + TA_RAP_STATUS__SUCCESS = 1, + TA_RAP_STATUS__ERROR_GENERIC_FAILURE = 2, + TA_RAP_STATUS__ERROR_CMD_NOT_SUPPORTED = 3, + TA_RAP_STATUS__ERROR_INVALID_VALIDATION_METHOD = 4, + TA_RAP_STATUS__ERROR_NULL_POINTER = 5, + TA_RAP_STATUS__ERROR_NOT_INITIALIZED = 6, + TA_RAP_STATUS__ERROR_VALIDATION_FAILED = 7, + TA_RAP_STATUS__ERROR_ASIC_NOT_SUPPORTED = 8, + TA_RAP_STATUS__ERROR_OPERATION_NOT_PERMISSABLE = 9, + TA_RAP_STATUS__ERROR_ALREADY_INIT = 10, +}; + +enum ta_rap_cmd { + TA_CMD_RAP__INITIALIZE = 1, + TA_CMD_RAP__VALIDATE_L0 = 2, +}; + +enum ta_rap_validation_method { + METHOD_A = 1, +}; + +struct ta_rap_cmd_input_data { + uint8_t reserved[8]; +}; + +struct ta_rap_cmd_output_data { + uint32_t last_subsection; + uint32_t num_total_validate; + uint32_t num_valid; + uint32_t last_validate_addr; + uint32_t last_validate_val; + uint32_t last_validate_val_exptd; +}; + +union ta_rap_cmd_input { + struct ta_rap_cmd_input_data input; +}; + +union ta_rap_cmd_output { + struct ta_rap_cmd_output_data output; +}; + +struct ta_rap_shared_memory { + uint32_t cmd_id; + uint32_t validation_method_id; + uint32_t resp_id; + enum ta_rap_status rap_status; + union ta_rap_cmd_input rap_in_message; + union ta_rap_cmd_output rap_out_message; + uint8_t reserved[64]; +}; + +#endif // #define _TA_RAP_IF_H -- GitLab From 8602692b6f73d2ea0312cccea5416b270d0f7247 Mon Sep 17 00:00:00 2001 From: Wenhui Sheng <Wenhui.Sheng@amd.com> Date: Fri, 17 Jul 2020 16:55:20 +0800 Subject: [PATCH 0414/1494] drm/amdgpu: enable RAP TA load Enable the RAP TA loading path and add RAP test trigger interface. v2: fix potential mem leak issue Signed-off-by: Wenhui Sheng <Wenhui.Sheng@amd.com> Reviewed-by: Guchun Chen <Guchun.Chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 183 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 17 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + 3 files changed, 201 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c68369731b20a..116a89990f39e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1430,6 +1430,168 @@ static int psp_dtm_terminate(struct psp_context *psp) } // DTM end +// RAP start +static int psp_rap_init_shared_buf(struct psp_context *psp) +{ + int ret; + + /* + * Allocate 16k memory aligned to 4k from Frame Buffer (local + * physical) for rap ta <-> Driver + */ + ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, + &psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + return ret; +} + +static int psp_rap_load(struct psp_context *psp) +{ + int ret; + struct psp_gfx_cmd_resp *cmd; + + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + memset(psp->fw_pri_buf, 0, PSP_1_MEG); + memcpy(psp->fw_pri_buf, psp->ta_rap_start_addr, psp->ta_rap_ucode_size); + + psp_prep_ta_load_cmd_buf(cmd, + psp->fw_pri_mc_addr, + psp->ta_rap_ucode_size, + psp->rap_context.rap_shared_mc_addr, + PSP_RAP_SHARED_MEM_SIZE); + + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + + if (!ret) { + psp->rap_context.rap_initialized = true; + psp->rap_context.session_id = cmd->resp.session_id; + mutex_init(&psp->rap_context.mutex); + } + + kfree(cmd); + + return ret; +} + +static int psp_rap_unload(struct psp_context *psp) +{ + int ret; + struct psp_gfx_cmd_resp *cmd; + + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id); + + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + + kfree(cmd); + + return ret; +} + +static int psp_rap_initialize(struct psp_context *psp) +{ + int ret; + + /* + * TODO: bypass the initialize in sriov for now + */ + if (amdgpu_sriov_vf(psp->adev)) + return 0; + + if (!psp->adev->psp.ta_rap_ucode_size || + !psp->adev->psp.ta_rap_start_addr) { + dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); + return 0; + } + + if (!psp->rap_context.rap_initialized) { + ret = psp_rap_init_shared_buf(psp); + if (ret) + return ret; + } + + ret = psp_rap_load(psp); + if (ret) + return ret; + + ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE); + if (ret != TA_RAP_STATUS__SUCCESS) { + psp_rap_unload(psp); + + amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + psp->rap_context.rap_initialized = false; + + dev_warn(psp->adev->dev, "RAP TA initialize fail.\n"); + return -EINVAL; + } + + return 0; +} + +static int psp_rap_terminate(struct psp_context *psp) +{ + int ret; + + if (!psp->rap_context.rap_initialized) + return 0; + + ret = psp_rap_unload(psp); + + psp->rap_context.rap_initialized = false; + + /* free rap shared memory */ + amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + return ret; +} + +int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id) +{ + struct ta_rap_shared_memory *rap_cmd; + int ret; + + if (!psp->rap_context.rap_initialized) + return -EINVAL; + + if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && + ta_cmd_id != TA_CMD_RAP__VALIDATE_L0) + return -EINVAL; + + mutex_lock(&psp->rap_context.mutex); + + rap_cmd = (struct ta_rap_shared_memory *) + psp->rap_context.rap_shared_buf; + memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); + + rap_cmd->cmd_id = ta_cmd_id; + rap_cmd->validation_method_id = METHOD_A; + + ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id); + if (ret) { + mutex_unlock(&psp->rap_context.mutex); + return ret; + } + + mutex_unlock(&psp->rap_context.mutex); + + return rap_cmd->rap_status; +} +// RAP end + static int psp_hw_start(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; @@ -1892,6 +2054,11 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) dev_err(psp->adev->dev, "DTM: Failed to initialize DTM\n"); + + ret = psp_rap_initialize(psp); + if (ret) + dev_err(psp->adev->dev, + "RAP: Failed to initialize RAP\n"); } return 0; @@ -1942,6 +2109,7 @@ static int psp_hw_fini(void *handle) if (psp->adev->psp.ta_fw) { psp_ras_terminate(psp); + psp_rap_terminate(psp); psp_dtm_terminate(psp); psp_hdcp_terminate(psp); } @@ -2000,6 +2168,11 @@ static int psp_suspend(void *handle) DRM_ERROR("Failed to terminate dtm ta\n"); return ret; } + ret = psp_rap_terminate(psp); + if (ret) { + DRM_ERROR("Failed to terminate rap ta\n"); + return ret; + } } ret = psp_asd_unload(psp); @@ -2078,6 +2251,11 @@ static int psp_resume(void *handle) if (ret) dev_err(psp->adev->dev, "DTM: Failed to initialize DTM\n"); + + ret = psp_rap_initialize(psp); + if (ret) + dev_err(psp->adev->dev, + "RAP: Failed to initialize RAP\n"); } mutex_unlock(&adev->firmware.mutex); @@ -2343,6 +2521,11 @@ int parse_ta_bin_descriptor(struct psp_context *psp, psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes); psp->ta_dtm_start_addr = ucode_start_addr; break; + case TA_FW_TYPE_PSP_RAP: + psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version); + psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes); + psp->ta_rap_start_addr = ucode_start_addr; + break; default: dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 623888bf30cb7..919d2fb7427b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -29,6 +29,7 @@ #include "psp_gfx_if.h" #include "ta_xgmi_if.h" #include "ta_ras_if.h" +#include "ta_rap_if.h" #define PSP_FENCE_BUFFER_SIZE 0x1000 #define PSP_CMD_BUFFER_SIZE 0x1000 @@ -38,6 +39,7 @@ #define PSP_TMR_SIZE 0x400000 #define PSP_HDCP_SHARED_MEM_SIZE 0x4000 #define PSP_DTM_SHARED_MEM_SIZE 0x4000 +#define PSP_RAP_SHARED_MEM_SIZE 0x4000 #define PSP_SHARED_MEM_SIZE 0x4000 struct psp_context; @@ -159,6 +161,15 @@ struct psp_dtm_context { struct mutex mutex; }; +struct psp_rap_context { + bool rap_initialized; + uint32_t session_id; + struct amdgpu_bo *rap_shared_bo; + uint64_t rap_shared_mc_addr; + void *rap_shared_buf; + struct mutex mutex; +}; + #define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942 #define GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES 0x1000 #define GDDR6_MEM_TRAINING_OFFSET 0x8000 @@ -277,11 +288,16 @@ struct psp_context uint32_t ta_dtm_ucode_size; uint8_t *ta_dtm_start_addr; + uint32_t ta_rap_ucode_version; + uint32_t ta_rap_ucode_size; + uint8_t *ta_rap_start_addr; + struct psp_asd_context asd_context; struct psp_xgmi_context xgmi_context; struct psp_ras_context ras; struct psp_hdcp_context hdcp_context; struct psp_dtm_context dtm_context; + struct psp_rap_context rap_context; struct mutex mutex; struct psp_memory_training_context mem_train_ctx; }; @@ -357,6 +373,7 @@ int psp_ras_trigger_error(struct psp_context *psp, int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id); +int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_rlc_autoload_start(struct psp_context *psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 12a8bc8fca0b0..3c23c6293ff94 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -131,6 +131,7 @@ enum ta_fw_type { TA_FW_TYPE_PSP_RAS, TA_FW_TYPE_PSP_HDCP, TA_FW_TYPE_PSP_DTM, + TA_FW_TYPE_PSP_RAP, }; struct ta_fw_bin_desc { -- GitLab From a4322e1881bed80ddb904482f0b2e948fa7fd47e Mon Sep 17 00:00:00 2001 From: Wenhui Sheng <Wenhui.Sheng@amd.com> Date: Tue, 11 Aug 2020 11:02:03 +0800 Subject: [PATCH 0415/1494] drm/amdgpu: add debugfs interface for RAP test After amdgpu driver loading successfully, we can use RAP debugfs interface <debugfs_dir>/dri/xxx/rap_test to trigger RAP test. Currently only L0 validate test is supported. v2: refine amdgpu_rap.h Signed-off-by: Wenhui Sheng <Wenhui.Sheng@amd.com> Reviewed-by: Guchun Chen <Guchun.Chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c | 127 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h | 30 +++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 0ba396e9d7e40..dec1927ca75d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -55,7 +55,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ - amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o + amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 3a4b31b1c4f2f..0af249a1e35b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -34,6 +34,7 @@ #include "amdgpu_pm.h" #include "amdgpu_dm_debugfs.h" #include "amdgpu_ras.h" +#include "amdgpu_rap.h" /** * amdgpu_debugfs_add_files - Add simple debugfs entries @@ -1623,6 +1624,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) amdgpu_debugfs_autodump_init(adev); + amdgpu_rap_debugfs_init(adev); + return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, ARRAY_SIZE(amdgpu_debugfs_list)); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c new file mode 100644 index 0000000000000..87cbc9011b2d6 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c @@ -0,0 +1,127 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + */ +#include <linux/debugfs.h> +#include <linux/pm_runtime.h> + +#include "amdgpu.h" +#include "amdgpu_rap.h" + +/** + * DOC: AMDGPU RAP debugfs test interface + * + * how to use? + * echo opcode > <debugfs_dir>/dri/xxx/rap_test + * + * opcode: + * currently, only 2 is supported by Linux host driver, + * opcode 2 stands for TA_CMD_RAP__VALIDATE_L0, used to + * trigger L0 policy validation, you can refer more detail + * from header file ta_rap_if.h + * + */ +static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; + struct ta_rap_shared_memory *rap_shared_mem; + struct ta_rap_cmd_output_data *rap_cmd_output; + struct drm_device *dev = adev->ddev; + uint32_t op; + int ret; + + if (*pos || size != 2) + return -EINVAL; + + ret = kstrtouint_from_user(buf, size, *pos, &op); + if (ret) + return ret; + + ret = pm_runtime_get_sync(dev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(dev->dev); + return ret; + } + + /* make sure gfx core is on, RAP TA cann't handle + * GFX OFF case currently. + */ + amdgpu_gfx_off_ctrl(adev, false); + + switch (op) { + case 2: + ret = psp_rap_invoke(&adev->psp, op); + + if (ret == TA_RAP_STATUS__SUCCESS) { + dev_info(adev->dev, "RAP L0 validate test success.\n"); + } else { + rap_shared_mem = (struct ta_rap_shared_memory *) + adev->psp.rap_context.rap_shared_buf; + rap_cmd_output = &(rap_shared_mem->rap_out_message.output); + + dev_info(adev->dev, "RAP test failed, the output is:\n"); + dev_info(adev->dev, "\tlast_subsection: 0x%08x.\n", + rap_cmd_output->last_subsection); + dev_info(adev->dev, "\tnum_total_validate: 0x%08x.\n", + rap_cmd_output->num_total_validate); + dev_info(adev->dev, "\tnum_valid: 0x%08x.\n", + rap_cmd_output->num_valid); + dev_info(adev->dev, "\tlast_validate_addr: 0x%08x.\n", + rap_cmd_output->last_validate_addr); + dev_info(adev->dev, "\tlast_validate_val: 0x%08x.\n", + rap_cmd_output->last_validate_val); + dev_info(adev->dev, "\tlast_validate_val_exptd: 0x%08x.\n", + rap_cmd_output->last_validate_val_exptd); + } + break; + default: + dev_info(adev->dev, "Unsupported op id: %d, ", op); + dev_info(adev->dev, "Only support op 2(L0 validate test).\n"); + } + + amdgpu_gfx_off_ctrl(adev, true); + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + + return size; +} + +static const struct file_operations amdgpu_rap_debugfs_ops = { + .owner = THIS_MODULE, + .read = NULL, + .write = amdgpu_rap_debugfs_write, + .llseek = default_llseek +}; + +void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + struct drm_minor *minor = adev->ddev->primary; + + if (!adev->psp.rap_context.rap_initialized) + return; + + debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root, + adev, &amdgpu_rap_debugfs_ops); +#endif +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h new file mode 100644 index 0000000000000..ec6d7632d3a0f --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + */ +#ifndef _AMDGPU_RAP_H +#define _AMDGPU_RAP_H + +#include "amdgpu.h" + +void amdgpu_rap_debugfs_init(struct amdgpu_device *adev); +#endif -- GitLab From 72e14ebf9fc09e33b28b70f00a2ed9821c198633 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Thu, 6 Aug 2020 14:48:15 +0800 Subject: [PATCH 0416/1494] drm/amdgpu: annotate a false positive recursive locking [ 584.110304] ============================================ [ 584.110590] WARNING: possible recursive locking detected [ 584.110876] 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 Tainted: G OE [ 584.111164] -------------------------------------------- [ 584.111456] kworker/38:1/553 is trying to acquire lock: [ 584.111721] ffff9b15ff0a47a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.112112] but task is already holding lock: [ 584.112673] ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.113068] other info that might help us debug this: [ 584.113689] Possible unsafe locking scenario: [ 584.114350] CPU0 [ 584.114685] ---- [ 584.115014] lock(&adev->reset_sem); [ 584.115349] lock(&adev->reset_sem); [ 584.115678] *** DEADLOCK *** [ 584.116624] May be due to missing lock nesting notation [ 584.117284] 4 locks held by kworker/38:1/553: [ 584.117616] #0: ffff9ad635c1d348 ((wq_completion)events){+.+.}, at: process_one_work+0x21f/0x630 [ 584.117967] #1: ffffac708e1c3e58 ((work_completion)(&con->recovery_work)){+.+.}, at: process_one_work+0x21f/0x630 [ 584.118358] #2: ffffffffc1c2a5d0 (&tmp->hive_lock){+.+.}, at: amdgpu_device_gpu_recover+0xae/0x1030 [amdgpu] [ 584.118786] #3: ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.119222] stack backtrace: [ 584.119990] CPU: 38 PID: 553 Comm: kworker/38:1 Kdump: loaded Tainted: G OE 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 [ 584.120782] Hardware name: Supermicro SYS-7049GP-TRT/X11DPG-QT, BIOS 3.1 05/23/2019 [ 584.121223] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 584.121638] Call Trace: [ 584.122050] dump_stack+0x98/0xd5 [ 584.122499] __lock_acquire+0x1139/0x16e0 [ 584.122931] ? trace_hardirqs_on+0x3b/0xf0 [ 584.123358] ? cancel_delayed_work+0xa6/0xc0 [ 584.123771] lock_acquire+0xb8/0x1c0 [ 584.124197] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.124599] down_write+0x49/0x120 [ 584.125032] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125472] amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125910] ? amdgpu_ras_error_query+0x1b8/0x2a0 [amdgpu] [ 584.126367] amdgpu_ras_do_recovery+0x159/0x190 [amdgpu] [ 584.126789] process_one_work+0x29e/0x630 [ 584.127208] worker_thread+0x3c/0x3f0 [ 584.127621] ? __kthread_parkme+0x61/0x90 [ 584.128014] kthread+0x12f/0x150 [ 584.128402] ? process_one_work+0x630/0x630 [ 584.128790] ? kthread_park+0x90/0x90 [ 584.129174] ret_from_fork+0x3a/0x50 Each adev has owned lock_class_key to avoid false positive recursive locking. v2: 1. register adev->lock_key into lockdep, otherwise lockdep will report the below warning [ 1216.705820] BUG: key ffff890183b647d0 has not been registered! [ 1216.705924] ------------[ cut here ]------------ [ 1216.705972] DEBUG_LOCKS_WARN_ON(1) [ 1216.705997] WARNING: CPU: 20 PID: 541 at kernel/locking/lockdep.c:3743 lockdep_init_map+0x150/0x210 v3: change to use down_write_nest_lock to annotate the false dead-lock warning. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 16e23f0533614..fe8878761c295 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4178,12 +4178,16 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) { if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - down_write(&adev->reset_sem); + if (hive) { + down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); + } else { + down_write(&adev->reset_sem); + } atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4345,7 +4349,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev)) { + if (!amdgpu_device_lock_adev(tmp_adev, hive)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; -- GitLab From 2f53072434525eccdd4a4cab3837096c1a3df357 Mon Sep 17 00:00:00 2001 From: Nirmoy Das <nirmoy.das@amd.com> Date: Tue, 11 Aug 2020 16:10:19 +0200 Subject: [PATCH 0417/1494] drm/amdgpu: pass NULL pointer instead of 0 Fixes: c030f2e4166c3f55 ("drm/amdgpu: add amdgpu_ras.c to support ras (v2)") Signed-off-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 2d1fad1abf7a9..cd1403f83dcf8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1570,7 +1570,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) } if (amdgpu_device_should_recover_gpu(ras->adev)) - amdgpu_device_gpu_recover(ras->adev, 0); + amdgpu_device_gpu_recover(ras->adev, NULL); atomic_set(&ras->in_recovery, 0); } -- GitLab From 9fb1506eb671aa1640a8bd60f0121b94041a1f6a Mon Sep 17 00:00:00 2001 From: Oak Zeng <Oak.Zeng@amd.com> Date: Thu, 6 Aug 2020 22:17:35 -0500 Subject: [PATCH 0418/1494] drm/amdgpu: Use function pointer for some mmhub functions Add more function pointers to amdgpu_mmhub_funcs. ASIC specific implementation of most mmhub functions are called from a general function pointer, instead of calling different function for different ASIC. Simplify the code by deleting duplicate functions Signed-off-by: Oak Zeng <Oak.Zeng@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 21 ++------ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 4 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h | 13 +++++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 19 +++++--- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 48 +++++-------------- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 27 +++++++---- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h | 14 ------ drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 25 +++++++--- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h | 11 +---- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 24 ++++++---- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h | 12 ----- 12 files changed, 100 insertions(+), 121 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index 35d4a5ab02280..a2cb317373783 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -283,22 +283,6 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, return 0; } -static void kgd_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, - uint64_t page_table_base) -{ - struct amdgpu_device *adev = get_amdgpu_device(kgd); - - if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) { - pr_err("trying to set page table base for wrong VMID %u\n", - vmid); - return; - } - - mmhub_v9_4_setup_vm_pt_regs(adev, vmid, page_table_base); - - gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); -} - const struct kfd2kgd_calls arcturus_kfd2kgd = { .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, @@ -317,7 +301,8 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { .wave_control_execute = kgd_gfx_v9_wave_control_execute, .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = - kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, - .set_vm_context_page_table_base = kgd_set_vm_context_page_table_base, + kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, + .set_vm_context_page_table_base = + kgd_gfx_v9_set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 73728181b88f4..d5d997fe6aa44 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -677,7 +677,7 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd, return 0; } -static void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, +void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_device *adev = get_amdgpu_device(kgd); @@ -688,7 +688,7 @@ static void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, return; } - mmhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); + adev->mmhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h index aedf67d57449c..f098e88d3a0d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h @@ -60,3 +60,6 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd, bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd, uint8_t vmid, uint16_t *p_pasid); + +void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, + uint32_t vmid, uint64_t page_table_base); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index e89fb35fec713..0c43d7fe893cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -27,6 +27,19 @@ struct amdgpu_mmhub_funcs { void (*query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count)(struct amdgpu_device *adev); + u64 (*get_fb_location)(struct amdgpu_device *adev); + void (*init)(struct amdgpu_device *adev); + int (*gart_enable)(struct amdgpu_device *adev); + void (*set_fault_enable_default)(struct amdgpu_device *adev, + bool value); + void (*gart_disable)(struct amdgpu_device *adev); + int (*set_clockgating)(struct amdgpu_device *adev, + enum amd_clockgating_state state); + void (*get_clockgating)(struct amdgpu_device *adev, u32 *flags); + void (*setup_vm_pt_regs)(struct amdgpu_device *adev, uint32_t vmid, + uint64_t page_table_base); + void (*update_power_gating)(struct amdgpu_device *adev, + bool enable); }; struct amdgpu_mmhub { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index f0f50e785dcd1..9d3b1245a339c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -627,10 +627,17 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) } } + +static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev) +{ + adev->mmhub.funcs = &mmhub_v2_0_funcs; +} + static int gmc_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + gmc_v10_0_set_mmhub_funcs(adev); gmc_v10_0_set_gmc_funcs(adev); gmc_v10_0_set_irq_funcs(adev); gmc_v10_0_set_umc_funcs(adev); @@ -775,7 +782,7 @@ static int gmc_v10_0_sw_init(void *handle) else gfxhub_v2_0_init(adev); - mmhub_v2_0_init(adev); + adev->mmhub.funcs->init(adev); spin_lock_init(&adev->gmc.invalidate_lock); @@ -944,7 +951,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - r = mmhub_v2_0_gart_enable(adev); + r = adev->mmhub.funcs->gart_enable(adev); if (r) return r; @@ -966,7 +973,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) gfxhub_v2_1_set_fault_enable_default(adev, value); else gfxhub_v2_0_set_fault_enable_default(adev, value); - mmhub_v2_0_set_fault_enable_default(adev, value); + adev->mmhub.funcs->set_fault_enable_default(adev, value); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB_0, 0); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB_0, 0); @@ -1011,7 +1018,7 @@ static void gmc_v10_0_gart_disable(struct amdgpu_device *adev) gfxhub_v2_1_gart_disable(adev); else gfxhub_v2_0_gart_disable(adev); - mmhub_v2_0_gart_disable(adev); + adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } @@ -1078,7 +1085,7 @@ static int gmc_v10_0_set_clockgating_state(void *handle, int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = mmhub_v2_0_set_clockgating(adev, state); + r = adev->mmhub.funcs->set_clockgating(adev, state); if (r) return r; @@ -1093,7 +1100,7 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - mmhub_v2_0_get_clockgating(adev, flags); + adev->mmhub.funcs->get_clockgating(adev, flags); if (adev->asic_type == CHIP_SIENNA_CICHLID || adev->asic_type == CHIP_NAVY_FLOUNDER) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 65488ddc34c3d..773ee11b3d173 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -908,13 +908,11 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev) { switch (adev->asic_type) { - case CHIP_VEGA20: - adev->mmhub.funcs = &mmhub_v1_0_funcs; - break; case CHIP_ARCTURUS: adev->mmhub.funcs = &mmhub_v9_4_funcs; break; default: + adev->mmhub.funcs = &mmhub_v1_0_funcs; break; } } @@ -980,10 +978,8 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev, { u64 base = 0; - if (adev->asic_type == CHIP_ARCTURUS) - base = mmhub_v9_4_get_fb_location(adev); - else if (!amdgpu_sriov_vf(adev)) - base = mmhub_v1_0_get_fb_location(adev); + if (!amdgpu_sriov_vf(adev)) + base = adev->mmhub.funcs->get_fb_location(adev); /* add the xgmi offset of the physical node */ base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; @@ -1083,10 +1079,8 @@ static int gmc_v9_0_sw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; gfxhub_v1_0_init(adev); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_init(adev); - else - mmhub_v1_0_init(adev); + + adev->mmhub.funcs->init(adev); spin_lock_init(&adev->gmc.invalidate_lock); @@ -1313,10 +1307,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - if (adev->asic_type == CHIP_ARCTURUS) - r = mmhub_v9_4_gart_enable(adev); - else - r = mmhub_v1_0_gart_enable(adev); + r = adev->mmhub.funcs->gart_enable(adev); if (r) return r; @@ -1351,11 +1342,10 @@ static int gmc_v9_0_hw_init(void *handle) golden_settings_vega10_hdp, ARRAY_SIZE(golden_settings_vega10_hdp)); + if (adev->mmhub.funcs->update_power_gating) + adev->mmhub.funcs->update_power_gating(adev, true); + switch (adev->asic_type) { - case CHIP_RAVEN: - /* TODO for renoir */ - mmhub_v1_0_update_power_gating(adev, true); - break; case CHIP_ARCTURUS: WREG32_FIELD15(HDP, 0, HDP_MMHUB_CNTL, HDP_MMHUB_GCC, 1); break; @@ -1381,10 +1371,7 @@ static int gmc_v9_0_hw_init(void *handle) if (!amdgpu_sriov_vf(adev)) { gfxhub_v1_0_set_fault_enable_default(adev, value); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_set_fault_enable_default(adev, value); - else - mmhub_v1_0_set_fault_enable_default(adev, value); + adev->mmhub.funcs->set_fault_enable_default(adev, value); } for (i = 0; i < adev->num_vmhubs; ++i) gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0); @@ -1421,10 +1408,7 @@ static void gmc_v9_0_save_registers(struct amdgpu_device *adev) static void gmc_v9_0_gart_disable(struct amdgpu_device *adev) { gfxhub_v1_0_gart_disable(adev); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_gart_disable(adev); - else - mmhub_v1_0_gart_disable(adev); + adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } @@ -1497,10 +1481,7 @@ static int gmc_v9_0_set_clockgating_state(void *handle, { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_set_clockgating(adev, state); - else - mmhub_v1_0_set_clockgating(adev, state); + adev->mmhub.funcs->set_clockgating(adev, state); athub_v1_0_set_clockgating(adev, state); @@ -1511,10 +1492,7 @@ static void gmc_v9_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_get_clockgating(adev, flags); - else - mmhub_v1_0_get_clockgating(adev, flags); + adev->mmhub.funcs->get_clockgating(adev, flags); athub_v1_0_get_clockgating(adev, flags); } diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index dffcb93ecee52..e24d6e533be33 100755 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -34,7 +34,7 @@ #define mmDAGB0_CNTL_MISC2_RV 0x008f #define mmDAGB0_CNTL_MISC2_RV_BASE_IDX 0 -u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) +static u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(MMHUB, 0, mmMC_VM_FB_LOCATION_BASE); u64 top = RREG32_SOC15(MMHUB, 0, mmMC_VM_FB_LOCATION_TOP); @@ -51,7 +51,7 @@ u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) return base; } -void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -297,7 +297,7 @@ static void mmhub_v1_0_program_invalidation(struct amdgpu_device *adev) } } -void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, +static void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, bool enable) { if (amdgpu_sriov_vf(adev)) @@ -310,7 +310,7 @@ void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, } } -int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) +static int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) { if (amdgpu_sriov_vf(adev)) { /* @@ -338,7 +338,7 @@ int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) +static void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -373,7 +373,7 @@ void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -415,7 +415,7 @@ void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) WREG32_SOC15(MMHUB, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp); } -void mmhub_v1_0_init(struct amdgpu_device *adev) +static void mmhub_v1_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -525,7 +525,7 @@ static void mmhub_v1_0_update_medium_grain_light_sleep(struct amdgpu_device *ade WREG32_SOC15(MMHUB, 0, mmATC_L2_MISC_CG, data); } -int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -549,7 +549,7 @@ int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -781,4 +781,13 @@ const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = { .ras_late_init = amdgpu_mmhub_ras_late_init, .query_ras_error_count = mmhub_v1_0_query_ras_error_count, .reset_ras_error_count = mmhub_v1_0_reset_ras_error_count, + .get_fb_location = mmhub_v1_0_get_fb_location, + .init = mmhub_v1_0_init, + .gart_enable = mmhub_v1_0_gart_enable, + .set_fault_enable_default = mmhub_v1_0_set_fault_enable_default, + .gart_disable = mmhub_v1_0_gart_disable, + .set_clockgating = mmhub_v1_0_set_clockgating, + .get_clockgating = mmhub_v1_0_get_clockgating, + .setup_vm_pt_regs = mmhub_v1_0_setup_vm_pt_regs, + .update_power_gating = mmhub_v1_0_update_power_gating, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h index c43319e8f945f..d77f5b65a6186 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h @@ -25,18 +25,4 @@ extern const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs; -u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev); -int mmhub_v1_0_gart_enable(struct amdgpu_device *adev); -void mmhub_v1_0_gart_disable(struct amdgpu_device *adev); -void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v1_0_init(struct amdgpu_device *adev); -int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, - bool enable); -void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); - #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 8acb3b625afe7..5baf899417d8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -83,7 +83,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, MMVM_L2_PROTECTION_FAULT_STATUS, RW)); } -void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -327,7 +327,7 @@ static void mmhub_v2_0_program_invalidation(struct amdgpu_device *adev) } } -int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) +static int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) { /* GART Enable. */ mmhub_v2_0_init_gart_aperture_regs(adev); @@ -343,7 +343,7 @@ int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) +static void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -374,7 +374,7 @@ void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -422,7 +422,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = { .get_invalidate_req = mmhub_v2_0_get_invalidate_req, }; -void mmhub_v2_0_init(struct amdgpu_device *adev) +static void mmhub_v2_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -552,7 +552,7 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade } } -int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -576,7 +576,7 @@ int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -609,3 +609,14 @@ void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK) *flags |= AMD_CG_SUPPORT_MC_LS; } + +const struct amdgpu_mmhub_funcs mmhub_v2_0_funcs = { + .ras_late_init = amdgpu_mmhub_ras_late_init, + .init = mmhub_v2_0_init, + .gart_enable = mmhub_v2_0_gart_enable, + .set_fault_enable_default = mmhub_v2_0_set_fault_enable_default, + .gart_disable = mmhub_v2_0_gart_disable, + .set_clockgating = mmhub_v2_0_set_clockgating, + .get_clockgating = mmhub_v2_0_get_clockgating, + .setup_vm_pt_regs = mmhub_v2_0_setup_vm_pt_regs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h index 3ea4344f0315c..f80f461d67dac 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h @@ -23,15 +23,6 @@ #ifndef __MMHUB_V2_0_H__ #define __MMHUB_V2_0_H__ -int mmhub_v2_0_gart_enable(struct amdgpu_device *adev); -void mmhub_v2_0_gart_disable(struct amdgpu_device *adev); -void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v2_0_init(struct amdgpu_device *adev); -int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); +extern const struct amdgpu_mmhub_funcs mmhub_v2_0_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index 9979f54fef57f..6c6ad529c65c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -36,7 +36,7 @@ #define MMHUB_NUM_INSTANCES 2 #define MMHUB_INSTANCE_REGISTER_OFFSET 0x3000 -u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev) +static u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev) { /* The base should be same b/t 2 mmhubs on Acrturus. Read one here. */ u64 base = RREG32_SOC15(MMHUB, 0, mmVMSHAREDVC0_MC_VM_FB_LOCATION_BASE); @@ -97,7 +97,7 @@ static void mmhub_v9_4_init_gart_aperture_regs(struct amdgpu_device *adev, (u32)(adev->gmc.gart_end >> 44)); } -void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { int i; @@ -375,7 +375,7 @@ static void mmhub_v9_4_program_invalidation(struct amdgpu_device *adev, } } -int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) +static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) { int i; @@ -397,7 +397,7 @@ int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) +static void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -442,7 +442,7 @@ void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; int i; @@ -500,7 +500,7 @@ void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) } } -void mmhub_v9_4_init(struct amdgpu_device *adev) +static void mmhub_v9_4_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub[MMHUB_NUM_INSTANCES] = {&adev->vmhub[AMDGPU_MMHUB_0], &adev->vmhub[AMDGPU_MMHUB_1]}; @@ -630,7 +630,7 @@ static void mmhub_v9_4_update_medium_grain_light_sleep(struct amdgpu_device *ade } } -int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -650,7 +650,7 @@ int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -1628,4 +1628,12 @@ const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = { .ras_late_init = amdgpu_mmhub_ras_late_init, .query_ras_error_count = mmhub_v9_4_query_ras_error_count, .reset_ras_error_count = mmhub_v9_4_reset_ras_error_count, + .get_fb_location = mmhub_v9_4_get_fb_location, + .init = mmhub_v9_4_init, + .gart_enable = mmhub_v9_4_gart_enable, + .set_fault_enable_default = mmhub_v9_4_set_fault_enable_default, + .gart_disable = mmhub_v9_4_gart_disable, + .set_clockgating = mmhub_v9_4_set_clockgating, + .get_clockgating = mmhub_v9_4_get_clockgating, + .setup_vm_pt_regs = mmhub_v9_4_setup_vm_pt_regs, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h index 1b979773776c0..92404a8f66f3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h @@ -25,16 +25,4 @@ extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs; -u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev); -int mmhub_v9_4_gart_enable(struct amdgpu_device *adev); -void mmhub_v9_4_gart_disable(struct amdgpu_device *adev); -void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v9_4_init(struct amdgpu_device *adev); -int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); - #endif -- GitLab From a9c75edcbe7cca5c2edb87fa765efac7558523c0 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 6 Aug 2020 15:38:25 +0800 Subject: [PATCH 0419/1494] drm/amd/powerplay: update the metrics table cache interval as 1ms To make the setting same as Arcturus/Navi1x/Sienna_Cichlid. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 2 +- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index c70c301758015..f0680dd585089 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -1272,7 +1272,7 @@ static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, if (bypass_cache || !data->metrics_time || - time_after(jiffies, data->metrics_time + HZ / 2)) { + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&data->metrics_table), TABLE_SMU_METRICS, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index c9f402edc0d64..da84012b7fd51 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -2082,7 +2082,7 @@ static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, if (bypass_cache || !data->metrics_time || - time_after(jiffies, data->metrics_time + HZ / 2)) { + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&data->metrics_table), TABLE_SMU_METRICS, diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 8a8e6033f71f9..c50c4547fea9d 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -139,7 +139,7 @@ static int renoir_get_metrics_table(struct smu_context *smu, if (bypass_cache || !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)smu_table->metrics_table, false); if (ret) { -- GitLab From fceafc9b7b393698ac9aadb5c3b64b1ba1f61e1e Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 6 Aug 2020 16:49:19 +0800 Subject: [PATCH 0420/1494] drm/amd/powerplay: maximum the code sharing around metrics table retrieving Instead of having one copy in each ASIC. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 55 ++----------------- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 41 +++----------- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 40 ++------------ .../drm/amd/powerplay/sienna_cichlid_ppt.c | 55 ++----------------- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 45 +++++++++++++++ drivers/gpu/drm/amd/powerplay/smu_cmn.h | 8 +++ 6 files changed, 77 insertions(+), 167 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index e59e6fb6f0a80..8b1025dc54fd2 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -541,49 +541,6 @@ static int arcturus_freqs_in_same_level(int32_t frequency1, return (abs(frequency1 - frequency2) <= EPSILON); } -static int arcturus_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - -static int arcturus_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = arcturus_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int arcturus_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -594,9 +551,9 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = arcturus_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2305,9 +2262,9 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = arcturus_get_metrics_table(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 82659b781f05c..42a60769c52f4 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -504,34 +504,6 @@ static int navi10_tables_init(struct smu_context *smu) return -ENOMEM; } -static int navi10_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - static int navi10_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -547,9 +519,9 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = navi10_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2526,14 +2498,15 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = navi10_get_metrics_table_locked(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + true); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; } + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); if (adev->asic_type == CHIP_NAVI12) memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index c50c4547fea9d..186929c31e9e9 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -128,36 +128,6 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), }; -static int renoir_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, - (void *)smu_table->metrics_table, false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int renoir_init_smc_tables(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; @@ -381,7 +351,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, memset(&metrics, 0, sizeof(metrics)); - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -527,7 +497,7 @@ static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, int ret = 0, clk_id = 0; SmuMetrics_t metrics; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -610,7 +580,7 @@ static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -630,7 +600,7 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -1016,7 +986,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = renoir_get_metrics_table(smu, &metrics, true); + ret = smu_cmn_get_metrics_table(smu, &metrics, true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index bb756b4c284ed..c5935f0a065b5 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -407,49 +407,6 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) return -ENOMEM; } -static int sienna_cichlid_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - -static int sienna_cichlid_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = sienna_cichlid_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -460,9 +417,9 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = sienna_cichlid_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2698,9 +2655,9 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = sienna_cichlid_get_metrics_table(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index 5c23c44c33bdd..968b734baac05 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -631,3 +631,48 @@ int smu_cmn_write_pptable(struct smu_context *smu) pptable, true); } + +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + struct smu_table_context *smu_table= &smu->smu_table; + uint32_t table_size = + smu_table->tables[SMU_TABLE_SMU_METRICS].size; + int ret = 0; + + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + return ret; + } + smu_table->metrics_time = jiffies; + } + + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, table_size); + + return 0; +} + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/powerplay/smu_cmn.h index 98face8c5fd61..6d00ad740c278 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.h +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.h @@ -79,5 +79,13 @@ int smu_cmn_write_watermarks_table(struct smu_context *smu); int smu_cmn_write_pptable(struct smu_context *smu); +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + #endif #endif -- GitLab From c048e4cd607ae637eac5e7c81e8aa5b9f0d43a6a Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 10 Aug 2020 13:27:56 +0800 Subject: [PATCH 0421/1494] drm/amd/powerplay: bump NAVI12 driver if version To fit the latest SMU firmware. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index ee1506beb0ea1..65363d56e3ccd 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -28,7 +28,7 @@ #define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU11_DRIVER_IF_VERSION_ARCT 0x17 #define SMU11_DRIVER_IF_VERSION_NV10 0x36 -#define SMU11_DRIVER_IF_VERSION_NV12 0x33 +#define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 -- GitLab From ba4e049e63b607ac2e0c070b1406826390d5047e Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 12 Aug 2020 15:57:32 +0800 Subject: [PATCH 0422/1494] drm/amdgpu: disable gfxoff for navy_flounder gfxoff is temporarily disabled for navy_flounder, since at present the feature has broken some basic amdgpu test. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index d851fe80eaf4f..de6e6de418679 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3610,6 +3610,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; + case CHIP_NAVY_FLOUNDER: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + break; default: break; } -- GitLab From e1a84641d478f7f35a8189f447da107c473ef0d0 Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevin1.wang@amd.com> Date: Thu, 6 Aug 2020 23:41:47 +0800 Subject: [PATCH 0423/1494] drm/amdgpu: fix uninit-value in arcturus_log_thermal_throttling_event() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when function arcturus_get_smu_metrics_data() call failed, it will cause the variable "throttler_status" isn't initialized before use. warning: powerplay/arcturus_ppt.c:2268:24: warning: ‘throttler_status’ may be used uninitialized in this function [-Wmaybe-uninitialized] 2268 | if (throttler_status & logging_label[throttler_idx].feature_mask) { Signed-off-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 8b1025dc54fd2..81f43fea4d528 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2208,14 +2208,17 @@ static const struct throttling_logging_label { }; static void arcturus_log_thermal_throttling_event(struct smu_context *smu) { + int ret; int throttler_idx, throtting_events = 0, buf_idx = 0; struct amdgpu_device *adev = smu->adev; uint32_t throttler_status; char log_buf[256]; - arcturus_get_smu_metrics_data(smu, - METRICS_THROTTLER_STATUS, - &throttler_status); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_THROTTLER_STATUS, + &throttler_status); + if (ret) + return; memset(log_buf, 0, sizeof(log_buf)); for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label); -- GitLab From f10bb940d8d2774fedc63c4dfb975e4310a261cd Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 11:53:47 +0800 Subject: [PATCH 0424/1494] drm/amd/powerplay: optimize the interface for mgpu fan boost enablement Cover the implementation details from outside(of power). Also preparing for expanding this to swSMU. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 6 ++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index fe8878761c295..bb7f0c8611f97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2228,9 +2228,7 @@ static int amdgpu_device_enable_mgpu_fan_boost(void) gpu_ins = &(mgpu_info.gpu_ins[i]); adev = gpu_ins->adev; if (!(adev->flags & AMD_IS_APU) && - !gpu_ins->mgpu_fan_enabled && - adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->enable_mgpu_fan_boost) { + !gpu_ins->mgpu_fan_enabled) { ret = amdgpu_dpm_enable_mgpu_fan_boost(adev); if (ret) break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 2082c0acd216d..27417f873a367 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1216,3 +1216,16 @@ int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) return 0; } + +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = 0; + + if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index b190c0af7db12..cc16b5a3ac449 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -357,10 +357,6 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ (adev)->powerplay.pp_handle, type, parameter, size)) -#define amdgpu_dpm_enable_mgpu_fan_boost(adev) \ - ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\ - (adev)->powerplay.pp_handle)) - #define amdgpu_dpm_get_ppfeature_status(adev, buf) \ ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ (adev)->powerplay.pp_handle, (buf))) @@ -548,4 +544,6 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); + #endif -- GitLab From 9f979a49e23f4b87d038708e06ea6d320e198e71 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 12:08:56 +0800 Subject: [PATCH 0425/1494] drm/amd/powerplay: enable swSMU mgpu fan boost support Enable mgpu fan boost feature on swSMU routines. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 5 ++++- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 27417f873a367..240c440cbe008 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1222,9 +1222,12 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) void *pp_handle = adev->powerplay.pp_handle; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + struct smu_context *smu = &adev->smu; int ret = 0; - if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + if (is_support_sw_smu(adev)) + ret = smu_enable_mgpu_fan_boost(smu); + else if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); return ret; diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 1ffacc712e53e..f87a73cb7ec59 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -2652,3 +2652,20 @@ ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, return size; } + +int smu_enable_mgpu_fan_boost(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->enable_mgpu_fan_boost) + ret = smu->ppt_funcs->enable_mgpu_fan_boost(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 23c2279bd5006..bbe4a343e9f1e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -595,6 +595,7 @@ struct pptable_funcs { size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); + int (*enable_mgpu_fan_boost)(struct smu_context *smu); }; typedef enum { @@ -799,5 +800,7 @@ int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); +int smu_enable_mgpu_fan_boost(struct smu_context *smu); + #endif #endif -- GitLab From 94a670d5ac45b9449581d7133287cc297774f944 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 12:29:16 +0800 Subject: [PATCH 0426/1494] drm/amd/powerplay: enable Navi1X mgpu fan boost feature(V2) Support Navi1X mgpu fan boost enablement. V2: rich the comment and correct the revision id check Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/powerplay/inc/smu_v11_0_ppsmc.h | 4 +++- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h index 406bfd187ce86..fa0174dc7e0ea 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h @@ -123,7 +123,9 @@ #define PPSMC_MSG_DALDisableDummyPstateChange 0x49 #define PPSMC_MSG_DALEnableDummyPstateChange 0x4A -#define PPSMC_Message_Count 0x4B +#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x4C + +#define PPSMC_Message_Count 0x4D typedef uint32_t PPSMC_Result; typedef uint32_t PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 42a60769c52f4..4b4d461899df4 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -138,6 +138,7 @@ static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0), MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), }; static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { @@ -2557,6 +2558,26 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_0); } +static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t param = 0; + + /* Navi12 does not support this */ + if (adev->asic_type == CHIP_NAVI12) + return 0; + + /* Workaround for WS SKU */ + if (adev->pdev->device == 0x7312 && + adev->pdev->revision == 0) + param = 0xD188; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + param, + NULL); +} + static const struct pptable_funcs navi10_ppt_funcs = { .get_allowed_feature_mask = navi10_get_allowed_feature_mask, .set_default_dpm_table = navi10_set_default_dpm_table, @@ -2638,6 +2659,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = navi10_get_gpu_metrics, + .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, }; void navi10_set_ppt_funcs(struct smu_context *smu) -- GitLab From 05f39286ce11b98376e0d179aff0d537c257e772 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 12:37:03 +0800 Subject: [PATCH 0427/1494] drm/amd/powerplay: enable Sienna Cichlid mgpu fan boost feature Support Sienna Cichlid mgpu fan boost enablement. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index c5935f0a065b5..407a11c2826b2 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -124,6 +124,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0), MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), }; static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { @@ -2709,6 +2710,14 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_0); } +static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + 0, + NULL); +} + static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, @@ -2786,6 +2795,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, + .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- GitLab From f1403342ebdfcff3c3cf57ae476f19d3078f2767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 12 Aug 2020 17:48:26 +0200 Subject: [PATCH 0428/1494] drm/amdgpu: revert "fix system hang issue during GPU reset" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The whole approach wasn't thought through till the end. We already had a reset lock like this in the past and it caused the same problems like this one. Completely revert the patch for now and add individual trylock protection to the hardware access functions as necessary. This reverts commit df9c8d1aa278c435c30a69b8f2418b4a52fcb929. Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 40 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 7 - drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 57 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 353 ++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 3 +- drivers/gpu/drm/amd/amdgpu/atom.c | 1 - drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 13 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 13 +- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 16 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 4 - .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 2 +- 39 files changed, 184 insertions(+), 469 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3e82a11577d90..08f80ca3b296c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,9 +949,9 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate; - atomic_t in_gpu_reset; + bool in_gpu_reset; enum pp_mp1_state mp1_state; - struct rw_semaphore reset_sem; + struct mutex lock_reset; struct amdgpu_doorbell_index doorbell_index; struct mutex notifier_lock; @@ -1266,9 +1266,4 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) return adev->gmc.tmz_enabled; } -static inline bool amdgpu_in_reset(struct amdgpu_device *adev) -{ - return atomic_read(&adev->in_gpu_reset) ? true : false; -} - #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 9738dccb1c2c8..0effc1d468241 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -244,14 +244,11 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, if (cp_mqd_gfx9) bp.flags |= AMDGPU_GEM_CREATE_CP_MQD_GFX9; - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - r = amdgpu_bo_create(adev, &bp, &bo); if (r) { dev_err(adev->dev, "failed to allocate BO for amdkfd (%d)\n", r); - goto err; + return r; } /* map the buffer */ @@ -286,7 +283,6 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, amdgpu_bo_unreserve(bo); - up_read(&adev->reset_sem); return 0; allocate_mem_kmap_bo_failed: @@ -295,25 +291,19 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, amdgpu_bo_unreserve(bo); allocate_mem_reserve_bo_failed: amdgpu_bo_unref(&bo); -err: - up_read(&adev->reset_sem); + return r; } void amdgpu_amdkfd_free_gtt_mem(struct kgd_dev *kgd, void *mem_obj) { - struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj; - down_read(&adev->reset_sem); - amdgpu_bo_reserve(bo, true); amdgpu_bo_kunmap(bo); amdgpu_bo_unpin(bo); amdgpu_bo_unreserve(bo); amdgpu_bo_unref(&(bo)); - - up_read(&adev->reset_sem); } int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, @@ -345,14 +335,9 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj) { - struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj; - down_read(&adev->reset_sem); - amdgpu_bo_unref(&bo); - - up_read(&adev->reset_sem); } uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd, @@ -626,15 +611,8 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, /* This works for NO_HWS. TODO: need to handle without knowing VMID */ job->vmid = vmid; - if (!down_read_trylock(&adev->reset_sem)) { - ret = -EIO; - goto err_ib_sched; - } - ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); - up_read(&adev->reset_sem); - if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; @@ -670,9 +648,6 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - if (adev->family == AMDGPU_FAMILY_AI) { int i; @@ -682,8 +657,6 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB_0, 0); } - up_read(&adev->reset_sem); - return 0; } @@ -692,18 +665,11 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid) struct amdgpu_device *adev = (struct amdgpu_device *)kgd; const uint32_t flush_type = 0; bool all_hub = false; - int ret = -EIO; if (adev->family == AMDGPU_FAMILY_AI) all_hub = true; - if (down_read_trylock(&adev->reset_sem)) { - ret = amdgpu_gmc_flush_gpu_tlb_pasid(adev, - pasid, flush_type, all_hub); - up_read(&adev->reset_sem); - } - - return ret; + return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub); } bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index b0dcc800251ee..bf927f432506d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -542,7 +542,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v10_compute_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; #if 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 275f20399373f..744366c7ee85d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -423,7 +423,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, unsigned long flags, end_jiffies; int retry; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 4997189d8b368..feab4cc6e8367 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -419,7 +419,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, int retry; struct vi_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index d5d997fe6aa44..e4c274bd35c8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -539,7 +539,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v9_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index fcf72f3377852..62cb510e2cc47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1194,9 +1194,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( return -EINVAL; } - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); if (!*mem) { ret = -ENOMEM; @@ -1263,7 +1260,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( if (offset) *offset = amdgpu_bo_mmap_offset(bo); - up_read(&adev->reset_sem); return 0; allocate_init_user_pages_failed: @@ -1281,9 +1277,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( sg_free_table(sg); kfree(sg); } - - up_read(&adev->reset_sem); - return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a3b150304daef..a512ccbc4deae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1292,8 +1292,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) parser.adev = adev; parser.filp = filp; - down_read(&adev->reset_sem); - r = amdgpu_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser %d!\n", r); @@ -1333,8 +1331,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); - up_read(&adev->reset_sem); - return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index d85d13f7a0435..8842c55d4490b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -358,8 +358,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, if (atomic_read(&ctx->guilty)) out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY; - down_read(&adev->reset_sem); - /*query ue count*/ ras_counter = amdgpu_ras_query_error_count(adev, false); /*ras counter is monotonic increasing*/ @@ -375,8 +373,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, ctx->ras_counter_ce = ras_counter; } - up_read(&adev->reset_sem); - mutex_unlock(&mgr->lock); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 0af249a1e35b7..35fed75a43972 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -101,14 +101,14 @@ static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) file->private_data = adev; - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); if (adev->autodump.dumping.done) { reinit_completion(&adev->autodump.dumping); ret = 0; } else { ret = -EBUSY; } - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); return ret; } @@ -127,7 +127,7 @@ static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_ poll_wait(file, &adev->autodump.gpu_hang, poll_table); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return POLLIN | POLLRDNORM | POLLWRNORM; return 0; @@ -1242,7 +1242,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) } /* Avoid accidently unparking the sched thread during GPU reset */ - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -1269,7 +1269,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) kthread_unpark(ring->sched.thread); } - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1459,7 +1459,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) return -ENOMEM; /* Avoid accidently unparking the sched thread during GPU reset */ - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); /* stop the scheduler */ kthread_park(ring->sched.thread); @@ -1500,7 +1500,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) /* restart the scheduler */ kthread_unpark(ring->sched.thread); - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index bb7f0c8611f97..415e1a32b98c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1940,7 +1940,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) if (adev->ip_blocks[i].status.hw == true) break; - if (amdgpu_in_reset(adev) || adev->in_suspend) { + if (adev->in_gpu_reset || adev->in_suspend) { r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { DRM_ERROR("resume of IP block <%s> failed %d\n", @@ -2117,7 +2117,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev) AMDGPU_RESET_MAGIC_NUM)) return true; - if (!amdgpu_in_reset(adev)) + if (!adev->in_gpu_reset) return false; /* @@ -3053,8 +3053,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->mn_lock); mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); - init_rwsem(&adev->reset_sem); - atomic_set(&adev->in_gpu_reset, 0); + mutex_init(&adev->lock_reset); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4082,11 +4081,8 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (need_full_reset) { /* post card */ - if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) { - dev_warn(tmp_adev->dev, "asic atom init failed!"); - r = -EAGAIN; - goto out; - } + if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) + DRM_WARN("asic atom init failed!"); if (!r) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); @@ -4176,18 +4172,16 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock) { - if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) - return false; - - if (hive) { - down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); - } else { - down_write(&adev->reset_sem); - } + if (trylock) { + if (!mutex_trylock(&adev->lock_reset)) + return false; + } else + mutex_lock(&adev->lock_reset); atomic_inc(&adev->gpu_reset_counter); + adev->in_gpu_reset = true; switch (amdgpu_asic_reset_method(adev)) { case AMD_RESET_METHOD_MODE1: adev->mp1_state = PP_MP1_STATE_SHUTDOWN; @@ -4207,8 +4201,8 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) { amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; - atomic_set(&adev->in_gpu_reset, 0); - up_write(&adev->reset_sem); + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); } static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) @@ -4318,14 +4312,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, false); - if (hive) { - if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { - DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", - job ? job->base.id : -1, hive->hive_id); - return 0; - } - mutex_lock(&hive->hive_lock); + hive = amdgpu_get_xgmi_hive(adev, true); + if (hive && !mutex_trylock(&hive->reset_lock)) { + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", + job ? job->base.id : -1, hive->hive_id); + mutex_unlock(&hive->hive_lock); + return 0; } /* @@ -4347,11 +4339,11 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev, hive)) { + if (!amdgpu_device_lock_adev(tmp_adev, !hive)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); - r = 0; - goto skip_recovery; + mutex_unlock(&hive->hive_lock); + return 0; } /* @@ -4484,9 +4476,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, amdgpu_device_unlock_adev(tmp_adev); } -skip_recovery: if (hive) { - atomic_set(&hive->in_reset, 0); + mutex_unlock(&hive->reset_lock); mutex_unlock(&hive->hive_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 73cc68ab53d06..7f9e50247413d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -671,8 +671,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, bo_va = NULL; } - down_read(&adev->reset_sem); - switch (args->operation) { case AMDGPU_VA_OP_MAP: va_flags = amdgpu_gem_va_map_flags(adev, args->flags); @@ -702,8 +700,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va, args->operation); - up_read(&adev->reset_sem); - error_backoff: ttm_eu_backoff_reservation(&ticket, &list); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 8ccd17d02cc60..a819360a4b6ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -719,7 +719,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_read; might_sleep(); @@ -777,7 +777,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_write; might_sleep(); @@ -796,5 +796,5 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_write: - dev_warn(adev->dev, "failed to write reg:%x\n", reg); + pr_err("failed to write reg:%x\n", reg); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 75d37dfb51aa7..937029ad5271a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -220,17 +220,17 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) trace_amdgpu_sched_run_job(job); - if (down_read_trylock(&ring->adev->reset_sem)) { + if (job->vram_lost_counter != atomic_read(&ring->adev->vram_lost_counter)) + dma_fence_set_error(finished, -ECANCELED);/* skip IB as well if VRAM lost */ + + if (finished->error < 0) { + DRM_INFO("Skip scheduling IBs!\n"); + } else { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, - &fence); - up_read(&ring->adev->reset_sem); + &fence); if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); - } else { - dma_fence_set_error(finished, -ECANCELED); - DRM_INFO("Skip scheduling IBs!\n"); } - /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 58580a48b6486..7619f1c3084df 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1087,8 +1087,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (!fpriv) return; - down_read(&adev->reset_sem); - pm_runtime_get_sync(dev->dev); if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL) @@ -1127,8 +1125,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); - - up_read(&adev->reset_sem); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 1705e328c6fcf..65ad174bb976b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -163,7 +163,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, enum amd_pm_state_type pm; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -172,8 +172,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { if (adev->smu.ppt_funcs->get_current_power_state) pm = smu_get_current_power_state(&adev->smu); @@ -185,8 +183,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, pm = adev->pm.dpm.user_state; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -205,7 +201,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strncmp("battery", buf, strlen("battery")) == 0) @@ -223,8 +219,6 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { mutex_lock(&adev->pm.mutex); adev->pm.dpm.user_state = state; @@ -238,9 +232,6 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, amdgpu_pm_compute_clocks(adev); } - - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -316,7 +307,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level = 0xff; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -325,8 +316,6 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -334,8 +323,6 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, else level = adev->pm.dpm.forced_level; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -362,7 +349,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level current_level = 0xff; int ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strncmp("low", buf, strlen("low")) == 0) { @@ -393,8 +380,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) current_level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -403,8 +388,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (current_level == level) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = count; - goto pro_end; + return count; } if (adev->asic_type == CHIP_RAVEN) { @@ -425,8 +409,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pr_err("Currently not in any profile mode!\n"); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } if (is_support_sw_smu(adev)) { @@ -434,8 +417,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } else if (adev->powerplay.pp_funcs->force_performance_level) { mutex_lock(&adev->pm.mutex); @@ -443,16 +425,14 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } ret = amdgpu_dpm_force_performance_level(adev, level); if (ret) { mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } else { adev->pm.dpm.forced_level = level; } @@ -461,9 +441,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); -pro_end: - up_read(&adev->reset_sem); - return ret; + return count; } static ssize_t amdgpu_get_pp_num_states(struct device *dev, @@ -475,7 +453,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len, ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -519,7 +497,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0, ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -560,7 +538,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->pp_force_state_enabled) @@ -580,7 +558,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, unsigned long idx; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strlen(buf) == 1) @@ -606,7 +584,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); /* only set user selected power states */ if (state != POWER_STATE_TYPE_INTERNAL_BOOT && state != POWER_STATE_TYPE_DEFAULT) { @@ -614,8 +591,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, AMD_PP_TASK_ENABLE_USER_STATE, &state); adev->pp_force_state_enabled = true; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); } @@ -643,7 +618,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size, ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -687,7 +662,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -696,21 +671,16 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_table(&adev->smu, (void *)buf, count); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return ret; } } else if (adev->powerplay.pp_funcs->set_pp_table) amdgpu_dpm_set_pp_table(adev, buf, count); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -845,7 +815,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, const char delimiter[3] = {' ', '\n', '\0'}; uint32_t type; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (count > 127) @@ -889,10 +859,6 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return ret; } - ret = count; - - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { ret = smu_od_edit_dpm_table(&adev->smu, type, parameter, parameter_size); @@ -900,8 +866,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } else { if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { @@ -910,8 +875,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } @@ -922,22 +886,18 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, NULL); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = count; - goto pro_end; + return count; } else { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); -pro_end: - up_read(&adev->reset_sem); - return ret; + return count; } static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, @@ -949,7 +909,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1003,7 +963,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtou64(buf, 0, &featuremask); @@ -1018,13 +978,11 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, return ret; } - down_read(&adev->reset_sem); if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_feature_mask(&adev->smu, featuremask); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } } else if (adev->powerplay.pp_funcs->set_ppfeature_status) { @@ -1032,12 +990,9 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1053,7 +1008,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1062,8 +1017,6 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_sys_get_pp_feature_mask(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_ppfeature_status) @@ -1071,8 +1024,6 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1118,7 +1069,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1127,8 +1078,6 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1136,8 +1085,6 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1190,7 +1137,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1203,15 +1150,11 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1230,7 +1173,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1239,8 +1182,6 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_MCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1248,8 +1189,6 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1266,7 +1205,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, uint32_t mask = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1279,15 +1218,11 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_MCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1306,7 +1241,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1315,8 +1250,6 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SOCCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1324,8 +1257,6 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1342,7 +1273,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1355,8 +1286,6 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SOCCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1364,8 +1293,6 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1384,7 +1311,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1393,8 +1320,6 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_FCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1402,8 +1327,6 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1420,7 +1343,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1433,8 +1356,6 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_FCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1442,8 +1363,6 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1462,7 +1381,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1471,8 +1390,6 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_DCEFCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1480,8 +1397,6 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1498,7 +1413,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1511,8 +1426,6 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_DCEFCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1520,8 +1433,6 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1540,7 +1451,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1549,8 +1460,6 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_PCIE, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1558,8 +1467,6 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1576,7 +1483,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1589,8 +1496,6 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_PCIE, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1598,8 +1503,6 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1618,7 +1521,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, uint32_t value = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1627,15 +1530,11 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK); else if (adev->powerplay.pp_funcs->get_sclk_od) value = amdgpu_dpm_get_sclk_od(adev); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1652,7 +1551,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, int ret; long int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1666,8 +1565,6 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value); } else { @@ -1682,8 +1579,6 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1699,7 +1594,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, uint32_t value = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1708,15 +1603,11 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK); else if (adev->powerplay.pp_funcs->get_mclk_od) value = amdgpu_dpm_get_mclk_od(adev); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1733,7 +1624,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, int ret; long int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1747,8 +1638,6 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value); } else { @@ -1763,8 +1652,6 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1800,7 +1687,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1809,8 +1696,6 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_get_power_profile_mode(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_power_profile_mode) @@ -1818,8 +1703,6 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1844,7 +1727,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; tmp[0] = *(buf); @@ -1878,15 +1761,11 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_set_power_profile_mode(&adev->smu, parameter, parameter_size, true); else if (adev->powerplay.pp_funcs->set_power_profile_mode) ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1912,7 +1791,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1921,11 +1800,9 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, return r; } - down_read(&adev->reset_sem); /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1952,7 +1829,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1961,14 +1838,10 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, return r; } - down_read(&adev->reset_sem); - /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1999,7 +1872,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, uint64_t count0 = 0, count1 = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->flags & AMD_IS_APU) @@ -2014,12 +1887,8 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, return ret; } - down_read(&adev->reset_sem); - amdgpu_asic_get_pcie_usage(adev, &count0, &count1); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -2044,7 +1913,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->unique_id) @@ -2142,7 +2011,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, ssize_t size = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -2151,12 +2020,10 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, return ret; } - down_read(&adev->reset_sem); if (is_support_sw_smu(adev)) size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); else if (adev->powerplay.pp_funcs->get_gpu_metrics) size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); - up_read(&adev->reset_sem); if (size <= 0) goto out; @@ -2368,7 +2235,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, int channel = to_sensor_dev_attr(attr)->index; int r, temp = 0, size = sizeof(temp); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (channel >= PP_TEMP_MAX) @@ -2380,8 +2247,6 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, return r; } - down_read(&adev->reset_sem); - switch (channel) { case PP_TEMP_JUNCTION: /* get current junction temperature */ @@ -2403,8 +2268,6 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, break; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2508,7 +2371,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2517,23 +2380,18 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2549,7 +2407,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err, ret; int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2562,23 +2420,18 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, value); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, value); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2608,7 +2461,7 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, u32 value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2617,15 +2470,11 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - up_read(&adev->reset_sem); - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); pm_runtime_mark_last_busy(adev->ddev->dev); @@ -2666,7 +2515,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, int err; u32 speed = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2675,8 +2524,6 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_percent(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_percent) @@ -2684,8 +2531,6 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2705,7 +2550,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, int err; u32 speed = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2714,8 +2559,6 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2723,8 +2566,6 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2743,7 +2584,7 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, u32 size = sizeof(min_rpm); int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2752,13 +2593,9 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, return r; } - down_read(&adev->reset_sem); - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, (void *)&min_rpm, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2777,7 +2614,7 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, u32 size = sizeof(max_rpm); int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2786,13 +2623,9 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, return r; } - down_read(&adev->reset_sem); - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, (void *)&max_rpm, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2810,7 +2643,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, int err; u32 rpm = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2819,8 +2652,6 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &rpm); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2828,8 +2659,6 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2848,7 +2677,7 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, u32 value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2857,15 +2686,11 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - up_read(&adev->reset_sem); - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2879,8 +2704,6 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_set_fan_speed_rpm(&adev->smu, value); else if (adev->powerplay.pp_funcs->set_fan_speed_rpm) @@ -2888,8 +2711,6 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2907,7 +2728,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2916,23 +2737,18 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2949,7 +2765,7 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, int value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2969,22 +2785,17 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, pwm_mode); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2999,7 +2810,7 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, u32 vddgfx; int r, size = sizeof(vddgfx); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3008,11 +2819,9 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&vddgfx, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3038,7 +2847,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, u32 vddnb; int r, size = sizeof(vddnb); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; /* only APUs have vddnb */ @@ -3051,11 +2860,9 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&vddnb, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3082,7 +2889,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, int r, size = sizeof(u32); unsigned uw; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3091,11 +2898,9 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3125,7 +2930,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ssize_t size; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3134,8 +2939,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, return r; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, true); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -3146,8 +2949,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3163,7 +2964,7 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ssize_t size; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3172,8 +2973,6 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, return r; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, false); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -3184,8 +2983,6 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3202,7 +2999,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, int err; u32 value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (amdgpu_sriov_vf(adev)) @@ -3221,8 +3018,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_set_power_limit(&adev->smu, value); else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_power_limit) @@ -3230,8 +3025,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3249,7 +3042,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, uint32_t sclk; int r, size = sizeof(sclk); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3258,11 +3051,9 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&sclk, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3288,7 +3079,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, uint32_t mclk; int r, size = sizeof(mclk); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3297,11 +3088,9 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&mclk, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -4188,7 +3977,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) u32 flags = 0; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(dev->dev); @@ -4204,7 +3993,6 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return 0; } - down_read(&adev->reset_sem); if (!is_support_sw_smu(adev) && adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { mutex_lock(&adev->pm.mutex); @@ -4217,13 +4005,10 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) } else { r = amdgpu_debugfs_pm_info_pp(m, adev); } - up_read(&adev->reset_sem); if (r) goto out; - down_read(&adev->reset_sem); amdgpu_device_ip_get_clockgating_state(adev, &flags); - up_read(&adev->reset_sem); seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); amdgpu_parse_cg_state(m, flags); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 116a89990f39e..aa1e77c60c0a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1869,7 +1869,7 @@ static int psp_load_smu_fw(struct psp_context *psp) return 0; - if (amdgpu_in_reset(adev) && ras && ras->supported) { + if (adev->in_gpu_reset && ras && ras->supported) { ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); if (ret) { DRM_WARN("Failed to set MP1 state prepare for reload\n"); @@ -1984,7 +1984,7 @@ static int psp_load_fw(struct amdgpu_device *adev) int ret; struct psp_context *psp = &adev->psp; - if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { + if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ goto skip_memalloc; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index cd1403f83dcf8..f09082578865e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2079,7 +2079,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, amdgpu_ras_request_reset_on_boot(adev, ras_block->block); return 0; - } else if (adev->in_suspend || amdgpu_in_reset(adev)) { + } else if (adev->in_suspend || adev->in_gpu_reset) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -2088,7 +2088,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, } /* in resume phase, no need to create ras fs node */ - if (adev->in_suspend || amdgpu_in_reset(adev)) + if (adev->in_suspend || adev->in_gpu_reset) return 0; if (ih_info->cb) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c7421aa32946c..2d502e98fad0f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2098,7 +2098,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) uint64_t size; int r; - if (!adev->mman.initialized || amdgpu_in_reset(adev) || + if (!adev->mman.initialized || adev->in_gpu_reset || adev->mman.buffer_funcs_enabled == enable) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 039245c98ff87..183743c5fb7bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -628,8 +628,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ - if (!amdgpu_sriov_vf(adev) && - (amdgpu_in_reset(adev) || adev->in_suspend)) + if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 1e211544f2dce..ae720a6dc5a0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -93,7 +93,7 @@ void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq: - dev_warn(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1); + pr_err("failed to write reg %x wait reg %x\n", reg0, reg1); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index b2046c3a404de..f826945989c72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -325,9 +325,9 @@ static inline bool is_virtual_machine(void) #define amdgpu_sriov_is_pp_one_vf(adev) \ ((adev)->virt.gim_feature & AMDGIM_FEATURE_PP_ONE_VF) #define amdgpu_sriov_is_debug(adev) \ - ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) + ((!adev->in_gpu_reset) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ - ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) + ((!adev->in_gpu_reset) && (!adev->virt.tdr_debug)) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 67a756f4337bb..cd6e6eb7d966b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -372,7 +372,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo tmp->hive_id = adev->gmc.xgmi.hive_id; INIT_LIST_HEAD(&tmp->device_list); mutex_init(&tmp->hive_lock); - atomic_set(&tmp->in_reset, 0); + mutex_init(&tmp->reset_lock); task_barrier_init(&tmp->tb); if (lock) @@ -397,7 +397,6 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) hive->hi_req_gpu : adev; bool is_hi_req = pstate == AMDGPU_XGMI_PSTATE_MAX_VEGA20; bool init_low = hive->pstate == AMDGPU_XGMI_PSTATE_UNKNOWN; - bool locked; /* fw bug so temporarily disable pstate switching */ return 0; @@ -405,9 +404,7 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) if (!hive || adev->asic_type != CHIP_VEGA20) return 0; - locked = atomic_read(&hive->in_reset) ? false : true; - if (locked) - mutex_lock(&hive->hive_lock); + mutex_lock(&hive->hive_lock); if (is_hi_req) hive->hi_req_count++; @@ -442,8 +439,7 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) adev : NULL; } out: - if (locked) - mutex_unlock(&hive->hive_lock); + mutex_unlock(&hive->hive_lock); return ret; } @@ -598,6 +594,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) if(!(--hive->number_devices)){ amdgpu_xgmi_sysfs_destroy(adev, hive); mutex_destroy(&hive->hive_lock); + mutex_destroy(&hive->reset_lock); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 61720cd4a1ee2..6999eab16a720 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -30,8 +30,7 @@ struct amdgpu_hive_info { uint64_t hive_id; struct list_head device_list; int number_devices; - struct mutex hive_lock; - atomic_t in_reset; + struct mutex hive_lock, reset_lock; struct kobject *kobj; struct device_attribute dev_attr; struct amdgpu_device *adev; diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index 8341bd965202b..4cfc786699c7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -755,7 +755,6 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) /* jiffies wrap around we will just wait a little longer */ ctx->last_jump_jiffies = jiffies; } - schedule(); } else { ctx->last_jump = ctx->start + target; ctx->last_jump_jiffies = jiffies; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index de6e6de418679..e87d43537013a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6201,7 +6201,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) struct v10_gfx_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.gfx_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6213,7 +6213,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (amdgpu_in_reset(adev)) { + } else if (adev->in_gpu_reset) { /* reset mqd with the backup copy */ if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6566,7 +6566,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v10_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6602,7 +6602,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6612,7 +6612,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 7df567a6656dd..14fd04b699da5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4633,7 +4633,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4670,7 +4670,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4682,7 +4682,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 93c63ff3b35ee..2c5bb282cc01c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3686,7 +3686,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3724,7 +3724,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -3736,7 +3736,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3930,7 +3930,7 @@ static int gfx_v9_0_hw_fini(void *handle) /* Use deinitialize sequence from CAIL when unbinding device from driver, * otherwise KIQ is hanging when binding back */ - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, adev->gfx.kiq.ring.me, adev->gfx.kiq.ring.pipe, @@ -4088,7 +4088,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_read; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 9d3b1245a339c..ec8c0af395538 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,7 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + !adev->in_gpu_reset) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -312,7 +312,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready || - amdgpu_in_reset(adev) || + adev->in_gpu_reset || ring->sched.ready == false) { gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0); mutex_unlock(&adev->mman.gtt_window_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 80c146df338aa..3ce5c1d2fdf2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -434,7 +434,7 @@ static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 9ab65ca7df777..3e6615f9d39c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -635,7 +635,7 @@ static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 773ee11b3d173..6a780b674018f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -501,7 +501,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + !adev->in_gpu_reset) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -596,7 +596,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; if (ring->sched.ready) { @@ -633,8 +633,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - dev_info(adev->dev, - "wait for kiq fence error: %ld\n", r); + DRM_ERROR("wait for kiq fence error: %ld.\n", r); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index fe31cbeccfe91..5fd67e1cc2a04 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -238,16 +238,20 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; + int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the reset_sem to allow "amdgpu_job_timedout" + * we can unlock the lock_reset to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - down_read(&adev->reset_sem); + locked = mutex_trylock(&adev->lock_reset); + if (locked) + adev->in_gpu_reset = true; + do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -257,7 +261,10 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - up_read(&adev->reset_sem); + if (locked) { + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); + } /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 6f55172e83374..ce2bf1fb79ed1 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -259,16 +259,20 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; + int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the reset_sem to allow "amdgpu_job_timedout" + * we can unlock the lock_reset to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - down_read(&adev->reset_sem); + locked = mutex_trylock(&adev->lock_reset); + if (locked) + adev->in_gpu_reset = true; + do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -278,7 +282,10 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - up_read(&adev->reset_sem); + if (locked) { + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); + } /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 7ad1537820b54..e0e60b0d0669e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -304,17 +304,15 @@ static void deallocate_vmid(struct device_queue_manager *dqm, struct qcm_process_device *qpd, struct queue *q) { - if (!dqm->is_resetting) { - /* On GFX v7, CP doesn't flush TC at dequeue */ - if (q->device->device_info->asic_family == CHIP_HAWAII) - if (flush_texture_cache_nocpsch(q->device, qpd)) - pr_err("Failed to flush TC\n"); + /* On GFX v7, CP doesn't flush TC at dequeue */ + if (q->device->device_info->asic_family == CHIP_HAWAII) + if (flush_texture_cache_nocpsch(q->device, qpd)) + pr_err("Failed to flush TC\n"); - kfd_flush_tlb(qpd_to_pdd(qpd)); + kfd_flush_tlb(qpd_to_pdd(qpd)); - /* Release the vmid mapping */ - set_pasid_vmid_mapping(dqm, 0, qpd->vmid); - } + /* Release the vmid mapping */ + set_pasid_vmid_mapping(dqm, 0, qpd->vmid); dqm->vmid_pasid[qpd->vmid] = 0; qpd->vmid = 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ee2258404c8fa..40695d52e9a8d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1551,10 +1551,6 @@ int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process, void kfd_flush_tlb(struct kfd_process_device *pdd) { struct kfd_dev *dev = pdd->dev; - struct device_queue_manager *dqm = dev->dqm; - - if (dqm->is_resetting) - return; if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { /* Nothing to flush until a VMID is assigned, which diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 031b7eb553569..653b4a0d51d8c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1658,7 +1658,7 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - if (amdgpu_in_reset(adev)) { + if (adev->in_gpu_reset) { mutex_lock(&dm->dc_lock); dm->cached_dc_state = dc_copy_state(dm->dc->current_state); @@ -1844,7 +1844,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j; - if (amdgpu_in_reset(adev)) { + if (adev->in_gpu_reset) { dc_state = dm->cached_dc_state; r = dm_dmub_hw_init(adev); diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f87a73cb7ec59..7d17c4f1b4893 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -1110,7 +1110,7 @@ static int smu_disable_dpms(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; bool use_baco = !smu->is_apu && - ((amdgpu_in_reset(adev) && + ((adev->in_gpu_reset && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index da84012b7fd51..c7216362b68da 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -489,7 +489,7 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; - bool use_baco = (amdgpu_in_reset(adev) && + bool use_baco = (adev->in_gpu_reset && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || (adev->in_runpm && amdgpu_asic_supports_baco(adev)); -- GitLab From 2e2f5dd51421648098bb4621719181b963d2d961 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 13 Aug 2020 14:35:35 +0800 Subject: [PATCH 0429/1494] drm/amdgpu: fix NULL pointer access issue when unloading driver When unloading driver by "modprobe -r amdgpu", one NULL pointer dereference bug occurs in ras debugfs releasing. The cause is the duplicated debugfs_remove, as drm debugfs_root dir has been cleaned up already by drm_minor_unregister. BUG: kernel NULL pointer dereference, address: 00000000000000a0 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 11 PID: 1526 Comm: modprobe Tainted: G OE 5.6.0-guchchen #1 Hardware name: System manufacturer System Product Name/TUF Z370-PLUS GAMING II, BIOS 0411 09/21/2018 RIP: 0010:down_write+0x15/0x40 Code: eb de e8 7e 17 72 ff cc cc cc cc cc cc cc cc cc cc cc cc cc cc 0f 1f 44 00 00 53 48 89 fb e8 92 d8 ff ff 31 c0 ba 01 00 00 00 <f0> 48 0f b1 13 75 0f 65 48 8b 04 25 c0 8b 01 00 48 89 43 08 5b c3 RSP: 0018:ffffb1590386fcd0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00000000000000a0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffffffff85b2fcc2 RDI: 00000000000000a0 RBP: ffffb1590386fd30 R08: ffffffff85b2fcc2 R09: 000000000002b3c0 R10: ffff97a330618c40 R11: 00000000000005f6 R12: ffff97a3481beb40 R13: 00000000000000a0 R14: ffff97a3481beb40 R15: 0000000000000000 FS: 00007fb11a717540(0000) GS:ffff97a376cc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000a0 CR3: 00000004066d6006 CR4: 00000000003606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: simple_recursive_removal+0x63/0x370 ? debugfs_remove+0x60/0x60 debugfs_remove+0x40/0x60 amdgpu_ras_fini+0x82/0x230 [amdgpu] ? __kernfs_remove.part.17+0x101/0x1f0 ? kernfs_name_hash+0x12/0x80 amdgpu_device_fini+0x1c0/0x580 [amdgpu] amdgpu_driver_unload_kms+0x3e/0x70 [amdgpu] amdgpu_pci_remove+0x36/0x60 [amdgpu] pci_device_remove+0x3b/0xb0 device_release_driver_internal+0xe5/0x1c0 driver_detach+0x46/0x90 bus_remove_driver+0x58/0xd0 pci_unregister_driver+0x29/0x90 amdgpu_exit+0x11/0x25 [amdgpu] __x64_sys_delete_module+0x13d/0x210 do_syscall_64+0x5f/0x250 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f09082578865e..e437530fa808d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1278,7 +1278,6 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, if (!obj || !obj->ent) return; - debugfs_remove(obj->ent); obj->ent = NULL; put_obj(obj); } @@ -1292,7 +1291,6 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) amdgpu_ras_debugfs_remove(adev, &obj->head); } - debugfs_remove_recursive(con->dir); con->dir = NULL; } /* debugfs end */ -- GitLab From ae2bf61ff39e78ce926de37d22dc7d5159c610cd Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 13 Aug 2020 15:00:56 +0800 Subject: [PATCH 0430/1494] drm/amdgpu: guard ras debugfs creation/removal based on CONFIG_DEBUG_FS It can avoid potential build warn/error when CONFIG_DEBUG_FS is not set. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e437530fa808d..866373c95cae6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1246,6 +1246,7 @@ void amdgpu_ras_debugfs_create(struct amdgpu_device *adev, void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev) { +#if defined(CONFIG_DEBUG_FS) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_manager *obj; struct ras_fs_if fs_info; @@ -1268,6 +1269,7 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev) amdgpu_ras_debugfs_create(adev, &fs_info); } } +#endif } void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, @@ -1284,6 +1286,7 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) { +#if defined(CONFIG_DEBUG_FS) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_manager *obj, *tmp; @@ -1292,6 +1295,7 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) } con->dir = NULL; +#endif } /* debugfs end */ -- GitLab From bc8f830035304b3ba91d4dda2480f868f66fe230 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 14 Aug 2020 12:15:44 +0800 Subject: [PATCH 0431/1494] drm/amd/powerplay: suppress the kernel test robot warning Suppress the warning below: In file included from drivers/gpu/drm/amd/amdgpu/../powerplay/smu_cmn.c: >> drivers/gpu/drm/amd/powerplay/smu_cmn.c:485:9: warning: Identical condition 'ret', second condition is always false [identicalConditionAfterEarlyExit] return ret; ^ drivers/gpu/drm/amd/powerplay/smu_cmn.c:477:6: note: first condition if (ret) ^ drivers/gpu/drm/amd/powerplay/smu_cmn.c:485:9: note: second condition return ret; ^ Signed-off-by: Evan Quan <evan.quan@amd.com> Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index 968b734baac05..a58ea08cd1153 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -604,7 +604,7 @@ int smu_cmn_update_table(struct smu_context *smu, memcpy(table_data, table->cpu_addr, table_size); } - return ret; + return 0; } int smu_cmn_write_watermarks_table(struct smu_context *smu) -- GitLab From 171090dbc0d5e11b2c3207bdd6b4910255e7e61b Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 14 Aug 2020 16:34:15 +0800 Subject: [PATCH 0432/1494] drm/amd/pm: drop redundant MEM_TYPE_* macros As these are already defined in amdgpu_atombios.h. Otherwise, we may hit "redefined" compile warning. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Feifei Xu <Feifei.Xu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h index 3ee54f1829432..76ed2e413594b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h @@ -26,15 +26,6 @@ #include "hwmgr.h" -#define MEM_TYPE_GDDR5 0x50 -#define MEM_TYPE_GDDR4 0x40 -#define MEM_TYPE_GDDR3 0x30 -#define MEM_TYPE_DDR2 0x20 -#define MEM_TYPE_GDDR1 0x10 -#define MEM_TYPE_DDR3 0xb0 -#define MEM_TYPE_MASK 0xF0 - - /* As returned from PowerConnectorDetectionTable. */ #define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80 #define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40 -- GitLab From b89e9eb681653868e3ecb0287f1cf65aaec853da Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 13:11:24 +0800 Subject: [PATCH 0433/1494] drm/amd/powerplay: optimize amdgpu_dpm_set_clockgating_by_smu() implementation Cover the implementation details from outside(of power part). Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 7 +++---- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 21 +++++++-------------- drivers/gpu/drm/amd/amdgpu/vi.c | 21 +++++++-------------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 240c440cbe008..5e9baca556a46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1232,3 +1232,18 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) return ret; } + +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = 0; + + if (pp_funcs && pp_funcs->set_clockgating_by_smu) + ret = pp_funcs->set_clockgating_by_smu(pp_handle, + msg_id); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index cc16b5a3ac449..672b73ad08c23 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -341,10 +341,6 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) -#define amdgpu_dpm_set_clockgating_by_smu(adev, msg_id) \ - ((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\ - (adev)->powerplay.pp_handle, msg_id)) - #define amdgpu_dpm_get_power_profile_mode(adev, buf) \ ((adev)->powerplay.pp_funcs->get_power_profile_mode(\ (adev)->powerplay.pp_handle, buf)) @@ -546,4 +542,7 @@ int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 14fd04b699da5..003982f8eb7fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5880,8 +5880,7 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -5902,8 +5901,7 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; @@ -5932,8 +5930,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) { @@ -5952,8 +5949,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_3D, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -5974,8 +5970,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) { @@ -5990,8 +5985,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_RLC, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) { @@ -6005,8 +5999,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CP, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index f6f2ed0830b1a..b4e4a7a19d19e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1507,8 +1507,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_MC, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_SDMA_MGCG)) { @@ -1526,8 +1525,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_SDMA, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_MGCG)) { @@ -1545,8 +1543,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_HDP, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } @@ -1560,8 +1557,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_LS, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG) { if (state == AMD_CG_STATE_UNGATE) @@ -1573,8 +1569,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_CG, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_DRM_LS) { @@ -1588,8 +1583,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_DRM, PP_STATE_SUPPORT_LS, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG) { @@ -1603,8 +1597,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_ROM, PP_STATE_SUPPORT_CG, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; } -- GitLab From 70bdb6ed222053bb0e4694f255a685cc3f4981e0 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 12 Aug 2020 13:19:25 +0800 Subject: [PATCH 0434/1494] drm/amd/powerplay: drop unnecessary pp_funcs checker It's redundant. Also, the callers should not care about the implementation details. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 11 +++-------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 5 ++--- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 3 +-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 12247a32f9ef9..d3e51d361179e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -136,9 +136,7 @@ static int acp_poweroff(struct generic_pm_domain *genpd) * 2. power off the acp tiles * 3. check and enter ulv state */ - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); } return 0; } @@ -157,8 +155,7 @@ static int acp_poweron(struct generic_pm_domain *genpd) * 2. turn on acp clock * 3. power on acp tiles */ - if (adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); } return 0; } @@ -529,9 +526,7 @@ static int acp_set_powergating_state(void *handle, struct amdgpu_device *adev = (struct amdgpu_device *)handle; bool enable = (state == AMD_PG_STATE_GATE); - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 003982f8eb7fb..3b71272024206 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5343,10 +5343,9 @@ static int gfx_v8_0_late_init(void *handle) static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev, bool enable) { - if (((adev->asic_type == CHIP_POLARIS11) || + if ((adev->asic_type == CHIP_POLARIS11) || (adev->asic_type == CHIP_POLARIS12) || - (adev->asic_type == CHIP_VEGAM)) && - adev->powerplay.pp_funcs->set_powergating_by_smu) + (adev->asic_type == CHIP_VEGAM)) /* Send msg to SMU via Powerplay */ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, enable); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index e24d6e533be33..45a902b1acb77 100755 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -304,8 +304,7 @@ static void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, return; if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); } } -- GitLab From 20d3c28ce4e28ac4df9d139054aecb65ee5a9ee4 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 13 Aug 2020 11:51:11 +0800 Subject: [PATCH 0435/1494] drm/amd/powerplay: optimize i2c bus access implementation The caller needs not care about the internal details how the powerplay API implemented. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 3 +++ drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 15 ++------------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 5e9baca556a46..3465fddff666d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1247,3 +1247,18 @@ int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, return ret; } + +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = -EOPNOTSUPP; + + if (pp_funcs && pp_funcs->smu_i2c_bus_access) + ret = pp_funcs->smu_i2c_bus_access(pp_handle, + acquire); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 672b73ad08c23..5a2344f839f23 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -545,4 +545,7 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, uint32_t msg_id); +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c index d55bf64770c48..7fb240c4990ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c @@ -508,14 +508,9 @@ static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) struct amdgpu_device *adev = to_amdgpu_device(control); /* Send PPSMC_MSG_RequestI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access) - goto Fail; - - - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle, true)) + if (!amdgpu_dpm_smu_i2c_bus_access(adev, true)) return true; -Fail: return false; } @@ -523,16 +518,10 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); - /* Send PPSMC_MSG_RequestI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access) - goto Fail; - /* Send PPSMC_MSG_ReleaseI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle, - false)) + if (!amdgpu_dpm_smu_i2c_bus_access(adev, false)) return true; -Fail: return false; } -- GitLab From e9372d23715d6802fd6d3763cb19c5a0c07ad641 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 13 Aug 2020 13:37:52 +0800 Subject: [PATCH 0436/1494] drm/amd/powerplay: put those exposed power interfaces in amdgpu_dpm.c As other power interfaces. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 425 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 14 + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 423 ----------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h | 8 - 4 files changed, 439 insertions(+), 431 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 3465fddff666d..e480b54f65459 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -28,6 +28,11 @@ #include "amdgpu_dpm.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_display.h" +#include "hwmgr.h" +#include <linux/power_supply.h> + +#define WIDTH_4K 3840 void amdgpu_dpm_print_class_info(u32 class, u32 class2) { @@ -1262,3 +1267,423 @@ int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, return ret; } + +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) +{ + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + if (power_supply_is_system_supplied() > 0) + adev->pm.ac_power = true; + else + adev->pm.ac_power = false; + if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->enable_bapm) + amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); + mutex_unlock(&adev->pm.mutex); + + if (is_support_sw_smu(adev)) + smu_set_ac_dc(&adev->smu); + } +} + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + + if (!data || !size) + return -EINVAL; + + if (is_support_sw_smu(adev)) + ret = smu_read_sensor(&adev->smu, sensor, data, size); + else { + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) + ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, + sensor, data, size); + else + ret = -EINVAL; + } + + return ret; +} + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work) +{ + struct amdgpu_device *adev = + container_of(work, struct amdgpu_device, + pm.dpm.thermal.work); + /* switch to the thermal state */ + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + int temp, size = sizeof(temp); + + if (!adev->pm.dpm_enabled) + return; + + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, + (void *)&temp, &size)) { + if (temp < adev->pm.dpm.thermal.min_temp) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } else { + if (adev->pm.dpm.thermal.high_to_low) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } + mutex_lock(&adev->pm.mutex); + if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) + adev->pm.dpm.thermal_active = true; + else + adev->pm.dpm.thermal_active = false; + adev->pm.dpm.state = dpm_state; + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); +} + +static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type dpm_state) +{ + int i; + struct amdgpu_ps *ps; + u32 ui_class; + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? + true : false; + + /* check if the vblank period is too short to adjust the mclk */ + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { + if (amdgpu_dpm_vblank_too_short(adev)) + single_display = false; + } + + /* certain older asics have a separare 3D performance state, + * so try that first if the user selected performance + */ + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; + /* balanced states don't exist at the moment */ + if (dpm_state == POWER_STATE_TYPE_BALANCED) + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + +restart_search: + /* Pick the best power state based on current conditions */ + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + ps = &adev->pm.dpm.ps[i]; + ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; + switch (dpm_state) { + /* user states */ + case POWER_STATE_TYPE_BATTERY: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_BALANCED: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_PERFORMANCE: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + /* internal states */ + case POWER_STATE_TYPE_INTERNAL_UVD: + if (adev->pm.dpm.uvd_ps) + return adev->pm.dpm.uvd_ps; + else + break; + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_BOOT: + return adev->pm.dpm.boot_ps; + case POWER_STATE_TYPE_INTERNAL_THERMAL: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ACPI: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ULV: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_3DPERF: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + return ps; + break; + default: + break; + } + } + /* use a fallback state if we didn't match */ + switch (dpm_state) { + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (adev->pm.dpm.uvd_ps) { + return adev->pm.dpm.uvd_ps; + } else { + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + } + case POWER_STATE_TYPE_INTERNAL_THERMAL: + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_ACPI: + dpm_state = POWER_STATE_TYPE_BATTERY; + goto restart_search; + case POWER_STATE_TYPE_BATTERY: + case POWER_STATE_TYPE_BALANCED: + case POWER_STATE_TYPE_INTERNAL_3DPERF: + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + default: + break; + } + + return NULL; +} + +static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) +{ + struct amdgpu_ps *ps; + enum amd_pm_state_type dpm_state; + int ret; + bool equal = false; + + /* if dpm init failed */ + if (!adev->pm.dpm_enabled) + return; + + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { + /* add other state override checks here */ + if ((!adev->pm.dpm.thermal_active) && + (!adev->pm.dpm.uvd_active)) + adev->pm.dpm.state = adev->pm.dpm.user_state; + } + dpm_state = adev->pm.dpm.state; + + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); + if (ps) + adev->pm.dpm.requested_ps = ps; + else + return; + + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + printk("switching from power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); + printk("switching to power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); + } + + /* update whether vce is active */ + ps->vce_active = adev->pm.dpm.vce_active; + if (adev->powerplay.pp_funcs->display_configuration_changed) + amdgpu_dpm_display_configuration_changed(adev); + + ret = amdgpu_dpm_pre_set_power_state(adev); + if (ret) + return; + + if (adev->powerplay.pp_funcs->check_state_equal) { + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) + equal = false; + } + + if (equal) + return; + + amdgpu_dpm_set_power_state(adev); + amdgpu_dpm_post_set_power_state(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; + + if (adev->powerplay.pp_funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) { + enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; + /* force low perf level for thermal */ + amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + /* save the user's level */ + adev->pm.dpm.forced_level = level; + } else { + /* otherwise, user selected level */ + amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + } + } +} + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) +{ + int i = 0; + + if (!adev->pm.dpm_enabled) + return; + + if (adev->mode_info.num_crtc) + amdgpu_display_bandwidth_update(adev); + + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->sched.ready) + amdgpu_fence_wait_empty(ring); + } + + if (is_support_sw_smu(adev)) { + struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; + smu_handle_task(&adev->smu, + smu_dpm->dpm_level, + AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, + true); + } else { + if (adev->powerplay.pp_funcs->dispatch_tasks) { + if (!amdgpu_device_has_dc_support(adev)) { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; + adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); + adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ + if (adev->pm.pm_display_cfg.vrefresh > 120) + adev->pm.pm_display_cfg.min_vblank_time = 0; + if (adev->powerplay.pp_funcs->display_configuration_change) + adev->powerplay.pp_funcs->display_configuration_change( + adev->powerplay.pp_handle, + &adev->pm.pm_display_cfg); + mutex_unlock(&adev->pm.mutex); + } + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); + } else { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + amdgpu_dpm_change_power_state_locked(adev); + mutex_unlock(&adev->pm.mutex); + } + } +} + +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + } else { + adev->pm.dpm.uvd_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); + if (ret) + DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + + /* enable/disable Low Memory PState for UVD (4k videos) */ + if (adev->asic_type == CHIP_STONEY && + adev->uvd.decode_image_width >= WIDTH_4K) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if (hwmgr && hwmgr->hwmgr_func && + hwmgr->hwmgr_func->update_nbdpm_pstate) + hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, + !enable, + true); + } + } +} + +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; + } else { + adev->pm.dpm.vce_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); + if (ret) + DRM_ERROR("Dpm %s vce failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + } +} + +void amdgpu_pm_print_power_states(struct amdgpu_device *adev) +{ + int i; + + if (adev->powerplay.pp_funcs->print_power_state == NULL) + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) + amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); + +} + +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); + if (ret) + DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", + enable ? "enable" : "disable", ret); +} + +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) +{ + int r; + + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { + r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); + if (r) { + pr_err("smu firmware loading failed\n"); + return r; + } + *smu_version = adev->pm.fw_version; + } + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 5a2344f839f23..dff4a5f99bb03 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -548,4 +548,18 @@ int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, bool acquire); +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size); + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work); + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); +void amdgpu_pm_print_power_states(struct amdgpu_device *adev); +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 65ad174bb976b..5fc6a9a13096f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -29,17 +29,14 @@ #include "amdgpu_drv.h" #include "amdgpu_pm.h" #include "amdgpu_dpm.h" -#include "amdgpu_display.h" #include "amdgpu_smu.h" #include "atom.h" -#include <linux/power_supply.h> #include <linux/pci.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/nospec.h> #include <linux/pm_runtime.h> #include "hwmgr.h" -#define WIDTH_4K 3840 static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, @@ -81,45 +78,6 @@ static const struct hwmon_temp_label { {PP_TEMP_MEM, "mem"}, }; -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) -{ - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - if (power_supply_is_system_supplied() > 0) - adev->pm.ac_power = true; - else - adev->pm.ac_power = false; - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->enable_bapm) - amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); - mutex_unlock(&adev->pm.mutex); - - if (is_support_sw_smu(adev)) - smu_set_ac_dc(&adev->smu); - } -} - -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if (!data || !size) - return -EINVAL; - - if (is_support_sw_smu(adev)) - ret = smu_read_sensor(&adev->smu, sensor, data, size); - else { - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) - ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, - sensor, data, size); - else - ret = -EINVAL; - } - - return ret; -} - /** * DOC: power_dpm_state * @@ -3425,338 +3383,6 @@ static const struct attribute_group *hwmon_groups[] = { NULL }; -void amdgpu_dpm_thermal_work_handler(struct work_struct *work) -{ - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, - pm.dpm.thermal.work); - /* switch to the thermal state */ - enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; - int temp, size = sizeof(temp); - - if (!adev->pm.dpm_enabled) - return; - - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, - (void *)&temp, &size)) { - if (temp < adev->pm.dpm.thermal.min_temp) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } else { - if (adev->pm.dpm.thermal.high_to_low) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } - mutex_lock(&adev->pm.mutex); - if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) - adev->pm.dpm.thermal_active = true; - else - adev->pm.dpm.thermal_active = false; - adev->pm.dpm.state = dpm_state; - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); -} - -static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amd_pm_state_type dpm_state) -{ - int i; - struct amdgpu_ps *ps; - u32 ui_class; - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? - true : false; - - /* check if the vblank period is too short to adjust the mclk */ - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { - if (amdgpu_dpm_vblank_too_short(adev)) - single_display = false; - } - - /* certain older asics have a separare 3D performance state, - * so try that first if the user selected performance - */ - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; - /* balanced states don't exist at the moment */ - if (dpm_state == POWER_STATE_TYPE_BALANCED) - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - -restart_search: - /* Pick the best power state based on current conditions */ - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - ps = &adev->pm.dpm.ps[i]; - ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; - switch (dpm_state) { - /* user states */ - case POWER_STATE_TYPE_BATTERY: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_BALANCED: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_PERFORMANCE: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - /* internal states */ - case POWER_STATE_TYPE_INTERNAL_UVD: - if (adev->pm.dpm.uvd_ps) - return adev->pm.dpm.uvd_ps; - else - break; - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_BOOT: - return adev->pm.dpm.boot_ps; - case POWER_STATE_TYPE_INTERNAL_THERMAL: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ACPI: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ULV: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_3DPERF: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - return ps; - break; - default: - break; - } - } - /* use a fallback state if we didn't match */ - switch (dpm_state) { - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (adev->pm.dpm.uvd_ps) { - return adev->pm.dpm.uvd_ps; - } else { - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - } - case POWER_STATE_TYPE_INTERNAL_THERMAL: - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_ACPI: - dpm_state = POWER_STATE_TYPE_BATTERY; - goto restart_search; - case POWER_STATE_TYPE_BATTERY: - case POWER_STATE_TYPE_BALANCED: - case POWER_STATE_TYPE_INTERNAL_3DPERF: - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - default: - break; - } - - return NULL; -} - -static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) -{ - struct amdgpu_ps *ps; - enum amd_pm_state_type dpm_state; - int ret; - bool equal = false; - - /* if dpm init failed */ - if (!adev->pm.dpm_enabled) - return; - - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { - /* add other state override checks here */ - if ((!adev->pm.dpm.thermal_active) && - (!adev->pm.dpm.uvd_active)) - adev->pm.dpm.state = adev->pm.dpm.user_state; - } - dpm_state = adev->pm.dpm.state; - - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); - if (ps) - adev->pm.dpm.requested_ps = ps; - else - return; - - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { - printk("switching from power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); - printk("switching to power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); - } - - /* update whether vce is active */ - ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) - amdgpu_dpm_display_configuration_changed(adev); - - ret = amdgpu_dpm_pre_set_power_state(adev); - if (ret) - return; - - if (adev->powerplay.pp_funcs->check_state_equal) { - if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) - equal = false; - } - - if (equal) - return; - - amdgpu_dpm_set_power_state(adev); - amdgpu_dpm_post_set_power_state(adev); - - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - - if (adev->powerplay.pp_funcs->force_performance_level) { - if (adev->pm.dpm.thermal_active) { - enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; - /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); - /* save the user's level */ - adev->pm.dpm.forced_level = level; - } else { - /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); - } - } -} - -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; - } else { - adev->pm.dpm.uvd_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); - if (ret) - DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - - /* enable/disable Low Memory PState for UVD (4k videos) */ - if (adev->asic_type == CHIP_STONEY && - adev->uvd.decode_image_width >= WIDTH_4K) { - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->hwmgr_func && - hwmgr->hwmgr_func->update_nbdpm_pstate) - hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, - !enable, - true); - } - } -} - -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; - } else { - adev->pm.dpm.vce_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); - if (ret) - DRM_ERROR("Dpm %s vce failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - } -} - -void amdgpu_pm_print_power_states(struct amdgpu_device *adev) -{ - int i; - - if (adev->powerplay.pp_funcs->print_power_state == NULL) - return; - - for (i = 0; i < adev->pm.dpm.num_ps; i++) - amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - -} - -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); - if (ret) - DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", - enable ? "enable" : "disable", ret); -} - -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) -{ - int r; - - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { - r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); - if (r) { - pr_err("smu firmware loading failed\n"); - return r; - } - *smu_version = adev->pm.fw_version; - } - return 0; -} - int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) { int ret; @@ -3817,55 +3443,6 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) amdgpu_device_attr_remove_groups(adev, &adev->pm.pm_attr_list); } -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) -{ - int i = 0; - - if (!adev->pm.dpm_enabled) - return; - - if (adev->mode_info.num_crtc) - amdgpu_display_bandwidth_update(adev); - - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->sched.ready) - amdgpu_fence_wait_empty(ring); - } - - if (is_support_sw_smu(adev)) { - struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; - smu_handle_task(&adev->smu, - smu_dpm->dpm_level, - AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, - true); - } else { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - if (!amdgpu_device_has_dc_support(adev)) { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; - adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); - adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ - if (adev->pm.pm_display_cfg.vrefresh > 120) - adev->pm.pm_display_cfg.min_vblank_time = 0; - if (adev->powerplay.pp_funcs->display_configuration_change) - adev->powerplay.pp_funcs->display_configuration_change( - adev->powerplay.pp_handle, - &adev->pm.pm_display_cfg); - mutex_unlock(&adev->pm.mutex); - } - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); - } else { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - amdgpu_dpm_change_power_state_locked(adev); - mutex_unlock(&adev->pm.mutex); - } - } -} - /* * Debugfs info */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h index d9ae2b49a402f..45a22e101d159 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h @@ -79,18 +79,10 @@ struct amdgpu_device_attr_entry { amdgpu_get_##_name, NULL, \ _flags, ##__VA_ARGS__) -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); int amdgpu_pm_sysfs_init(struct amdgpu_device *adev); int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev); void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev); void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev); -void amdgpu_pm_print_power_states(struct amdgpu_device *adev); -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); -void amdgpu_dpm_thermal_work_handler(struct work_struct *work); -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); -- GitLab From e098bc9612c2b60f94920461d71c92962a916e73 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 13 Aug 2020 16:39:25 +0800 Subject: [PATCH 0437/1494] drm/amd/pm: optimize the power related source code layout The target is to provide a clear entry point(for power routines). Also this can help to maintain a clear view about the frameworks used on different ASICs. Hopefully all these can make power part more friendly to play with. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/Makefile | 14 ++---- drivers/gpu/drm/amd/pm/Makefile | 46 +++++++++++++++++++ .../gpu/drm/amd/{amdgpu => pm}/amdgpu_dpm.c | 0 .../gpu/drm/amd/{amdgpu => pm}/amdgpu_pm.c | 0 .../amd/{powerplay => pm}/inc/amd_powerplay.h | 0 .../drm/amd/{amdgpu => pm/inc}/amdgpu_dpm.h | 0 .../drm/amd/{amdgpu => pm/inc}/amdgpu_pm.h | 0 .../amd/{powerplay => pm}/inc/amdgpu_smu.h | 0 .../{powerplay => pm}/inc/arcturus_ppsmc.h | 0 .../drm/amd/{powerplay => pm}/inc/cz_ppsmc.h | 0 .../amd/{powerplay => pm}/inc/fiji_ppsmc.h | 0 .../{powerplay => pm}/inc/hardwaremanager.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/hwmgr.h | 0 .../inc/polaris10_pwrvirus.h | 0 .../amd/{powerplay => pm}/inc/power_state.h | 0 .../drm/amd/{powerplay => pm}/inc/pp_debug.h | 0 .../drm/amd/{powerplay => pm}/inc/pp_endian.h | 0 .../amd/{powerplay => pm}/inc/pp_thermal.h | 0 .../amd/{powerplay => pm}/inc/ppinterrupt.h | 0 .../drm/amd/{powerplay => pm}/inc/rv_ppsmc.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu10.h | 0 .../{powerplay => pm}/inc/smu10_driver_if.h | 0 .../{powerplay => pm}/inc/smu11_driver_if.h | 0 .../inc/smu11_driver_if_arcturus.h | 0 .../inc/smu11_driver_if_navi10.h | 0 .../inc/smu11_driver_if_sienna_cichlid.h | 0 .../{powerplay => pm}/inc/smu12_driver_if.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu7.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu71.h | 0 .../{powerplay => pm}/inc/smu71_discrete.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu72.h | 0 .../{powerplay => pm}/inc/smu72_discrete.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu73.h | 0 .../{powerplay => pm}/inc/smu73_discrete.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu74.h | 0 .../{powerplay => pm}/inc/smu74_discrete.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu75.h | 0 .../{powerplay => pm}/inc/smu75_discrete.h | 0 .../amd/{powerplay => pm}/inc/smu7_common.h | 0 .../amd/{powerplay => pm}/inc/smu7_discrete.h | 0 .../amd/{powerplay => pm}/inc/smu7_fusion.h | 0 .../amd/{powerplay => pm}/inc/smu7_ppsmc.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu8.h | 0 .../amd/{powerplay => pm}/inc/smu8_fusion.h | 0 .../gpu/drm/amd/{powerplay => pm}/inc/smu9.h | 0 .../{powerplay => pm}/inc/smu9_driver_if.h | 0 .../drm/amd/{powerplay => pm}/inc/smu_types.h | 0 .../{powerplay => pm}/inc/smu_ucode_xfer_cz.h | 0 .../{powerplay => pm}/inc/smu_ucode_xfer_vi.h | 0 .../drm/amd/{powerplay => pm}/inc/smu_v11_0.h | 0 .../{powerplay => pm}/inc/smu_v11_0_7_ppsmc.h | 0 .../inc/smu_v11_0_7_pptable.h | 0 .../{powerplay => pm}/inc/smu_v11_0_ppsmc.h | 0 .../{powerplay => pm}/inc/smu_v11_0_pptable.h | 0 .../drm/amd/{powerplay => pm}/inc/smu_v12_0.h | 0 .../{powerplay => pm}/inc/smu_v12_0_ppsmc.h | 0 .../drm/amd/{powerplay => pm}/inc/smumgr.h | 0 .../amd/{powerplay => pm}/inc/tonga_ppsmc.h | 0 .../amd/{powerplay => pm}/inc/vega10_ppsmc.h | 0 .../inc/vega12/smu9_driver_if.h | 0 .../amd/{powerplay => pm}/inc/vega12_ppsmc.h | 0 .../amd/{powerplay => pm}/inc/vega20_ppsmc.h | 0 .../gpu/drm/amd/{ => pm}/powerplay/Makefile | 23 ++++------ .../amd/{ => pm}/powerplay/amd_powerplay.c | 0 .../amd/{amdgpu => pm/powerplay}/cik_dpm.h | 0 .../drm/amd/{ => pm}/powerplay/hwmgr/Makefile | 0 .../amd/{ => pm}/powerplay/hwmgr/ci_baco.c | 0 .../amd/{ => pm}/powerplay/hwmgr/ci_baco.h | 0 .../{ => pm}/powerplay/hwmgr/common_baco.c | 0 .../{ => pm}/powerplay/hwmgr/common_baco.h | 0 .../amd/{ => pm}/powerplay/hwmgr/fiji_baco.c | 0 .../amd/{ => pm}/powerplay/hwmgr/fiji_baco.h | 0 .../powerplay/hwmgr/hardwaremanager.c | 0 .../drm/amd/{ => pm}/powerplay/hwmgr/hwmgr.c | 0 .../amd/{ => pm}/powerplay/hwmgr/hwmgr_ppt.h | 0 .../{ => pm}/powerplay/hwmgr/polaris_baco.c | 0 .../{ => pm}/powerplay/hwmgr/polaris_baco.h | 0 .../{ => pm}/powerplay/hwmgr/pp_overdriver.c | 0 .../{ => pm}/powerplay/hwmgr/pp_overdriver.h | 0 .../drm/amd/{ => pm}/powerplay/hwmgr/pp_psm.c | 0 .../drm/amd/{ => pm}/powerplay/hwmgr/pp_psm.h | 0 .../amd/{ => pm}/powerplay/hwmgr/ppatomctrl.c | 0 .../amd/{ => pm}/powerplay/hwmgr/ppatomctrl.h | 0 .../{ => pm}/powerplay/hwmgr/ppatomfwctrl.c | 0 .../{ => pm}/powerplay/hwmgr/ppatomfwctrl.h | 0 .../amd/{ => pm}/powerplay/hwmgr/ppevvmath.h | 0 .../{ => pm}/powerplay/hwmgr/pppcielanes.c | 0 .../{ => pm}/powerplay/hwmgr/pppcielanes.h | 0 .../{ => pm}/powerplay/hwmgr/pptable_v1_0.h | 0 .../powerplay/hwmgr/process_pptables_v1_0.c | 0 .../powerplay/hwmgr/process_pptables_v1_0.h | 0 .../powerplay/hwmgr/processpptables.c | 0 .../powerplay/hwmgr/processpptables.h | 0 .../{ => pm}/powerplay/hwmgr/smu10_hwmgr.c | 0 .../{ => pm}/powerplay/hwmgr/smu10_hwmgr.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu10_inc.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu7_baco.c | 0 .../amd/{ => pm}/powerplay/hwmgr/smu7_baco.h | 0 .../powerplay/hwmgr/smu7_clockpowergating.c | 0 .../powerplay/hwmgr/smu7_clockpowergating.h | 0 .../powerplay/hwmgr/smu7_dyn_defaults.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu7_hwmgr.c | 0 .../amd/{ => pm}/powerplay/hwmgr/smu7_hwmgr.h | 0 .../{ => pm}/powerplay/hwmgr/smu7_powertune.c | 0 .../{ => pm}/powerplay/hwmgr/smu7_powertune.h | 0 .../{ => pm}/powerplay/hwmgr/smu7_thermal.c | 0 .../{ => pm}/powerplay/hwmgr/smu7_thermal.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu8_hwmgr.c | 0 .../amd/{ => pm}/powerplay/hwmgr/smu8_hwmgr.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu9_baco.c | 0 .../amd/{ => pm}/powerplay/hwmgr/smu9_baco.h | 0 .../amd/{ => pm}/powerplay/hwmgr/smu_helper.c | 0 .../amd/{ => pm}/powerplay/hwmgr/smu_helper.h | 0 .../amd/{ => pm}/powerplay/hwmgr/tonga_baco.c | 0 .../amd/{ => pm}/powerplay/hwmgr/tonga_baco.h | 0 .../{ => pm}/powerplay/hwmgr/vega10_baco.c | 0 .../{ => pm}/powerplay/hwmgr/vega10_baco.h | 0 .../{ => pm}/powerplay/hwmgr/vega10_hwmgr.c | 0 .../{ => pm}/powerplay/hwmgr/vega10_hwmgr.h | 0 .../amd/{ => pm}/powerplay/hwmgr/vega10_inc.h | 0 .../powerplay/hwmgr/vega10_powertune.c | 0 .../powerplay/hwmgr/vega10_powertune.h | 0 .../{ => pm}/powerplay/hwmgr/vega10_pptable.h | 0 .../powerplay/hwmgr/vega10_processpptables.c | 0 .../powerplay/hwmgr/vega10_processpptables.h | 0 .../{ => pm}/powerplay/hwmgr/vega10_thermal.c | 0 .../{ => pm}/powerplay/hwmgr/vega10_thermal.h | 0 .../{ => pm}/powerplay/hwmgr/vega12_baco.c | 0 .../{ => pm}/powerplay/hwmgr/vega12_baco.h | 0 .../{ => pm}/powerplay/hwmgr/vega12_hwmgr.c | 0 .../{ => pm}/powerplay/hwmgr/vega12_hwmgr.h | 0 .../amd/{ => pm}/powerplay/hwmgr/vega12_inc.h | 0 .../{ => pm}/powerplay/hwmgr/vega12_pptable.h | 0 .../powerplay/hwmgr/vega12_processpptables.c | 0 .../powerplay/hwmgr/vega12_processpptables.h | 0 .../{ => pm}/powerplay/hwmgr/vega12_thermal.c | 0 .../{ => pm}/powerplay/hwmgr/vega12_thermal.h | 0 .../{ => pm}/powerplay/hwmgr/vega20_baco.c | 0 .../{ => pm}/powerplay/hwmgr/vega20_baco.h | 0 .../{ => pm}/powerplay/hwmgr/vega20_hwmgr.c | 0 .../{ => pm}/powerplay/hwmgr/vega20_hwmgr.h | 0 .../amd/{ => pm}/powerplay/hwmgr/vega20_inc.h | 0 .../powerplay/hwmgr/vega20_powertune.c | 0 .../powerplay/hwmgr/vega20_powertune.h | 0 .../{ => pm}/powerplay/hwmgr/vega20_pptable.h | 0 .../powerplay/hwmgr/vega20_processpptables.c | 0 .../powerplay/hwmgr/vega20_processpptables.h | 0 .../{ => pm}/powerplay/hwmgr/vega20_thermal.c | 0 .../{ => pm}/powerplay/hwmgr/vega20_thermal.h | 0 .../drm/amd/{amdgpu => pm/powerplay}/kv_dpm.c | 0 .../drm/amd/{amdgpu => pm/powerplay}/kv_dpm.h | 0 .../drm/amd/{amdgpu => pm/powerplay}/kv_smc.c | 0 .../drm/amd/{amdgpu => pm/powerplay}/ppsmc.h | 0 .../amd/{amdgpu => pm/powerplay}/r600_dpm.h | 0 .../drm/amd/{amdgpu => pm/powerplay}/si_dpm.c | 0 .../drm/amd/{amdgpu => pm/powerplay}/si_dpm.h | 0 .../drm/amd/{amdgpu => pm/powerplay}/si_smc.c | 0 .../{amdgpu => pm/powerplay}/sislands_smc.h | 0 .../amd/{ => pm}/powerplay/smumgr/Makefile | 0 .../amd/{ => pm}/powerplay/smumgr/ci_smumgr.c | 0 .../amd/{ => pm}/powerplay/smumgr/ci_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/fiji_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/fiji_smumgr.h | 0 .../powerplay/smumgr/iceland_smumgr.c | 0 .../powerplay/smumgr/iceland_smumgr.h | 0 .../powerplay/smumgr/polaris10_smumgr.c | 0 .../powerplay/smumgr/polaris10_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/smu10_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/smu10_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/smu7_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/smu7_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/smu8_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/smu8_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/smu9_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/smu9_smumgr.h | 0 .../amd/{ => pm}/powerplay/smumgr/smumgr.c | 0 .../{ => pm}/powerplay/smumgr/tonga_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/tonga_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/vega10_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/vega10_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/vega12_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/vega12_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/vega20_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/vega20_smumgr.h | 0 .../{ => pm}/powerplay/smumgr/vegam_smumgr.c | 0 .../{ => pm}/powerplay/smumgr/vegam_smumgr.h | 0 drivers/gpu/drm/amd/pm/swsmu/Makefile | 36 +++++++++++++++ .../amd/{powerplay => pm/swsmu}/amdgpu_smu.c | 0 drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile | 33 +++++++++++++ .../swsmu/smu11}/arcturus_ppt.c | 0 .../swsmu/smu11}/arcturus_ppt.h | 0 .../swsmu/smu11}/navi10_ppt.c | 0 .../swsmu/smu11}/navi10_ppt.h | 0 .../swsmu/smu11}/sienna_cichlid_ppt.c | 0 .../swsmu/smu11}/sienna_cichlid_ppt.h | 0 .../{powerplay => pm/swsmu/smu11}/smu_v11_0.c | 0 drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile | 31 +++++++++++++ .../swsmu/smu12}/renoir_ppt.c | 0 .../swsmu/smu12}/renoir_ppt.h | 0 .../{powerplay => pm/swsmu/smu12}/smu_v12_0.c | 0 .../drm/amd/{powerplay => pm/swsmu}/smu_cmn.c | 0 .../drm/amd/{powerplay => pm/swsmu}/smu_cmn.h | 0 .../{powerplay => pm/swsmu}/smu_internal.h | 0 203 files changed, 160 insertions(+), 23 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/Makefile rename drivers/gpu/drm/amd/{amdgpu => pm}/amdgpu_dpm.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm}/amdgpu_pm.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/amd_powerplay.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/inc}/amdgpu_dpm.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/inc}/amdgpu_pm.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/amdgpu_smu.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/arcturus_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/cz_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/fiji_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/hardwaremanager.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/hwmgr.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/polaris10_pwrvirus.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/power_state.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/pp_debug.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/pp_endian.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/pp_thermal.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/ppinterrupt.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/rv_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu10.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu10_driver_if.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu11_driver_if.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu11_driver_if_arcturus.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu11_driver_if_navi10.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu11_driver_if_sienna_cichlid.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu12_driver_if.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu7.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu71.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu71_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu72.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu72_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu73.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu73_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu74.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu74_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu75.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu75_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu7_common.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu7_discrete.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu7_fusion.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu7_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu8.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu8_fusion.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu9.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu9_driver_if.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_types.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_ucode_xfer_cz.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_ucode_xfer_vi.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v11_0.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v11_0_7_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v11_0_7_pptable.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v11_0_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v11_0_pptable.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v12_0.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smu_v12_0_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/smumgr.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/tonga_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/vega10_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/vega12/smu9_driver_if.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/vega12_ppsmc.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm}/inc/vega20_ppsmc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/Makefile (70%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/amd_powerplay.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/cik_dpm.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/Makefile (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ci_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ci_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/common_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/common_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/fiji_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/fiji_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/hardwaremanager.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/hwmgr_ppt.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/polaris_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/polaris_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pp_overdriver.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pp_overdriver.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pp_psm.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pp_psm.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ppatomctrl.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ppatomctrl.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ppatomfwctrl.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ppatomfwctrl.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/ppevvmath.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pppcielanes.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pppcielanes.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/pptable_v1_0.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/process_pptables_v1_0.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/process_pptables_v1_0.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/processpptables.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/processpptables.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu10_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu10_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu10_inc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_clockpowergating.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_clockpowergating.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_dyn_defaults.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_powertune.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_powertune.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_thermal.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu7_thermal.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu8_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu8_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu9_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu9_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu_helper.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/smu_helper.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/tonga_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/tonga_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_inc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_powertune.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_powertune.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_pptable.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_processpptables.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_processpptables.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_thermal.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega10_thermal.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_inc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_pptable.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_processpptables.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_processpptables.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_thermal.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega12_thermal.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_baco.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_baco.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_hwmgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_hwmgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_inc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_powertune.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_powertune.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_pptable.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_processpptables.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_processpptables.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_thermal.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/hwmgr/vega20_thermal.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/kv_dpm.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/kv_dpm.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/kv_smc.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/ppsmc.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/r600_dpm.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/si_dpm.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/si_dpm.h (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/si_smc.c (100%) rename drivers/gpu/drm/amd/{amdgpu => pm/powerplay}/sislands_smc.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/Makefile (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/ci_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/ci_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/fiji_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/fiji_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/iceland_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/iceland_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/polaris10_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/polaris10_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu10_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu10_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu7_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu7_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu8_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu8_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu9_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smu9_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/tonga_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/tonga_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega10_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega10_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega12_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega12_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega20_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vega20_smumgr.h (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vegam_smumgr.c (100%) rename drivers/gpu/drm/amd/{ => pm}/powerplay/smumgr/vegam_smumgr.h (100%) create mode 100644 drivers/gpu/drm/amd/pm/swsmu/Makefile rename drivers/gpu/drm/amd/{powerplay => pm/swsmu}/amdgpu_smu.c (100%) create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/arcturus_ppt.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/arcturus_ppt.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/navi10_ppt.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/navi10_ppt.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/sienna_cichlid_ppt.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/sienna_cichlid_ppt.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu11}/smu_v11_0.c (100%) create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu12}/renoir_ppt.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu12}/renoir_ppt.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu/smu12}/smu_v12_0.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu}/smu_cmn.c (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu}/smu_cmn.h (100%) rename drivers/gpu/drm/amd/{powerplay => pm/swsmu}/smu_internal.h (100%) diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index dec1927ca75d4..39976c7b100c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -30,7 +30,7 @@ FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME) ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ - -I$(FULL_AMD_PATH)/powerplay/inc \ + -I$(FULL_AMD_PATH)/pm/inc \ -I$(FULL_AMD_PATH)/acp/include \ -I$(FULL_AMD_DISPLAY_PATH) \ -I$(FULL_AMD_DISPLAY_PATH)/include \ @@ -47,7 +47,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ - amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ + atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_dma_buf.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ @@ -60,10 +60,10 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o # add asic specific block -amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o \ dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o -amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o \ uvd_v3_1.o amdgpu-y += \ @@ -105,10 +105,6 @@ amdgpu-y += \ psp_v11_0.o \ psp_v12_0.o -# add SMC block -amdgpu-y += \ - amdgpu_dpm.o - # add DCE block amdgpu-y += \ dce_v10_0.o \ @@ -212,7 +208,7 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_mn.o -include $(FULL_AMD_PATH)/powerplay/Makefile +include $(FULL_AMD_PATH)/pm/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) diff --git a/drivers/gpu/drm/amd/pm/Makefile b/drivers/gpu/drm/amd/pm/Makefile new file mode 100644 index 0000000000000..f01e86030cd16 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/Makefile @@ -0,0 +1,46 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +subdir-ccflags-y += \ + -I$(FULL_AMD_PATH)/pm/inc/ \ + -I$(FULL_AMD_PATH)/include/asic_reg \ + -I$(FULL_AMD_PATH)/include \ + -I$(FULL_AMD_PATH)/pm/swsmu \ + -I$(FULL_AMD_PATH)/pm/swsmu/smu11 \ + -I$(FULL_AMD_PATH)/pm/swsmu/smu12 \ + -I$(FULL_AMD_PATH)/pm/powerplay \ + -I$(FULL_AMD_PATH)/pm/powerplay/smumgr\ + -I$(FULL_AMD_PATH)/pm/powerplay/hwmgr + +AMD_PM_PATH = ../pm + +PM_LIBS = swsmu powerplay + +AMD_PM = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/,$(PM_LIBS))) + +include $(AMD_PM) + +PM_MGR = amdgpu_dpm.o amdgpu_pm.o + +AMD_PM_POWER = $(addprefix $(AMD_PM_PATH)/,$(PM_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PM_POWER) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c rename to drivers/gpu/drm/amd/pm/amdgpu_dpm.c diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c rename to drivers/gpu/drm/amd/pm/amdgpu_pm.c diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/pm/inc/amd_powerplay.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h rename to drivers/gpu/drm/amd/pm/inc/amd_powerplay.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h rename to drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h rename to drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h rename to drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/pm/inc/hardwaremanager.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h rename to drivers/gpu/drm/amd/pm/inc/hardwaremanager.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/hwmgr.h rename to drivers/gpu/drm/amd/pm/inc/hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h b/drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h rename to drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/pm/inc/power_state.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/power_state.h rename to drivers/gpu/drm/amd/pm/inc/power_state.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/pm/inc/pp_debug.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/pp_debug.h rename to drivers/gpu/drm/amd/pm/inc/pp_debug.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_endian.h b/drivers/gpu/drm/amd/pm/inc/pp_endian.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/pp_endian.h rename to drivers/gpu/drm/amd/pm/inc/pp_endian.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h b/drivers/gpu/drm/amd/pm/inc/pp_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h rename to drivers/gpu/drm/amd/pm/inc/pp_thermal.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h b/drivers/gpu/drm/amd/pm/inc/ppinterrupt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h rename to drivers/gpu/drm/amd/pm/inc/ppinterrupt.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu10.h b/drivers/gpu/drm/amd/pm/inc/smu10.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu10.h rename to drivers/gpu/drm/amd/pm/inc/smu10.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h rename to drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h rename to drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h rename to drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h rename to drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h rename to drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h rename to drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7.h b/drivers/gpu/drm/amd/pm/inc/smu7.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu7.h rename to drivers/gpu/drm/amd/pm/inc/smu7.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu71.h b/drivers/gpu/drm/amd/pm/inc/smu71.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu71.h rename to drivers/gpu/drm/amd/pm/inc/smu71.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu71_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu71_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu71_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu71_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72.h b/drivers/gpu/drm/amd/pm/inc/smu72.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu72.h rename to drivers/gpu/drm/amd/pm/inc/smu72.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu72_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu72_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73.h b/drivers/gpu/drm/amd/pm/inc/smu73.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu73.h rename to drivers/gpu/drm/amd/pm/inc/smu73.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu73_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu73_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu74.h b/drivers/gpu/drm/amd/pm/inc/smu74.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu74.h rename to drivers/gpu/drm/amd/pm/inc/smu74.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu74_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu75.h b/drivers/gpu/drm/amd/pm/inc/smu75.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu75.h rename to drivers/gpu/drm/amd/pm/inc/smu75.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu75_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu75_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu75_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu75_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7_common.h b/drivers/gpu/drm/amd/pm/inc/smu7_common.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu7_common.h rename to drivers/gpu/drm/amd/pm/inc/smu7_common.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu7_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h rename to drivers/gpu/drm/amd/pm/inc/smu7_discrete.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h b/drivers/gpu/drm/amd/pm/inc/smu7_fusion.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h rename to drivers/gpu/drm/amd/pm/inc/smu7_fusion.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu8.h b/drivers/gpu/drm/amd/pm/inc/smu8.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu8.h rename to drivers/gpu/drm/amd/pm/inc/smu8.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h b/drivers/gpu/drm/amd/pm/inc/smu8_fusion.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h rename to drivers/gpu/drm/amd/pm/inc/smu8_fusion.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu9.h b/drivers/gpu/drm/amd/pm/inc/smu9.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu9.h rename to drivers/gpu/drm/amd/pm/inc/smu9.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h rename to drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_types.h rename to drivers/gpu/drm/amd/pm/inc/smu_types.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h rename to drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h b/drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h rename to drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h rename to drivers/gpu/drm/amd/pm/inc/smu_v11_0.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_pptable.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_pptable.h rename to drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h rename to drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v12_0.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h rename to drivers/gpu/drm/amd/pm/inc/smu_v12_0.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smu_v12_0_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/pm/inc/smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/smumgr.h rename to drivers/gpu/drm/amd/pm/inc/smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h b/drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h rename to drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h rename to drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/pm/powerplay/Makefile similarity index 70% rename from drivers/gpu/drm/amd/powerplay/Makefile rename to drivers/gpu/drm/amd/pm/powerplay/Makefile index e9c48f99f71b5..0fb114adc79f6 100644 --- a/drivers/gpu/drm/amd/powerplay/Makefile +++ b/drivers/gpu/drm/amd/pm/powerplay/Makefile @@ -1,5 +1,5 @@ # -# Copyright 2017 Advanced Micro Devices, Inc. +# Copyright 2020 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -20,25 +20,20 @@ # OTHER DEALINGS IN THE SOFTWARE. # -subdir-ccflags-y += \ - -I$(FULL_AMD_PATH)/powerplay/inc/ \ - -I$(FULL_AMD_PATH)/include/asic_reg \ - -I$(FULL_AMD_PATH)/include \ - -I$(FULL_AMD_PATH)/powerplay/smumgr\ - -I$(FULL_AMD_PATH)/powerplay/hwmgr - -AMD_PP_PATH = ../powerplay +AMD_PP_PATH = ../pm/powerplay PP_LIBS = smumgr hwmgr -AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/powerplay/,$(PP_LIBS))) +AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/,$(PP_LIBS))) include $(AMD_POWERPLAY) -POWER_MGR = amd_powerplay.o amdgpu_smu.o smu_v11_0.o \ - smu_v12_0.o arcturus_ppt.o navi10_ppt.o \ - renoir_ppt.o sienna_cichlid_ppt.o smu_cmn.o +POWER_MGR-y = amd_powerplay.o + +POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o + +POWER_MGR-$(CONFIG_DRM_AMDGPU_SI)+= si_dpm.o si_smc.o -AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR)) +AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR-y)) AMD_POWERPLAY_FILES += $(AMD_PP_POWER) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/amd_powerplay.c rename to drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c diff --git a/drivers/gpu/drm/amd/amdgpu/cik_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/cik_dpm.h rename to drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/Makefile rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h rename to drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/kv_dpm.c rename to drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/kv_dpm.h rename to drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/kv_smc.c b/drivers/gpu/drm/amd/pm/powerplay/kv_smc.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/kv_smc.c rename to drivers/gpu/drm/amd/pm/powerplay/kv_smc.c diff --git a/drivers/gpu/drm/amd/amdgpu/ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/ppsmc.h diff --git a/drivers/gpu/drm/amd/amdgpu/r600_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/r600_dpm.h rename to drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/si_dpm.c rename to drivers/gpu/drm/amd/pm/powerplay/si_dpm.c diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/si_dpm.h rename to drivers/gpu/drm/amd/pm/powerplay/si_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/pm/powerplay/si_smc.c similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/si_smc.c rename to drivers/gpu/drm/amd/pm/powerplay/si_smc.c diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h similarity index 100% rename from drivers/gpu/drm/amd/amdgpu/sislands_smc.h rename to drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/Makefile rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h diff --git a/drivers/gpu/drm/amd/pm/swsmu/Makefile b/drivers/gpu/drm/amd/pm/swsmu/Makefile new file mode 100644 index 0000000000000..6f281990b7b4b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/Makefile @@ -0,0 +1,36 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +AMD_SWSMU_PATH = ../pm/swsmu + +SWSMU_LIBS = smu11 smu12 + +AMD_SWSMU = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/swsmu/,$(SWSMU_LIBS))) + +include $(AMD_SWSMU) + +SWSMU_MGR = amdgpu_smu.o \ + smu_cmn.o \ + +AMD_SWSMU_POWER = $(addprefix $(AMD_SWSMU_PATH)/,$(SWSMU_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_POWER) diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/amdgpu_smu.c rename to drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile new file mode 100644 index 0000000000000..f98d97192635b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile @@ -0,0 +1,33 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU11_MGR = arcturus_ppt.o \ + navi10_ppt.o \ + sienna_cichlid_ppt.o \ + smu_v11_0.o + +AMD_SWSMU_SMU11MGR = $(addprefix $(AMD_SWSMU_PATH)/smu11/,$(SMU11_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_SMU11MGR) diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/arcturus_ppt.c rename to drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/arcturus_ppt.h rename to drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/navi10_ppt.c rename to drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/navi10_ppt.h rename to drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c rename to drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h rename to drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smu_v11_0.c rename to drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile new file mode 100644 index 0000000000000..67e53f7da3cea --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile @@ -0,0 +1,31 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU12_MGR = renoir_ppt.o \ + smu_v12_0.o + +AMD_SWSMU_SMU12MGR = $(addprefix $(AMD_SWSMU_PATH)/smu12/,$(SMU12_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_SMU12MGR) diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/renoir_ppt.c rename to drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/renoir_ppt.h rename to drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smu_v12_0.c rename to drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smu_cmn.c rename to drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smu_cmn.h rename to drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h similarity index 100% rename from drivers/gpu/drm/amd/powerplay/smu_internal.h rename to drivers/gpu/drm/amd/pm/swsmu/smu_internal.h -- GitLab From ac1128c99620ba8057fa82f2ca1264d0d54544d6 Mon Sep 17 00:00:00 2001 From: James Zhu <James.Zhu@amd.com> Date: Thu, 13 Aug 2020 09:57:31 -0400 Subject: [PATCH 0438/1494] drm/amdgpu/vcn3.0: only SIENNA_CICHLID need specify instance for dec/enc Only SIENNA_CICHLID(VCN3) has 2 unsymmetrical instances, there're less codecs on instance 1, we use 0 for decode and 1 for encode. Signed-off-by: James Zhu <James.Zhu@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 63e5547cfb16d..589d6cd8adec9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -198,7 +198,7 @@ static int vcn_v3_0_sw_init(void *handle) } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i; } - if (i != 0) + if (adev->asic_type == CHIP_SIENNA_CICHLID && i != 0) ring->no_scheduler = true; sprintf(ring->name, "vcn_dec_%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, @@ -222,7 +222,7 @@ static int vcn_v3_0_sw_init(void *handle) } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i; } - if (i != 1) + if (adev->asic_type == CHIP_SIENNA_CICHLID && i != 1) ring->no_scheduler = true; sprintf(ring->name, "vcn_enc_%d.%d", i, j); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, -- GitLab From 31e726ca3da9b126f162b51bb55647b1ffccbd48 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Tue, 28 Jul 2020 11:35:54 -0400 Subject: [PATCH 0439/1494] drm/amdgpu: parse ta firmware for navy_flounder Use the same case as sienna_cichlid Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index d488d250805d3..e16874f30d5dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -179,12 +179,11 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) } break; case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: err = psp_init_ta_microcode(&adev->psp, chip_name); if (err) return err; break; - case CHIP_NAVY_FLOUNDER: - break; default: BUG(); } -- GitLab From bddbacc9e0373fc1f1f7963fa2a7838dd06e4b1b Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 10 Aug 2020 17:09:17 -0400 Subject: [PATCH 0440/1494] drm/amdgpu: print where we get the vbios image from MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ACPI, ROM, PCI BAR, etc. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 28 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index b1172d93c99c3..6333cada1e096 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -417,26 +417,40 @@ static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) bool amdgpu_get_bios(struct amdgpu_device *adev) { - if (amdgpu_atrm_get_bios(adev)) + if (amdgpu_atrm_get_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ATRM\n"); goto success; + } - if (amdgpu_acpi_vfct_bios(adev)) + if (amdgpu_acpi_vfct_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from VFCT\n"); goto success; + } - if (igp_read_bios_from_vram(adev)) + if (igp_read_bios_from_vram(adev)) { + dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n"); goto success; + } - if (amdgpu_read_bios(adev)) + if (amdgpu_read_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); goto success; + } - if (amdgpu_read_bios_from_rom(adev)) + if (amdgpu_read_bios_from_rom(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM\n"); goto success; + } - if (amdgpu_read_disabled_bios(adev)) + if (amdgpu_read_disabled_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n"); goto success; + } - if (amdgpu_read_platform_bios(adev)) + if (amdgpu_read_platform_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from platform\n"); goto success; + } DRM_ERROR("Unable to locate a BIOS ROM\n"); return false; -- GitLab From 11043b7a995c18ea725c956825d1dfcbbdd8e78b Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 11 Aug 2020 12:02:21 -0400 Subject: [PATCH 0441/1494] drm/amdgpu: note what type of reset we are using When we reset the GPU, note what type of reset will be used. This makes debugging different reset scenarios more clear as the driver may use different reset methods depending on conditions on the system. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/cik.c | 2 ++ drivers/gpu/drm/amd/amdgpu/nv.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/si.c | 2 ++ drivers/gpu/drm/amd/amdgpu/soc15.c | 3 +++ drivers/gpu/drm/amd/amdgpu/vi.c | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index c2c67ab68a43b..7e71ffbca93d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1366,8 +1366,10 @@ static int cik_asic_reset(struct amdgpu_device *adev) int r; if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); } else { + dev_info(adev->dev, "PCI CONFIG reset\n"); r = cik_asic_pci_config_reset(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index da8024c2826ec..54e941e0db608 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -379,7 +379,7 @@ static int nv_asic_reset(struct amdgpu_device *adev) struct smu_context *smu = &adev->smu; if (nv_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { - dev_info(adev->dev, "GPU BACO reset\n"); + dev_info(adev->dev, "BACO reset\n"); ret = smu_baco_enter(smu); if (ret) @@ -387,8 +387,10 @@ static int nv_asic_reset(struct amdgpu_device *adev) ret = smu_baco_exit(smu); if (ret) return ret; - } else + } else { + dev_info(adev->dev, "MODE1 reset\n"); ret = nv_asic_mode1_reset(adev); + } return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index e330884edd196..eaa2f071b1394 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1302,6 +1302,8 @@ static int si_asic_reset(struct amdgpu_device *adev) { int r; + dev_info(adev->dev, "PCI CONFIG reset\n"); + amdgpu_atombios_scratch_regs_engine_hung(adev, true); r = si_gpu_pci_config_reset(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 84d811b6e48be..3cd98c144bc65 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -580,10 +580,13 @@ static int soc15_asic_reset(struct amdgpu_device *adev) switch (soc15_asic_reset_method(adev)) { case AMD_RESET_METHOD_BACO: + dev_info(adev->dev, "BACO reset\n"); return soc15_asic_baco_reset(adev); case AMD_RESET_METHOD_MODE2: + dev_info(adev->dev, "MODE2 reset\n"); return amdgpu_dpm_mode2_reset(adev); default: + dev_info(adev->dev, "MODE1 reset\n"); return soc15_asic_mode1_reset(adev); } } diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index b4e4a7a19d19e..a92880c678410 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -752,8 +752,10 @@ static int vi_asic_reset(struct amdgpu_device *adev) int r; if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); } else { + dev_info(adev->dev, "PCI CONFIG reset\n"); r = vi_asic_pci_config_reset(adev); } -- GitLab From 2a25ba97879f809e79642fca05178d4ee77f9f52 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 13 Aug 2020 00:23:22 -0400 Subject: [PATCH 0442/1494] drm/amdgpu: drop log message in amdgpu_dpm_baco_reset() The caller does this now for all reset types. This is now a duplicate call. Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index e480b54f65459..ca3fb32979d4d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1115,8 +1115,6 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) struct smu_context *smu = &adev->smu; int ret = 0; - dev_info(adev->dev, "GPU BACO reset\n"); - if (is_support_sw_smu(adev)) { ret = smu_baco_enter(smu); if (ret) -- GitLab From 72957f48aaaa4e62bff22af81b5d96ca6bd0f492 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Fri, 14 Aug 2020 21:44:51 +0200 Subject: [PATCH 0443/1494] drm/mcde: Retry DSI read/write transactions The vendor driver makes a few retries on read DSI transactions, something that is needed especially in case of read (such as reading the panel MTP ID) while the panel is running in video mode. This happens on the Samsung s6e63m0 panel on the Golden device. Retry reads and writes alike three times. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Stephan Gerhold <stephan@gerhold.net> Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200814194451.3494294-1-linus.walleij@linaro.org --- drivers/gpu/drm/mcde/mcde_dsi.c | 158 +++++++++++++++++++------------- 1 file changed, 92 insertions(+), 66 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index ae70f76bfb89a..2314c81229920 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -208,79 +208,16 @@ static int mcde_dsi_host_detach(struct mipi_dsi_host *host, (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ (type == MIPI_DSI_DCS_READ)) -static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, - const struct mipi_dsi_msg *msg) +static int mcde_dsi_execute_transfer(struct mcde_dsi *d, + const struct mipi_dsi_msg *msg) { - struct mcde_dsi *d = host_to_mcde_dsi(host); const u32 loop_delay_us = 10; /* us */ - const u8 *tx = msg->tx_buf; u32 loop_counter; size_t txlen = msg->tx_len; size_t rxlen = msg->rx_len; + int i; u32 val; int ret; - int i; - - if (txlen > 16) { - dev_err(d->dev, - "dunno how to write more than 16 bytes yet\n"); - return -EIO; - } - if (rxlen > 4) { - dev_err(d->dev, - "dunno how to read more than 4 bytes yet\n"); - return -EIO; - } - - dev_dbg(d->dev, - "message to channel %d, write %zd bytes read %zd bytes\n", - msg->channel, txlen, rxlen); - - /* Command "nature" */ - if (MCDE_DSI_HOST_IS_READ(msg->type)) - /* MCTL_MAIN_DATA_CTL already set up */ - val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ; - else - val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE; - /* - * More than 2 bytes will not fit in a single packet, so it's - * time to set the "long not short" bit. One byte is used by - * the MIPI DCS command leaving just one byte for the payload - * in a short package. - */ - if (mipi_dsi_packet_format_is_long(msg->type)) - val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT; - val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT; - val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT; - val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN; - val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT; - writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS); - - /* MIPI DCS command is part of the data */ - if (txlen > 0) { - val = 0; - for (i = 0; i < 4 && i < txlen; i++) - val |= tx[i] << (i * 8); - } - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0); - if (txlen > 4) { - val = 0; - for (i = 0; i < 4 && (i + 4) < txlen; i++) - val |= tx[i + 4] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1); - } - if (txlen > 8) { - val = 0; - for (i = 0; i < 4 && (i + 8) < txlen; i++) - val |= tx[i + 8] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2); - } - if (txlen > 12) { - val = 0; - for (i = 0; i < 4 && (i + 12) < txlen; i++) - val |= tx[i + 12] << (i * 8); - writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3); - } writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR); writel(~0, d->regs + DSI_CMD_MODE_STS_CLR); @@ -297,6 +234,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, usleep_range(loop_delay_us, (loop_delay_us * 3) / 2); if (!loop_counter) { dev_err(d->dev, "DSI read timeout!\n"); + /* Set exit code and retry */ return -ETIME; } } else { @@ -307,6 +245,7 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, usleep_range(loop_delay_us, (loop_delay_us * 3) / 2); if (!loop_counter) { + /* Set exit code and retry */ dev_err(d->dev, "DSI write timeout!\n"); return -ETIME; } @@ -348,6 +287,93 @@ static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, ret = rdsz; } + /* Successful transmission */ + return ret; +} + +static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct mcde_dsi *d = host_to_mcde_dsi(host); + const u8 *tx = msg->tx_buf; + size_t txlen = msg->tx_len; + size_t rxlen = msg->rx_len; + unsigned int retries = 0; + u32 val; + int ret; + int i; + + if (txlen > 16) { + dev_err(d->dev, + "dunno how to write more than 16 bytes yet\n"); + return -EIO; + } + if (rxlen > 4) { + dev_err(d->dev, + "dunno how to read more than 4 bytes yet\n"); + return -EIO; + } + + dev_dbg(d->dev, + "message to channel %d, write %zd bytes read %zd bytes\n", + msg->channel, txlen, rxlen); + + /* Command "nature" */ + if (MCDE_DSI_HOST_IS_READ(msg->type)) + /* MCTL_MAIN_DATA_CTL already set up */ + val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ; + else + val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE; + /* + * More than 2 bytes will not fit in a single packet, so it's + * time to set the "long not short" bit. One byte is used by + * the MIPI DCS command leaving just one byte for the payload + * in a short package. + */ + if (mipi_dsi_packet_format_is_long(msg->type)) + val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT; + val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT; + val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT; + val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN; + val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT; + writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS); + + /* MIPI DCS command is part of the data */ + if (txlen > 0) { + val = 0; + for (i = 0; i < 4 && i < txlen; i++) + val |= tx[i] << (i * 8); + } + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0); + if (txlen > 4) { + val = 0; + for (i = 0; i < 4 && (i + 4) < txlen; i++) + val |= tx[i + 4] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1); + } + if (txlen > 8) { + val = 0; + for (i = 0; i < 4 && (i + 8) < txlen; i++) + val |= tx[i + 8] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2); + } + if (txlen > 12) { + val = 0; + for (i = 0; i < 4 && (i + 12) < txlen; i++) + val |= tx[i + 12] << (i * 8); + writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3); + } + + while (retries < 3) { + ret = mcde_dsi_execute_transfer(d, msg); + if (ret >= 0) + break; + retries++; + } + if (ret < 0 && retries) + dev_err(d->dev, "gave up after %d retries\n", retries); + + /* Clear any errors */ writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR); writel(~0, d->regs + DSI_CMD_MODE_STS_CLR); -- GitLab From 5b44f125eff9df72336a12cf9839323dd7b70b74 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 11 Aug 2020 02:22:36 +0200 Subject: [PATCH 0444/1494] drm/panel: novatek,nt39016: Handle backlight the standard way Instead of manipulating the backlight directly in this driver, register it in the probe using drm_panel_of_backlight() and let the drm_panel framework code handle it. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200811002240.55194-2-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index 3d15d99252044..ba05165b60508 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -6,7 +6,6 @@ * Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net> */ -#include <linux/backlight.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/gpio/consumer.h> @@ -63,8 +62,6 @@ struct nt39016 { const struct nt39016_panel_info *panel_info; struct gpio_desc *reset_gpio; - - struct backlight_device *backlight; }; static inline struct nt39016 *to_nt39016(struct drm_panel *panel) @@ -180,14 +177,12 @@ static int nt39016_enable(struct drm_panel *drm_panel) return ret; } - if (panel->backlight) { + if (drm_panel->backlight) { /* Wait for the picture to be ready before enabling backlight */ msleep(150); - - ret = backlight_enable(panel->backlight); } - return ret; + return 0; } static int nt39016_disable(struct drm_panel *drm_panel) @@ -195,8 +190,6 @@ static int nt39016_disable(struct drm_panel *drm_panel) struct nt39016 *panel = to_nt39016(drm_panel); int err; - backlight_disable(panel->backlight); - err = regmap_write(panel->map, NT39016_REG_SYSTEM, NT39016_SYSTEM_RESET_N); if (err) { @@ -292,9 +285,8 @@ static int nt39016_probe(struct spi_device *spi) return PTR_ERR(panel->map); } - panel->backlight = devm_of_find_backlight(dev); - if (IS_ERR(panel->backlight)) { - err = PTR_ERR(panel->backlight); + err = drm_panel_of_backlight(&panel->drm_panel); + if (err) { if (err != -EPROBE_DEFER) dev_err(dev, "Failed to get backlight handle"); return err; -- GitLab From bdfd720fb25a0a1773d0554eaaa771596ffeffd8 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 11 Aug 2020 02:22:37 +0200 Subject: [PATCH 0445/1494] drm/panel: novatek,nt39016: Add missing CR to error messages If you pass a string that is not terminated with a carriage return to dev_err(), it will eventually be printed with a carriage return, but not right away, since the kernel will wait for a pr_cont(). Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200811002240.55194-3-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index ba05165b60508..39f7be679da53 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -124,7 +124,7 @@ static int nt39016_prepare(struct drm_panel *drm_panel) err = regulator_enable(panel->supply); if (err) { - dev_err(panel->dev, "Failed to enable power supply: %d", err); + dev_err(panel->dev, "Failed to enable power supply: %d\n", err); return err; } @@ -143,7 +143,7 @@ static int nt39016_prepare(struct drm_panel *drm_panel) err = regmap_multi_reg_write(panel->map, nt39016_panel_regs, ARRAY_SIZE(nt39016_panel_regs)); if (err) { - dev_err(panel->dev, "Failed to init registers: %d", err); + dev_err(panel->dev, "Failed to init registers: %d\n", err); goto err_disable_regulator; } @@ -173,7 +173,7 @@ static int nt39016_enable(struct drm_panel *drm_panel) ret = regmap_write(panel->map, NT39016_REG_SYSTEM, NT39016_SYSTEM_RESET_N | NT39016_SYSTEM_STANDBY); if (ret) { - dev_err(panel->dev, "Unable to enable panel: %d", ret); + dev_err(panel->dev, "Unable to enable panel: %d\n", ret); return ret; } @@ -193,7 +193,7 @@ static int nt39016_disable(struct drm_panel *drm_panel) err = regmap_write(panel->map, NT39016_REG_SYSTEM, NT39016_SYSTEM_RESET_N); if (err) { - dev_err(panel->dev, "Unable to disable panel: %d", err); + dev_err(panel->dev, "Unable to disable panel: %d\n", err); return err; } @@ -261,13 +261,13 @@ static int nt39016_probe(struct spi_device *spi) panel->supply = devm_regulator_get(dev, "power"); if (IS_ERR(panel->supply)) { - dev_err(dev, "Failed to get power supply"); + dev_err(dev, "Failed to get power supply\n"); return PTR_ERR(panel->supply); } panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(panel->reset_gpio)) { - dev_err(dev, "Failed to get reset GPIO"); + dev_err(dev, "Failed to get reset GPIO\n"); return PTR_ERR(panel->reset_gpio); } @@ -275,20 +275,20 @@ static int nt39016_probe(struct spi_device *spi) spi->mode = SPI_MODE_3 | SPI_3WIRE; err = spi_setup(spi); if (err) { - dev_err(dev, "Failed to setup SPI"); + dev_err(dev, "Failed to setup SPI\n"); return err; } panel->map = devm_regmap_init_spi(spi, &nt39016_regmap_config); if (IS_ERR(panel->map)) { - dev_err(dev, "Failed to init regmap"); + dev_err(dev, "Failed to init regmap\n"); return PTR_ERR(panel->map); } err = drm_panel_of_backlight(&panel->drm_panel); if (err) { if (err != -EPROBE_DEFER) - dev_err(dev, "Failed to get backlight handle"); + dev_err(dev, "Failed to get backlight handle\n"); return err; } -- GitLab From 656b759636738a9ddc235de4b152743c5b7788c4 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 11 Aug 2020 02:22:38 +0200 Subject: [PATCH 0446/1494] drm/panel: simple: Convert sharp,ls020b1dd01d from timings to videomode Convert the Sharp LS020B1DD01D panel entry from using a struct display_timing to using a struct drm_display_mode, as display_timing seems to be the old and legacy format. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200811002240.55194-4-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-simple.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index ef04fd75babd3..9c791d610f990 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3398,22 +3398,24 @@ static const struct panel_desc sharp_lq123p1jx31 = { }, }; -static const struct display_timing sharp_ls020b1dd01d_timing = { - .pixelclock = { 2000000, 4200000, 5000000 }, - .hactive = { 240, 240, 240 }, - .hfront_porch = { 66, 66, 66 }, - .hback_porch = { 1, 1, 1 }, - .hsync_len = { 1, 1, 1 }, - .vactive = { 160, 160, 160 }, - .vfront_porch = { 52, 52, 52 }, - .vback_porch = { 6, 6, 6 }, - .vsync_len = { 10, 10, 10 }, - .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW, +static const struct drm_display_mode sharp_ls020b1dd01d_modes[] = { + { /* 60 Hz */ + .clock = 4200, + .hdisplay = 240, + .hsync_start = 240 + 66, + .hsync_end = 240 + 66 + 1, + .htotal = 240 + 66 + 1 + 1, + .vdisplay = 160, + .vsync_start = 160 + 52, + .vsync_end = 160 + 52 + 10, + .vtotal = 160 + 52 + 10 + 6, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, + }, }; static const struct panel_desc sharp_ls020b1dd01d = { - .timings = &sharp_ls020b1dd01d_timing, - .num_timings = 1, + .modes = sharp_ls020b1dd01d_modes, + .num_modes = ARRAY_SIZE(sharp_ls020b1dd01d_modes), .bpc = 6, .size = { .width = 42, -- GitLab From c1bd32b5f6b55f101c1404a6abfa335dfb5408ef Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 11 Aug 2020 02:22:39 +0200 Subject: [PATCH 0447/1494] drm/panel: simple: Tweak timings of sharp,ls020b1dd01d for perfect 60Hz Modify the video mode in order to obtain a perfect 60.00 Hz frame rate using a 3 MHz pixel clock. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200811002240.55194-5-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-simple.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 9c791d610f990..1df8f1f1e6a04 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3400,15 +3400,15 @@ static const struct panel_desc sharp_lq123p1jx31 = { static const struct drm_display_mode sharp_ls020b1dd01d_modes[] = { { /* 60 Hz */ - .clock = 4200, + .clock = 3000, .hdisplay = 240, - .hsync_start = 240 + 66, - .hsync_end = 240 + 66 + 1, - .htotal = 240 + 66 + 1 + 1, + .hsync_start = 240 + 8, + .hsync_end = 240 + 8 + 1, + .htotal = 240 + 8 + 1 + 1, .vdisplay = 160, - .vsync_start = 160 + 52, - .vsync_end = 160 + 52 + 10, - .vtotal = 160 + 52 + 10 + 6, + .vsync_start = 160 + 24, + .vsync_end = 160 + 24 + 10, + .vtotal = 160 + 24 + 10 + 6, .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, }, }; -- GitLab From e6c21e6f9cf4ef7986ed1b885e869ee7c3b12fc3 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Tue, 11 Aug 2020 02:22:40 +0200 Subject: [PATCH 0448/1494] drm/panel: simple: Add 50Hz mode for sharp,ls020b1dd01d Add a perfect 50.00 Hz frame rate mode to the list of available modes for the Sharp LS020B1DD01D panel. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200811002240.55194-6-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-simple.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 1df8f1f1e6a04..6c8a9b5b67b02 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3399,6 +3399,18 @@ static const struct panel_desc sharp_lq123p1jx31 = { }; static const struct drm_display_mode sharp_ls020b1dd01d_modes[] = { + { /* 50 Hz */ + .clock = 3000, + .hdisplay = 240, + .hsync_start = 240 + 58, + .hsync_end = 240 + 58 + 1, + .htotal = 240 + 58 + 1 + 1, + .vdisplay = 160, + .vsync_start = 160 + 24, + .vsync_end = 160 + 24 + 10, + .vtotal = 160 + 24 + 10 + 6, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, + }, { /* 60 Hz */ .clock = 3000, .hdisplay = 240, -- GitLab From b7d71b6e1f039873e05b2d53f88200757316f931 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng <icenowy@aosc.io> Date: Mon, 20 Jul 2020 01:04:07 +0800 Subject: [PATCH 0449/1494] drm/panel: ilitek-ili9881c: prepare for adding support for extra panels There're more panels with ILI9881C controller than the Bananapi one supported by this driver. Extract the mode and init sequence part, to prepare the driver for adding new panels. Signed-off-by: Icenowy Zheng <icenowy@aosc.io> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200719170411.275812-2-icenowy@aosc.io --- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 066ef6c535df0..02ef2750bd776 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -10,6 +10,7 @@ #include <linux/fb.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> @@ -20,14 +21,6 @@ #include <video/mipi_display.h> -struct ili9881c { - struct drm_panel panel; - struct mipi_dsi_device *dsi; - - struct regulator *power; - struct gpio_desc *reset; -}; - enum ili9881c_op { ILI9881C_SWITCH_PAGE, ILI9881C_COMMAND, @@ -45,6 +38,21 @@ struct ili9881c_instr { } arg; }; +struct ili9881c_desc { + const struct ili9881c_instr *init; + const size_t init_length; + const struct drm_display_mode *mode; +}; + +struct ili9881c { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + const struct ili9881c_desc *desc; + + struct regulator *power; + struct gpio_desc *reset; +}; + #define ILI9881C_SWITCH_PAGE_INSTR(_page) \ { \ .op = ILI9881C_SWITCH_PAGE, \ @@ -64,7 +72,7 @@ struct ili9881c_instr { }, \ } -static const struct ili9881c_instr ili9881c_init[] = { +static const struct ili9881c_instr lhr050h41_init[] = { ILI9881C_SWITCH_PAGE_INSTR(3), ILI9881C_COMMAND_INSTR(0x01, 0x00), ILI9881C_COMMAND_INSTR(0x02, 0x00), @@ -311,8 +319,8 @@ static int ili9881c_prepare(struct drm_panel *panel) gpiod_set_value(ctx->reset, 0); msleep(20); - for (i = 0; i < ARRAY_SIZE(ili9881c_init); i++) { - const struct ili9881c_instr *instr = &ili9881c_init[i]; + for (i = 0; i < ctx->desc->init_length; i++) { + const struct ili9881c_instr *instr = &ctx->desc->init[i]; if (instr->op == ILI9881C_SWITCH_PAGE) ret = ili9881c_switch_page(ctx, instr->arg.page); @@ -368,7 +376,7 @@ static int ili9881c_unprepare(struct drm_panel *panel) return 0; } -static const struct drm_display_mode bananapi_default_mode = { +static const struct drm_display_mode lhr050h41_default_mode = { .clock = 62000, .hdisplay = 720, @@ -380,6 +388,9 @@ static const struct drm_display_mode bananapi_default_mode = { .vsync_start = 1280 + 10, .vsync_end = 1280 + 10 + 10, .vtotal = 1280 + 10 + 10 + 20, + + .width_mm = 62, + .height_mm = 110, }; static int ili9881c_get_modes(struct drm_panel *panel, @@ -388,12 +399,12 @@ static int ili9881c_get_modes(struct drm_panel *panel, struct ili9881c *ctx = panel_to_ili9881c(panel); struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->dev, &bananapi_default_mode); + mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); if (!mode) { dev_err(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n", - bananapi_default_mode.hdisplay, - bananapi_default_mode.vdisplay, - drm_mode_vrefresh(&bananapi_default_mode)); + ctx->desc->mode->hdisplay, + ctx->desc->mode->vdisplay, + drm_mode_vrefresh(ctx->desc->mode)); return -ENOMEM; } @@ -402,8 +413,8 @@ static int ili9881c_get_modes(struct drm_panel *panel, mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); - connector->display_info.width_mm = 62; - connector->display_info.height_mm = 110; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; return 1; } @@ -426,6 +437,7 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi) return -ENOMEM; mipi_dsi_set_drvdata(dsi, ctx); ctx->dsi = dsi; + ctx->desc = of_device_get_match_data(&dsi->dev); drm_panel_init(&ctx->panel, &dsi->dev, &ili9881c_funcs, DRM_MODE_CONNECTOR_DSI); @@ -465,8 +477,14 @@ static int ili9881c_dsi_remove(struct mipi_dsi_device *dsi) return 0; } +static const struct ili9881c_desc lhr050h41_desc = { + .init = lhr050h41_init, + .init_length = ARRAY_SIZE(lhr050h41_init), + .mode = &lhr050h41_default_mode, +}; + static const struct of_device_id ili9881c_of_match[] = { - { .compatible = "bananapi,lhr050h41" }, + { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc }, { } }; MODULE_DEVICE_TABLE(of, ili9881c_of_match); -- GitLab From 82df3aa4968c5a1a092990c499887fd0594a4004 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng <icenowy@aosc.io> Date: Mon, 20 Jul 2020 01:10:04 +0800 Subject: [PATCH 0450/1494] dt-bindings: ili9881c: add compatible string for Feixin K101-IM2BYL02 Feixin K101-IM2BYL02 is a drop-in replacement of K101-IM2BA02 panel (which is already supported by panel-feixin-k101-im2ba02 driver) with the same pinout. It utilizes an Ilitek ILI9881C controller chip, so its compatible string should be added to ilitek,ili9881c file. Add the compatible string for it. Signed-off-by: Icenowy Zheng <icenowy@aosc.io> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200719171007.276383-1-icenowy@aosc.io --- .../devicetree/bindings/display/panel/ilitek,ili9881c.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml index a39332276bab2..c60b3bd74337e 100644 --- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml +++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml @@ -14,6 +14,7 @@ properties: items: - enum: - bananapi,lhr050h41 + - feixin,k101-im2byl02 - const: ilitek,ili9881c -- GitLab From 1c243751c095bb95e2795f076ea7a0bcdd60a93a Mon Sep 17 00:00:00 2001 From: Icenowy Zheng <icenowy@aosc.io> Date: Mon, 20 Jul 2020 01:10:05 +0800 Subject: [PATCH 0451/1494] drm/panel: ilitek-ili9881c: add support for Feixin K101-IM2BYL02 panel Feixin K101-IM2BYL02 is a new panel by Feixin designed as a replacement to their K101-IM2BA02 panel. This panel utilizes the Ilitek ILI9881C controller. Add this panel's initialzation sequence and timing to ILI9881C driver. Signed-off-by: Icenowy Zheng <icenowy@aosc.io> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200719171007.276383-2-icenowy@aosc.io --- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index 02ef2750bd776..0145129d7c661 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -260,6 +260,199 @@ static const struct ili9881c_instr lhr050h41_init[] = { ILI9881C_COMMAND_INSTR(0xD3, 0x3F), }; +static const struct ili9881c_instr k101_im2byl02_init[] = { + ILI9881C_SWITCH_PAGE_INSTR(3), + ILI9881C_COMMAND_INSTR(0x01, 0x00), + ILI9881C_COMMAND_INSTR(0x02, 0x00), + ILI9881C_COMMAND_INSTR(0x03, 0x73), + ILI9881C_COMMAND_INSTR(0x04, 0x00), + ILI9881C_COMMAND_INSTR(0x05, 0x00), + ILI9881C_COMMAND_INSTR(0x06, 0x08), + ILI9881C_COMMAND_INSTR(0x07, 0x00), + ILI9881C_COMMAND_INSTR(0x08, 0x00), + ILI9881C_COMMAND_INSTR(0x09, 0x00), + ILI9881C_COMMAND_INSTR(0x0A, 0x01), + ILI9881C_COMMAND_INSTR(0x0B, 0x01), + ILI9881C_COMMAND_INSTR(0x0C, 0x00), + ILI9881C_COMMAND_INSTR(0x0D, 0x01), + ILI9881C_COMMAND_INSTR(0x0E, 0x01), + ILI9881C_COMMAND_INSTR(0x0F, 0x00), + ILI9881C_COMMAND_INSTR(0x10, 0x00), + ILI9881C_COMMAND_INSTR(0x11, 0x00), + ILI9881C_COMMAND_INSTR(0x12, 0x00), + ILI9881C_COMMAND_INSTR(0x13, 0x00), + ILI9881C_COMMAND_INSTR(0x14, 0x00), + ILI9881C_COMMAND_INSTR(0x15, 0x00), + ILI9881C_COMMAND_INSTR(0x16, 0x00), + ILI9881C_COMMAND_INSTR(0x17, 0x00), + ILI9881C_COMMAND_INSTR(0x18, 0x00), + ILI9881C_COMMAND_INSTR(0x19, 0x00), + ILI9881C_COMMAND_INSTR(0x1A, 0x00), + ILI9881C_COMMAND_INSTR(0x1B, 0x00), + ILI9881C_COMMAND_INSTR(0x1C, 0x00), + ILI9881C_COMMAND_INSTR(0x1D, 0x00), + ILI9881C_COMMAND_INSTR(0x1E, 0x40), + ILI9881C_COMMAND_INSTR(0x1F, 0xC0), + ILI9881C_COMMAND_INSTR(0x20, 0x06), + ILI9881C_COMMAND_INSTR(0x21, 0x01), + ILI9881C_COMMAND_INSTR(0x22, 0x06), + ILI9881C_COMMAND_INSTR(0x23, 0x01), + ILI9881C_COMMAND_INSTR(0x24, 0x88), + ILI9881C_COMMAND_INSTR(0x25, 0x88), + ILI9881C_COMMAND_INSTR(0x26, 0x00), + ILI9881C_COMMAND_INSTR(0x27, 0x00), + ILI9881C_COMMAND_INSTR(0x28, 0x3B), + ILI9881C_COMMAND_INSTR(0x29, 0x03), + ILI9881C_COMMAND_INSTR(0x2A, 0x00), + ILI9881C_COMMAND_INSTR(0x2B, 0x00), + ILI9881C_COMMAND_INSTR(0x2C, 0x00), + ILI9881C_COMMAND_INSTR(0x2D, 0x00), + ILI9881C_COMMAND_INSTR(0x2E, 0x00), + ILI9881C_COMMAND_INSTR(0x2F, 0x00), + ILI9881C_COMMAND_INSTR(0x30, 0x00), + ILI9881C_COMMAND_INSTR(0x31, 0x00), + ILI9881C_COMMAND_INSTR(0x32, 0x00), + ILI9881C_COMMAND_INSTR(0x33, 0x00), + ILI9881C_COMMAND_INSTR(0x34, 0x00), /* GPWR1/2 non overlap time 2.62us */ + ILI9881C_COMMAND_INSTR(0x35, 0x00), + ILI9881C_COMMAND_INSTR(0x36, 0x00), + ILI9881C_COMMAND_INSTR(0x37, 0x00), + ILI9881C_COMMAND_INSTR(0x38, 0x00), + ILI9881C_COMMAND_INSTR(0x39, 0x00), + ILI9881C_COMMAND_INSTR(0x3A, 0x00), + ILI9881C_COMMAND_INSTR(0x3B, 0x00), + ILI9881C_COMMAND_INSTR(0x3C, 0x00), + ILI9881C_COMMAND_INSTR(0x3D, 0x00), + ILI9881C_COMMAND_INSTR(0x3E, 0x00), + ILI9881C_COMMAND_INSTR(0x3F, 0x00), + ILI9881C_COMMAND_INSTR(0x40, 0x00), + ILI9881C_COMMAND_INSTR(0x41, 0x00), + ILI9881C_COMMAND_INSTR(0x42, 0x00), + ILI9881C_COMMAND_INSTR(0x43, 0x00), + ILI9881C_COMMAND_INSTR(0x44, 0x00), + ILI9881C_COMMAND_INSTR(0x50, 0x01), + ILI9881C_COMMAND_INSTR(0x51, 0x23), + ILI9881C_COMMAND_INSTR(0x52, 0x45), + ILI9881C_COMMAND_INSTR(0x53, 0x67), + ILI9881C_COMMAND_INSTR(0x54, 0x89), + ILI9881C_COMMAND_INSTR(0x55, 0xAB), + ILI9881C_COMMAND_INSTR(0x56, 0x01), + ILI9881C_COMMAND_INSTR(0x57, 0x23), + ILI9881C_COMMAND_INSTR(0x58, 0x45), + ILI9881C_COMMAND_INSTR(0x59, 0x67), + ILI9881C_COMMAND_INSTR(0x5A, 0x89), + ILI9881C_COMMAND_INSTR(0x5B, 0xAB), + ILI9881C_COMMAND_INSTR(0x5C, 0xCD), + ILI9881C_COMMAND_INSTR(0x5D, 0xEF), + ILI9881C_COMMAND_INSTR(0x5E, 0x00), + ILI9881C_COMMAND_INSTR(0x5F, 0x01), + ILI9881C_COMMAND_INSTR(0x60, 0x01), + ILI9881C_COMMAND_INSTR(0x61, 0x06), + ILI9881C_COMMAND_INSTR(0x62, 0x06), + ILI9881C_COMMAND_INSTR(0x63, 0x07), + ILI9881C_COMMAND_INSTR(0x64, 0x07), + ILI9881C_COMMAND_INSTR(0x65, 0x00), + ILI9881C_COMMAND_INSTR(0x66, 0x00), + ILI9881C_COMMAND_INSTR(0x67, 0x02), + ILI9881C_COMMAND_INSTR(0x68, 0x02), + ILI9881C_COMMAND_INSTR(0x69, 0x05), + ILI9881C_COMMAND_INSTR(0x6A, 0x05), + ILI9881C_COMMAND_INSTR(0x6B, 0x02), + ILI9881C_COMMAND_INSTR(0x6C, 0x0D), + ILI9881C_COMMAND_INSTR(0x6D, 0x0D), + ILI9881C_COMMAND_INSTR(0x6E, 0x0C), + ILI9881C_COMMAND_INSTR(0x6F, 0x0C), + ILI9881C_COMMAND_INSTR(0x70, 0x0F), + ILI9881C_COMMAND_INSTR(0x71, 0x0F), + ILI9881C_COMMAND_INSTR(0x72, 0x0E), + ILI9881C_COMMAND_INSTR(0x73, 0x0E), + ILI9881C_COMMAND_INSTR(0x74, 0x02), + ILI9881C_COMMAND_INSTR(0x75, 0x01), + ILI9881C_COMMAND_INSTR(0x76, 0x01), + ILI9881C_COMMAND_INSTR(0x77, 0x06), + ILI9881C_COMMAND_INSTR(0x78, 0x06), + ILI9881C_COMMAND_INSTR(0x79, 0x07), + ILI9881C_COMMAND_INSTR(0x7A, 0x07), + ILI9881C_COMMAND_INSTR(0x7B, 0x00), + ILI9881C_COMMAND_INSTR(0x7C, 0x00), + ILI9881C_COMMAND_INSTR(0x7D, 0x02), + ILI9881C_COMMAND_INSTR(0x7E, 0x02), + ILI9881C_COMMAND_INSTR(0x7F, 0x05), + ILI9881C_COMMAND_INSTR(0x80, 0x05), + ILI9881C_COMMAND_INSTR(0x81, 0x02), + ILI9881C_COMMAND_INSTR(0x82, 0x0D), + ILI9881C_COMMAND_INSTR(0x83, 0x0D), + ILI9881C_COMMAND_INSTR(0x84, 0x0C), + ILI9881C_COMMAND_INSTR(0x85, 0x0C), + ILI9881C_COMMAND_INSTR(0x86, 0x0F), + ILI9881C_COMMAND_INSTR(0x87, 0x0F), + ILI9881C_COMMAND_INSTR(0x88, 0x0E), + ILI9881C_COMMAND_INSTR(0x89, 0x0E), + ILI9881C_COMMAND_INSTR(0x8A, 0x02), + ILI9881C_SWITCH_PAGE_INSTR(4), + ILI9881C_COMMAND_INSTR(0x3B, 0xC0), /* ILI4003D sel */ + ILI9881C_COMMAND_INSTR(0x6C, 0x15), /* Set VCORE voltage = 1.5V */ + ILI9881C_COMMAND_INSTR(0x6E, 0x2A), /* di_pwr_reg=0 for power mode 2A, VGH clamp 18V */ + ILI9881C_COMMAND_INSTR(0x6F, 0x33), /* pumping ratio VGH=5x VGL=-3x */ + ILI9881C_COMMAND_INSTR(0x8D, 0x1B), /* VGL clamp -10V */ + ILI9881C_COMMAND_INSTR(0x87, 0xBA), /* ESD */ + ILI9881C_COMMAND_INSTR(0x3A, 0x24), /* POWER SAVING */ + ILI9881C_COMMAND_INSTR(0x26, 0x76), + ILI9881C_COMMAND_INSTR(0xB2, 0xD1), + ILI9881C_SWITCH_PAGE_INSTR(1), + ILI9881C_COMMAND_INSTR(0x22, 0x0A), /* BGR, SS */ + ILI9881C_COMMAND_INSTR(0x31, 0x00), /* Zigzag type3 inversion */ + ILI9881C_COMMAND_INSTR(0x40, 0x53), /* ILI4003D sel */ + ILI9881C_COMMAND_INSTR(0x43, 0x66), + ILI9881C_COMMAND_INSTR(0x53, 0x4C), + ILI9881C_COMMAND_INSTR(0x50, 0x87), + ILI9881C_COMMAND_INSTR(0x51, 0x82), + ILI9881C_COMMAND_INSTR(0x60, 0x15), + ILI9881C_COMMAND_INSTR(0x61, 0x01), + ILI9881C_COMMAND_INSTR(0x62, 0x0C), + ILI9881C_COMMAND_INSTR(0x63, 0x00), + ILI9881C_COMMAND_INSTR(0xA0, 0x00), + ILI9881C_COMMAND_INSTR(0xA1, 0x13), /* VP251 */ + ILI9881C_COMMAND_INSTR(0xA2, 0x23), /* VP247 */ + ILI9881C_COMMAND_INSTR(0xA3, 0x14), /* VP243 */ + ILI9881C_COMMAND_INSTR(0xA4, 0x16), /* VP239 */ + ILI9881C_COMMAND_INSTR(0xA5, 0x29), /* VP231 */ + ILI9881C_COMMAND_INSTR(0xA6, 0x1E), /* VP219 */ + ILI9881C_COMMAND_INSTR(0xA7, 0x1D), /* VP203 */ + ILI9881C_COMMAND_INSTR(0xA8, 0x86), /* VP175 */ + ILI9881C_COMMAND_INSTR(0xA9, 0x1E), /* VP144 */ + ILI9881C_COMMAND_INSTR(0xAA, 0x29), /* VP111 */ + ILI9881C_COMMAND_INSTR(0xAB, 0x74), /* VP80 */ + ILI9881C_COMMAND_INSTR(0xAC, 0x19), /* VP52 */ + ILI9881C_COMMAND_INSTR(0xAD, 0x17), /* VP36 */ + ILI9881C_COMMAND_INSTR(0xAE, 0x4B), /* VP24 */ + ILI9881C_COMMAND_INSTR(0xAF, 0x20), /* VP16 */ + ILI9881C_COMMAND_INSTR(0xB0, 0x26), /* VP12 */ + ILI9881C_COMMAND_INSTR(0xB1, 0x4C), /* VP8 */ + ILI9881C_COMMAND_INSTR(0xB2, 0x5D), /* VP4 */ + ILI9881C_COMMAND_INSTR(0xB3, 0x3F), /* VP0 */ + ILI9881C_COMMAND_INSTR(0xC0, 0x00), /* VN255 GAMMA N */ + ILI9881C_COMMAND_INSTR(0xC1, 0x13), /* VN251 */ + ILI9881C_COMMAND_INSTR(0xC2, 0x23), /* VN247 */ + ILI9881C_COMMAND_INSTR(0xC3, 0x14), /* VN243 */ + ILI9881C_COMMAND_INSTR(0xC4, 0x16), /* VN239 */ + ILI9881C_COMMAND_INSTR(0xC5, 0x29), /* VN231 */ + ILI9881C_COMMAND_INSTR(0xC6, 0x1E), /* VN219 */ + ILI9881C_COMMAND_INSTR(0xC7, 0x1D), /* VN203 */ + ILI9881C_COMMAND_INSTR(0xC8, 0x86), /* VN175 */ + ILI9881C_COMMAND_INSTR(0xC9, 0x1E), /* VN144 */ + ILI9881C_COMMAND_INSTR(0xCA, 0x29), /* VN111 */ + ILI9881C_COMMAND_INSTR(0xCB, 0x74), /* VN80 */ + ILI9881C_COMMAND_INSTR(0xCC, 0x19), /* VN52 */ + ILI9881C_COMMAND_INSTR(0xCD, 0x17), /* VN36 */ + ILI9881C_COMMAND_INSTR(0xCE, 0x4B), /* VN24 */ + ILI9881C_COMMAND_INSTR(0xCF, 0x20), /* VN16 */ + ILI9881C_COMMAND_INSTR(0xD0, 0x26), /* VN12 */ + ILI9881C_COMMAND_INSTR(0xD1, 0x4C), /* VN8 */ + ILI9881C_COMMAND_INSTR(0xD2, 0x5D), /* VN4 */ + ILI9881C_COMMAND_INSTR(0xD3, 0x3F), /* VN0 */ +}; + static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel) { return container_of(panel, struct ili9881c, panel); @@ -393,6 +586,23 @@ static const struct drm_display_mode lhr050h41_default_mode = { .height_mm = 110, }; +static const struct drm_display_mode k101_im2byl02_default_mode = { + .clock = 69700, + + .hdisplay = 800, + .hsync_start = 800 + 6, + .hsync_end = 800 + 6 + 15, + .htotal = 800 + 6 + 15 + 16, + + .vdisplay = 1280, + .vsync_start = 1280 + 8, + .vsync_end = 1280 + 8 + 48, + .vtotal = 1280 + 8 + 48 + 52, + + .width_mm = 135, + .height_mm = 217, +}; + static int ili9881c_get_modes(struct drm_panel *panel, struct drm_connector *connector) { @@ -483,8 +693,15 @@ static const struct ili9881c_desc lhr050h41_desc = { .mode = &lhr050h41_default_mode, }; +static const struct ili9881c_desc k101_im2byl02_desc = { + .init = k101_im2byl02_init, + .init_length = ARRAY_SIZE(k101_im2byl02_init), + .mode = &k101_im2byl02_default_mode, +}; + static const struct of_device_id ili9881c_of_match[] = { { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc }, + { .compatible = "feixin,k101-im2byl02", .data = &k101_im2byl02_desc }, { } }; MODULE_DEVICE_TABLE(of, ili9881c_of_match); -- GitLab From 5f3e7503b97b3d068304ac8bb74faa10b804b24d Mon Sep 17 00:00:00 2001 From: Derek Basehore <dbasehore@chromium.org> Date: Fri, 14 Aug 2020 00:56:06 +0300 Subject: [PATCH 0452/1494] drm/panel: Add helper for reading DT rotation This adds a helper function for reading the rotation (panel orientation) from the device tree. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Tested-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Derek Basehore <dbasehore@chromium.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200813215609.28643-2-digetx@gmail.com --- drivers/gpu/drm/drm_panel.c | 43 +++++++++++++++++++++++++++++++++++++ include/drm/drm_panel.h | 10 +++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index ba11c3641bf37..f634371c717a8 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -260,6 +260,49 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) return ERR_PTR(-EPROBE_DEFER); } EXPORT_SYMBOL(of_drm_find_panel); + +/** + * of_drm_get_panel_orientation - look up the orientation of the panel through + * the "rotation" binding from a device tree node + * @np: device tree node of the panel + * @orientation: orientation enum to be filled in + * + * Looks up the rotation of a panel in the device tree. The orientation of the + * panel is expressed as a property name "rotation" in the device tree. The + * rotation in the device tree is counter clockwise. + * + * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the + * rotation property doesn't exist. Return a negative error code on failure. + */ +int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + int rotation, ret; + + ret = of_property_read_u32(np, "rotation", &rotation); + if (ret == -EINVAL) { + /* Don't return an error if there's no rotation property. */ + *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + return 0; + } + + if (ret < 0) + return ret; + + if (rotation == 0) + *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (rotation == 90) + *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else if (rotation == 180) + *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (rotation == 270) + *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(of_drm_get_panel_orientation); #endif #if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 45a1b5a2275db..33605c3f0ebaa 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -35,6 +35,8 @@ struct drm_device; struct drm_panel; struct display_timing; +enum drm_panel_orientation; + /** * struct drm_panel_funcs - perform operations on a given panel * @@ -188,11 +190,19 @@ int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); +int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation); #else static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) { return ERR_PTR(-ENODEV); } + +static inline int of_drm_get_panel_orientation(const struct device_node *np, + enum drm_panel_orientation *orientation) +{ + return -ENODEV; +} #endif #if IS_ENABLED(CONFIG_DRM_PANEL) && (IS_BUILTIN(CONFIG_BACKLIGHT_CLASS_DEVICE) || \ -- GitLab From 4a135d54410f11041baa92d8709a9fd16be5cab9 Mon Sep 17 00:00:00 2001 From: Derek Basehore <dbasehore@chromium.org> Date: Fri, 14 Aug 2020 00:56:07 +0300 Subject: [PATCH 0453/1494] drm/panel: Read panel orientation for BOE TV101WUM-NL6 This reads the DT setting for the panel rotation to set the panel orientation in the get_modes callback. Reviewed-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Derek Basehore <dbasehore@chromium.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200813215609.28643-3-digetx@gmail.com --- drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index c9729fdd51ab8..db9d0b86d5428 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -11,6 +11,7 @@ #include <linux/of_device.h> #include <linux/regulator/consumer.h> +#include <drm/drm_connector.h> #include <drm/drm_crtc.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> @@ -43,6 +44,7 @@ struct boe_panel { const struct panel_desc *desc; + enum drm_panel_orientation orientation; struct regulator *pp1800; struct regulator *avee; struct regulator *avdd; @@ -740,6 +742,7 @@ static int boe_panel_get_modes(struct drm_panel *panel, connector->display_info.width_mm = boe->desc->size.width_mm; connector->display_info.height_mm = boe->desc->size.height_mm; connector->display_info.bpc = boe->desc->bpc; + drm_connector_set_panel_orientation(connector, boe->orientation); return 1; } @@ -779,6 +782,11 @@ static int boe_panel_add(struct boe_panel *boe) drm_panel_init(&boe->base, dev, &boe_panel_funcs, DRM_MODE_CONNECTOR_DSI); + err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation); + if (err < 0) { + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err); + return err; + } err = drm_panel_of_backlight(&boe->base); if (err) -- GitLab From 58310c2ec9941ff4e2582764e8ab3ee9620ccd2c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 00:56:08 +0300 Subject: [PATCH 0454/1494] drm/panel: lvds: Read panel orientation The panel orientation needs to parsed from a device-tree and assigned to the panel's connector in order to make orientation property available to userspace. That's what this patch does for the generic LVDS panel. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200813215609.28643-4-digetx@gmail.com --- drivers/gpu/drm/panel/panel-lvds.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index 41305c3dcf318..66c7d765b8f78 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -37,6 +37,8 @@ struct panel_lvds { struct gpio_desc *enable_gpio; struct gpio_desc *reset_gpio; + + enum drm_panel_orientation orientation; }; static inline struct panel_lvds *to_panel_lvds(struct drm_panel *panel) @@ -99,6 +101,7 @@ static int panel_lvds_get_modes(struct drm_panel *panel, connector->display_info.bus_flags = lvds->data_mirror ? DRM_BUS_FLAG_DATA_LSB_TO_MSB : DRM_BUS_FLAG_DATA_MSB_TO_LSB; + drm_connector_set_panel_orientation(connector, lvds->orientation); return 1; } @@ -116,6 +119,12 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) const char *mapping; int ret; + ret = of_drm_get_panel_orientation(np, &lvds->orientation); + if (ret < 0) { + dev_err(lvds->dev, "%pOF: failed to get orientation %d\n", np, ret); + return ret; + } + ret = of_get_display_timing(np, "panel-timing", &timing); if (ret < 0) { dev_err(lvds->dev, "%pOF: problems parsing panel-timing (%d)\n", -- GitLab From 5759c9674c20ffdb2c02c29fe85462732d86ed78 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 00:56:09 +0300 Subject: [PATCH 0455/1494] drm/panel-simple: Read panel orientation The panel orientation needs to parsed from a device-tree and assigned to the panel's connector in order to make orientation property available to userspace. That's what this patch does for the panel-simple driver. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200813215609.28643-5-digetx@gmail.com --- drivers/gpu/drm/panel/panel-simple.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 6c8a9b5b67b02..4eabfdd3be2d7 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -112,6 +112,8 @@ struct panel_simple { struct gpio_desc *hpd_gpio; struct drm_display_mode override_mode; + + enum drm_panel_orientation orientation; }; static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) @@ -371,6 +373,9 @@ static int panel_simple_get_modes(struct drm_panel *panel, /* add hard-coded panel modes */ num += panel_simple_get_non_edid_modes(p, connector); + /* set up connector's "panel orientation" property */ + drm_connector_set_panel_orientation(connector, p->orientation); + return num; } @@ -532,6 +537,12 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) return err; } + err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation); + if (err) { + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err); + return err; + } + ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); if (ddc) { panel->ddc = of_find_i2c_adapter_by_node(ddc); -- GitLab From 087e3d479155a18ff57f294c04e33c5ac7d6f50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> Date: Sun, 16 Aug 2020 09:13:42 +0200 Subject: [PATCH 0456/1494] dt-bindings: panel: rocktech,jh057n00900: Modernize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use common properties from panel-common.yaml - Indent comment like content - Don't preserve newlines in description - Indent example by four spaces Signed-off-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/60639e670028af7e8ab31379256ba331a1bdf6cc.1597561897.git.agx@sigxcpu.org --- .../display/panel/rocktech,jh057n00900.yaml | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml index d5733ef309549..c97e89707342e 100644 --- a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml +++ b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml @@ -9,9 +9,9 @@ title: Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel maintainers: - Ondrej Jirman <megi@xff.cz> -description: | - Rocktech JH057N00900 is a 720x1440 TFT LCD panel - connected using a MIPI-DSI video interface. +description: + Rocktech JH057N00900 is a 720x1440 TFT LCD panel + connected using a MIPI-DSI video interface. allOf: - $ref: panel-common.yaml# @@ -19,9 +19,9 @@ allOf: properties: compatible: enum: - # Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel + # Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel - rocktech,jh057n00900 - # Xingbangda XBD599 5.99" 720x1440 TFT LCD panel + # Xingbangda XBD599 5.99" 720x1440 TFT LCD panel - xingbangda,xbd599 port: true @@ -35,13 +35,9 @@ properties: iovcc-supply: description: I/O voltage supply - reset-gpios: - description: GPIO used for the reset pin - maxItems: 1 + reset-gpios: true - backlight: - description: Backlight used by the panel - $ref: "/schemas/types.yaml#/definitions/phandle" + backlight: true required: - compatible @@ -57,15 +53,16 @@ examples: #include <dt-bindings/gpio/gpio.h> dsi { - #address-cells = <1>; - #size-cells = <0>; - panel@0 { - compatible = "rocktech,jh057n00900"; - reg = <0>; - vcc-supply = <®_2v8_p>; - iovcc-supply = <®_1v8_p>; - reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>; - backlight = <&backlight>; - }; + #address-cells = <1>; + #size-cells = <0>; + panel@0 { + compatible = "rocktech,jh057n00900"; + reg = <0>; + vcc-supply = <®_2v8_p>; + iovcc-supply = <®_1v8_p>; + reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>; + backlight = <&backlight>; + }; }; + ... -- GitLab From 5f374e63d214a1e1cfaff9575fa34f27b046d54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> Date: Sun, 16 Aug 2020 09:13:43 +0200 Subject: [PATCH 0457/1494] dt-bindings: panel: rocktech,jh057n00900: Add myself as maintainer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I maintained the txt based bindings before yaml conversion and care about the driver. Signed-off-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/9427a9c0e6aaf9fb375f7ecee6691ba491149d52.1597561897.git.agx@sigxcpu.org --- .../devicetree/bindings/display/panel/rocktech,jh057n00900.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml index c97e89707342e..09b5eb7542f8a 100644 --- a/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml +++ b/Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml @@ -8,6 +8,7 @@ title: Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel maintainers: - Ondrej Jirman <megi@xff.cz> + - Guido GÅnther <agx@sigxcpu.org> description: Rocktech JH057N00900 is a 720x1440 TFT LCD panel -- GitLab From d4c5c2f331199aad3ff5d952de4dc4e28fa6beec Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 1 Jul 2020 14:41:54 +0100 Subject: [PATCH 0458/1494] drm/virtgpu: remove redundant assignments to width and height Variables width and height are being assigned values that are never read. The assignments are redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King <colin.king@canonical.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200701134154.549112-1-colin.king@canonical.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index af55b334be2fd..2c2742b8d6570 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -165,8 +165,6 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); if (width == 0 || height == 0) { - width = XRES_DEF; - height = YRES_DEF; drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); } else { DRM_DEBUG("add mode: %dx%d\n", width, height); -- GitLab From 51c3b0cc32d2e17581fce5b487ee95bbe9e8270a Mon Sep 17 00:00:00 2001 From: Gurchetan Singh <gurchetansingh@chromium.org> Date: Mon, 15 Jun 2020 16:05:00 -0700 Subject: [PATCH 0459/1494] drm/virtio: Revert "drm/virtio: Call the right shmem helpers" This reverts commit d323bb44e4d23802eb25d13de1f93f2335bd60d0. Fixes a double-free regression: [ 4.357928] drm_gem_shmem_free_object+0xb4/0x100 [ 4.358983] virtio_gpu_dequeue_ctrl_func+0xd9/0x290 [ 4.360343] process_one_work+0x1d2/0x3a0 [ 4.361581] worker_thread+0x45/0x3c0 [ 4.362645] kthread+0xf6/0x130 [ 4.363543] ? process_one_work+0x3a0/0x3a0 [ 4.364770] ? kthread_park+0x80/0x80 [ 4.365799] ret_from_fork+0x35/0x40 [ 4.367103] Modules linked in: [ 4.367958] CR2: 0000000000000018 [ 4.368857] ---[ end trace db84f7a2974d5c79 ]--- [ 4.370118] RIP: 0010:dma_direct_unmap_sg+0x1f/0x60 In addition, virtio has it's own set of dma-ops so there's not an obviously clean way to transition to shmem helpers. Fixes: d323bb44e4d2 ("drm/virtio: Call the right shmem helpers") Signed-off-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200615230500.551-1-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_object.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 346cef5ce2517..1359eb8f1a022 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -150,7 +150,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, if (ret < 0) return -EINVAL; - shmem->pages = drm_gem_shmem_get_pages_sgt(&bo->base.base); + /* + * virtio_gpu uses drm_gem_shmem_get_sg_table instead of + * drm_gem_shmem_get_pages_sgt because virtio has it's own set of + * dma-ops. This is discouraged for other drivers, but should be fine + * since virtio_gpu doesn't support dma-buf import from other devices. + */ + shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base); if (!shmem->pages) { drm_gem_shmem_unpin(&bo->base.base); return -EINVAL; -- GitLab From 66c8ef900611166f7a8a343172b1b38d21ecba61 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Fri, 7 Aug 2020 12:55:01 +0200 Subject: [PATCH 0460/1494] drm/qxl: don't take vga ports on rev5+ qemu 5.0 introduces a new qxl hardware revision 5. Unlike revision 4 (and below) the device doesn't switch back into vga compatibility mode when someone touches the vga ports. So we don't have to reserve the vga ports any more to avoid that happening. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20200807105501.24599-1-kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 13872b882775d..6e7f16f4cec79 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -96,7 +96,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto disable_pci; - if (is_vga(pdev)) { + if (is_vga(pdev) && pdev->revision < 5) { ret = vga_get_interruptible(pdev, VGA_RSRC_LEGACY_IO); if (ret) { DRM_ERROR("can't get legacy vga ioports\n"); @@ -127,7 +127,7 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) unload: qxl_device_fini(qdev); put_vga: - if (is_vga(pdev)) + if (is_vga(pdev) && pdev->revision < 5) vga_put(pdev, VGA_RSRC_LEGACY_IO); disable_pci: pci_disable_device(pdev); @@ -155,7 +155,7 @@ qxl_pci_remove(struct pci_dev *pdev) drm_dev_unregister(dev); drm_atomic_helper_shutdown(dev); - if (is_vga(pdev)) + if (is_vga(pdev) && pdev->revision < 5) vga_put(pdev, VGA_RSRC_LEGACY_IO); } -- GitLab From 77cf3a6827fe04e894ff0fbe8abc6a73795f8a92 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" <gustavoars@kernel.org> Date: Wed, 17 Jun 2020 16:57:07 -0500 Subject: [PATCH 0461/1494] drm/virtio: Use struct_size() helper in kmalloc() Make use of the struct_size() helper instead of an open-coded version in order to avoid any potential type mistakes. This code was detected with the help of Coccinelle and, audited and fixed manually. Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200617215707.GA16785@embeddedor Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_gem.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 24ffacac99e4c..c30c75ee83fce 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -154,9 +154,8 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj, struct virtio_gpu_object_array *virtio_gpu_array_alloc(u32 nents) { struct virtio_gpu_object_array *objs; - size_t size = sizeof(*objs) + sizeof(objs->objs[0]) * nents; - objs = kmalloc(size, GFP_KERNEL); + objs = kmalloc(struct_size(objs, objs, nents), GFP_KERNEL); if (!objs) return NULL; -- GitLab From bbaac1354cc98415e5b4c3830d796c583ca71907 Mon Sep 17 00:00:00 2001 From: Sidong Yang <realwakka@gmail.com> Date: Sun, 24 May 2020 11:26:23 +0900 Subject: [PATCH 0462/1494] drm/qxl: Replace deprecated function in qxl_display Replace deprecated function drm_modeset_lock/unlock_all with helper function DRM_MODESET_LOCK_ALL_BEGIN/END. Signed-off-by: Sidong Yang <realwakka@gmail.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200524022624.10363-1-realwakka@gmail.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/qxl/qxl_display.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 099dca48b0ff3..fa79688013b7d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -162,7 +162,8 @@ static void qxl_update_offset_props(struct qxl_device *qdev) void qxl_display_read_client_monitors_config(struct qxl_device *qdev) { struct drm_device *dev = &qdev->ddev; - int status, retries; + struct drm_modeset_acquire_ctx ctx; + int status, retries, ret; for (retries = 0; retries < 10; retries++) { status = qxl_display_copy_rom_client_monitors_config(qdev); @@ -183,9 +184,9 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev) return; } - drm_modeset_lock_all(dev); + DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); qxl_update_offset_props(qdev); - drm_modeset_unlock_all(dev); + DRM_MODESET_LOCK_ALL_END(ctx, ret); if (!drm_helper_hpd_irq_event(dev)) { /* notify that the monitor configuration changed, to adjust at the arbitrary resolution */ @@ -403,18 +404,17 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, struct qxl_device *qdev = to_qxl(fb->dev); struct drm_clip_rect norect; struct qxl_bo *qobj; + struct drm_modeset_acquire_ctx ctx; bool is_primary; - int inc = 1; + int inc = 1, ret; - drm_modeset_lock_all(fb->dev); + DRM_MODESET_LOCK_ALL_BEGIN(fb->dev, ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); qobj = gem_to_qxl_bo(fb->obj[0]); /* if we aren't primary surface ignore this */ is_primary = qobj->shadow ? qobj->shadow->is_primary : qobj->is_primary; - if (!is_primary) { - drm_modeset_unlock_all(fb->dev); - return 0; - } + if (!is_primary) + goto out_lock_end; if (!num_clips) { num_clips = 1; @@ -430,7 +430,8 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, qxl_draw_dirty_fb(qdev, fb, qobj, flags, color, clips, num_clips, inc, 0); - drm_modeset_unlock_all(fb->dev); +out_lock_end: + DRM_MODESET_LOCK_ALL_END(ctx, ret); return 0; } -- GitLab From d95c42a150d01e28830e0f597bc126a20db8fd0b Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 11 Aug 2020 13:54:56 +0800 Subject: [PATCH 0463/1494] drm/amdkfd: fix the wrong sdma instance query for renoir Renoir only has one sdma instance, it will get failed once query the sdma1 registers. So use switch-case instead of static register array. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index e4c274bd35c8c..a755f63514e15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -195,19 +195,32 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, unsigned int engine_id, unsigned int queue_id) { - uint32_t sdma_engine_reg_base[2] = { - SOC15_REG_OFFSET(SDMA0, 0, - mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL, - SOC15_REG_OFFSET(SDMA1, 0, - mmSDMA1_RLC0_RB_CNTL) - mmSDMA1_RLC0_RB_CNTL - }; - uint32_t retval = sdma_engine_reg_base[engine_id] + uint32_t sdma_engine_reg_base = 0; + uint32_t sdma_rlc_reg_offset; + + switch (engine_id) { + default: + dev_warn(adev->dev, + "Invalid sdma engine id (%d), using engine id 0\n", + engine_id); + fallthrough; + case 0: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0, + mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + case 1: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA1, 0, + mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + } + + sdma_rlc_reg_offset = sdma_engine_reg_base + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL); pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id, - queue_id, retval); + queue_id, sdma_rlc_reg_offset); - return retval; + return sdma_rlc_reg_offset; } static inline struct v9_mqd *get_mqd(void *mqd) -- GitLab From 736b17297857cf533649a4161d1369e3cde0d922 Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevin1.wang@amd.com> Date: Mon, 17 Aug 2020 14:55:11 +0800 Subject: [PATCH 0464/1494] drm/amdgpu: fix amdgpu_bo_release_notify() comment error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix amdgpu_bo_release_notify() comment error. Signed-off-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index a3cf38d25fc15..3080b56441211 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1302,7 +1302,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, } /** - * amdgpu_bo_move_notify - notification about a BO being released + * amdgpu_bo_release_notify - notification about a BO being released * @bo: pointer to a buffer object * * Wipes VRAM buffers whose contents should not be leaked before the -- GitLab From 4444457450fa66860fca856c6dd20f7acde80efa Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevin1.wang@amd.com> Date: Mon, 17 Aug 2020 16:57:20 +0800 Subject: [PATCH 0465/1494] drm/amdgpu: add condition check for trace_amdgpu_cs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1: add trace event enabled check to avoid nop loop when submit multi ibs in amdgpu_cs_ioctl() function. v2: add a new wrapper function to trace all amdgpu cs ibs. Signed-off-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a512ccbc4deae..10c0779aba731 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1275,13 +1275,24 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, return r; } +static void trace_amdgpu_cs_ibs(struct amdgpu_cs_parser *parser) +{ + int i; + + if (!trace_amdgpu_cs_enabled()) + return; + + for (i = 0; i < parser->job->num_ibs; i++) + trace_amdgpu_cs(parser, i); +} + int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser parser = {}; bool reserved_buffers = false; - int i, r; + int r; if (amdgpu_ras_intr_triggered()) return -EHWPOISON; @@ -1319,8 +1330,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) reserved_buffers = true; - for (i = 0; i < parser.job->num_ibs; i++) - trace_amdgpu_cs(&parser, i); + trace_amdgpu_cs_ibs(&parser); r = amdgpu_cs_vm_handling(&parser); if (r) -- GitLab From 45083ed24b8df3b43ce17c5598b6304a044659e6 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Mon, 3 Aug 2020 16:11:44 -0400 Subject: [PATCH 0466/1494] drm/amd/display: [FW Promotion] Release 0.0.28 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 55717ae4724d3..b58ed6538eab2 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xd7f4bb6ee +#define DMUB_FW_VERSION_GIT_HASH 0x3f7e3738b #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 27 +#define DMUB_FW_VERSION_REVISION 28 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 -- GitLab From 1ffe92021e6cd27ee9ccc30012a57d8a4868e28f Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Mon, 3 Aug 2020 16:12:58 -0400 Subject: [PATCH 0467/1494] drm/amd/display: 3.2.98 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6d4cab948607c..772b3a6477008 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.97" +#define DC_VER "3.2.98" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 8a0e210c048e97f950c674840e281e378de08373 Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Wed, 5 Aug 2020 13:46:40 -0400 Subject: [PATCH 0468/1494] drm/amd/display: Call DMUB for eDP power control [Why] If DMUB is used, LVTMA VBIOS call can be used to control eDP instead of tranditional transmitter control. Interface is agreed with VBIOS for eDP to use this new path to program LVTMA registers. [How] Create DAL interface to send DMUB command for LVTMA as currently implemented in VBIOS. Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/bios/bios_parser2.c | 16 ++++++++++- .../drm/amd/display/dc/bios/command_table2.c | 28 +++++++++++++++++++ .../drm/amd/display/dc/bios/command_table2.h | 3 +- .../gpu/drm/amd/display/dc/dc_bios_types.h | 4 +++ .../display/dc/dce110/dce110_hw_sequencer.c | 24 ++++++++++++++++ .../amd/display/include/bios_parser_types.h | 7 +++++ 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 078b7e3441855..2d5c7daaee231 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1108,6 +1108,18 @@ static enum bp_result bios_parser_enable_disp_power_gating( action); } +static enum bp_result bios_parser_enable_lvtma_control( + struct dc_bios *dcb, + uint8_t uc_pwr_on) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_lvtma_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on); +} + static bool bios_parser_is_accelerated_mode( struct dc_bios *dcb) { @@ -2208,7 +2220,9 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_board_layout_info = bios_get_board_layout_info, .pack_data_tables = bios_parser_pack_data_tables, - .get_atom_dc_golden_table = bios_get_atom_dc_golden_table + .get_atom_dc_golden_table = bios_get_atom_dc_golden_table, + + .enable_lvtma_control = bios_parser_enable_lvtma_control }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index e8f52eb8ef0d8..a91d7be5d86e0 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -901,6 +901,33 @@ static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id) return 0; } +/****************************************************************************** + ****************************************************************************** + ** + ** LVTMA CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on); + +static void init_enable_lvtma_control(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control; + +} + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on) +{ + enum bp_result result = BP_RESULT_FAILURE; + return result; +} + void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) { init_dig_encoder_control(bp); @@ -916,4 +943,5 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_set_dce_clock(bp); init_get_smu_clock_info(bp); + init_enable_lvtma_control(bp); } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h index 7a2af24dfe605..7bdce013cde5a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -94,7 +94,8 @@ struct cmd_tbl { struct bp_set_dce_clock_parameters *bp_params); unsigned int (*get_smu_clock_info)( struct bios_parser *bp, uint8_t id); - + enum bp_result (*enable_lvtma_control)(struct bios_parser *bp, + uint8_t uc_pwr_on); }; void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index d06d07042a120..0811f941f4304 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -136,6 +136,10 @@ struct dc_vbios_funcs { enum bp_result (*get_atom_dc_golden_table)( struct dc_bios *dcb); + + enum bp_result (*enable_lvtma_control)( + struct dc_bios *bios, + uint8_t uc_pwr_on); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 49380ed3aeae1..45c9e90278862 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -842,6 +842,17 @@ void dce110_edp_power_control( cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; cntl.hpd_sel = link->link_enc->hpd_source; + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_POWER_ON) + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_ON); + else + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_OFF); + } + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); if (!power_up) @@ -919,8 +930,21 @@ void dce110_edp_backlight_control( /*edp 1.2*/ if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) edp_receiver_ready_T7(link); + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLON); + else + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLOFF); + } + link_transmitter_control(ctx->dc_bios, &cntl); + + if (enable && link->dpcd_sink_ext_caps.bits.oled) msleep(OLED_POST_T7_DELAY); diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index c30437ae83953..21011edea337b 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -101,6 +101,13 @@ enum bp_pipe_control_action { ASIC_PIPE_INIT }; +enum bp_lvtma_control_action { + LVTMA_CONTROL_LCD_BLOFF = 2, + LVTMA_CONTROL_LCD_BLON = 3, + LVTMA_CONTROL_POWER_ON = 12, + LVTMA_CONTROL_POWER_OFF = 13 +}; + struct bp_encoder_control { enum bp_encoder_control_action action; enum engine_id engine_id; -- GitLab From 5a7c86e168b4b3229945f792ba0ea04c5236521f Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Wed, 5 Aug 2020 16:59:28 -0400 Subject: [PATCH 0469/1494] drm/amd/display: Assign correct left shift [Why] Reading for DP alt registers return incorrect values due to LE_SF definition missing. [How] Define correct LE_SF or DP alt registers. Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 4 +++- .../gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index bf0044f7417ec..dcbf28dd72d4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -167,7 +167,9 @@ LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh) + LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) #define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 8e9fd59ccde82..2fbf879cd327e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -61,7 +61,10 @@ DPCS_DCN2_MASK_SH_LIST(mask_sh),\ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh) + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + void dcn30_link_encoder_construct( struct dcn20_link_encoder *enc20, -- GitLab From c08321cb181d5677dedec276f9a11990f27c8d99 Mon Sep 17 00:00:00 2001 From: Wenjing Liu <wenjing.liu@amd.com> Date: Thu, 9 Jul 2020 17:08:50 -0400 Subject: [PATCH 0470/1494] drm/amd/display: create a function to decide mst link settings [why] create a dedicated function to make mst link settings decision, so that the policy's decision is made in a unified place. Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 9bc03f26efdaf..2319299325160 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2431,6 +2431,12 @@ static bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settin return false; } +static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting) +{ + *link_setting = link->verified_link_cap; + return true; +} + void decide_link_settings(struct dc_stream_state *stream, struct dc_link_settings *link_setting) { @@ -2456,11 +2462,9 @@ void decide_link_settings(struct dc_stream_state *stream, * TODO: add MST specific link training routine */ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - *link_setting = link->verified_link_cap; - return; - } - - if (link->connector_signal == SIGNAL_TYPE_EDP) { + if (decide_mst_link_settings(link, link_setting)) + return; + } else if (link->connector_signal == SIGNAL_TYPE_EDP) { if (decide_edp_link_settings(link, link_setting, req_bw)) return; } else if (decide_dp_link_settings(link, link_setting, req_bw)) -- GitLab From ecfe7569a512852eb35fe0edf73089e6451152e4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun <yongqiang.sun@amd.com> Date: Fri, 31 Jul 2020 13:57:05 -0400 Subject: [PATCH 0471/1494] drm/amd/display: Change ABM config init interface [Why & How] change abm config init interface to support multiple ABMs. Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Reviewed-by: Chris Park <Chris.Park@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../amd/display/modules/power/power_helpers.c | 19 +++++++++++++++---- .../amd/display/modules/power/power_helpers.h | 4 +++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 653b4a0d51d8c..a9b34462f5e19 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1415,7 +1415,7 @@ static int dm_late_init(void *handle) if (dmcu) ret = dmcu_load_iram(dmcu, params); else if (adev->dm.dc->ctx->dmub_srv) - ret = dmub_init_abm_config(adev->dm.dc->res_pool->abm, params); + ret = dmub_init_abm_config(adev->dm.dc->res_pool, params); if (!ret) return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 859724771a75d..61497954e67e5 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -657,7 +657,7 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame params, ram_table, big_endian); } -bool dmub_init_abm_config(struct abm *abm, +bool dmub_init_abm_config(struct resource_pool *res_pool, struct dmcu_iram_parameters params) { struct iram_table_v_2_2 ram_table; @@ -665,8 +665,13 @@ bool dmub_init_abm_config(struct abm *abm, bool result = false; uint32_t i, j = 0; - if (abm == NULL) +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (res_pool->abm == NULL && res_pool->multiple_abms[0] == NULL) return false; +#else + if (res_pool->abm == NULL) + return false; +#endif memset(&ram_table, 0, sizeof(ram_table)); memset(&config, 0, sizeof(config)); @@ -707,8 +712,14 @@ bool dmub_init_abm_config(struct abm *abm, config.min_abm_backlight = ram_table.min_abm_backlight; - result = abm->funcs->init_abm_config( - abm, (char *)(&config), sizeof(struct abm_config_table)); +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (res_pool->multiple_abms[0]) { + result = res_pool->multiple_abms[0]->funcs->init_abm_config( + res_pool->multiple_abms[0], (char *)(&config), sizeof(struct abm_config_table)); + } else +#endif + result = res_pool->abm->funcs->init_abm_config( + res_pool->abm, (char *)(&config), sizeof(struct abm_config_table)); return result; } diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h index 46fbca2e2cd1c..fa4728d880920 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h @@ -28,6 +28,8 @@ #include "dc/inc/hw/dmcu.h" #include "dc/inc/hw/abm.h" +struct resource_pool; + enum abm_defines { abm_defines_max_level = 4, @@ -45,7 +47,7 @@ struct dmcu_iram_parameters { bool dmcu_load_iram(struct dmcu *dmcu, struct dmcu_iram_parameters params); -bool dmub_init_abm_config(struct abm *abm, +bool dmub_init_abm_config(struct resource_pool *res_pool, struct dmcu_iram_parameters params); #endif /* MODULES_POWER_POWER_HELPERS_H_ */ -- GitLab From 9804ecbba8f73916101ac36929bc647c3cb17155 Mon Sep 17 00:00:00 2001 From: Paul Hsieh <paul.hsieh@amd.com> Date: Wed, 5 Aug 2020 17:28:37 +0800 Subject: [PATCH 0472/1494] drm/amd/display: Fix DFPstate hang due to view port changed [Why] Place the cursor in the center of screen between two pipes then adjusting the viewport but cursour doesn't update cause DFPstate hang. [How] If viewport changed, update cursor as well. Cc: stable@vger.kernel.org Signed-off-by: Paul Hsieh <paul.hsieh@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1d..c8cfd3ba1c156 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1457,8 +1457,8 @@ static void dcn20_update_dchubp_dpp( /* Any updates are handled in dc interface, just need to apply existing for plane enable */ if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || - pipe_ctx->update_flags.bits.scaler || pipe_ctx->update_flags.bits.viewport) - && pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { + pipe_ctx->update_flags.bits.scaler || viewport_changed == true) && + pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { dc->hwss.set_cursor_position(pipe_ctx); dc->hwss.set_cursor_attribute(pipe_ctx); -- GitLab From 6ee90e88b976743835d4f34f3234d775c733ef12 Mon Sep 17 00:00:00 2001 From: hersen wu <hersenxs.wu@amd.com> Date: Wed, 8 Jul 2020 22:14:41 -0400 Subject: [PATCH 0473/1494] drm/amd/display: PSR eDP p-state warning occurs intermittently after unplug DP [Why] with eDP + DP, each display use one pipe. after DP unplugged, eDP switch from one pipe to two pipes -- pipe split. dpp1_cm_set_regamma_pwl will be executed too. The duration from switch single pipe to dual pipes is a little long which could let eDP enter PSR mode. upon two pipes for eDP are setup, eDP PHY is disabled. front pipe is not really running to fetch data from frame buffer. i.e., dchubp is not in normal working status. execution of hubbub1_wm_change_req_wa may cause p-state warning. [How] disable eDP PSR before dc_commit_state. psr is disabled when execute hubbub1_wm_change_req_wa. Signed-off-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Roman Li <Roman.Li@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++++++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 +++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a9b34462f5e19..0d121a3f21031 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -171,7 +171,7 @@ static void amdgpu_dm_set_psr_caps(struct dc_link *link); static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream); - +static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm); /* * dm_vblank_get_counter @@ -7445,6 +7445,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; int crtc_disable_count = 0; + bool mode_set_reset_required = false; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -7521,19 +7522,21 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) acrtc->enabled = true; acrtc->hw_mode = new_crtc_state->mode; crtc->hwmode = new_crtc_state->mode; + mode_set_reset_required = true; } else if (modereset_required(new_crtc_state)) { DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (dm_old_crtc_state->stream) { - if (dm_old_crtc_state->stream->link->psr_settings.psr_allow_active) - amdgpu_dm_psr_disable(dm_old_crtc_state->stream); - + if (dm_old_crtc_state->stream) remove_stream(adev, acrtc, dm_old_crtc_state->stream); - } + mode_set_reset_required = true; } } /* for_each_crtc_in_state() */ if (dc_state) { + /* if there mode set or reset, disable eDP PSR */ + if (mode_set_reset_required) + amdgpu_dm_psr_disable_all(dm); + dm_enable_per_frame_crtc_master_sync(dc_state); mutex_lock(&dm->dc_lock); WARN_ON(!dc_commit_state(dm->dc, dc_state)); @@ -9054,6 +9057,18 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) return dc_link_set_psr_allow_active(stream->link, false, true); } +/* + * amdgpu_dm_psr_disable() - disable psr f/w + * if psr is enabled on any stream + * + * Return: true if success + */ +static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) +{ + DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n"); + return dc_set_psr_allow_active(dm->dc, false); +} + void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { struct amdgpu_device *adev = dev->dev_private; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ebbb8182228d2..a2084f279e7ba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2948,6 +2948,30 @@ void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_ dc->hwss.get_clock(dc, clock_type, clock_cfg); } +/* enable/disable eDP PSR without specify stream for eDP */ +bool dc_set_psr_allow_active(struct dc *dc, bool enable) +{ + int i; + + for (i = 0; i < dc->current_state->stream_count ; i++) { + struct dc_link *link; + struct dc_stream_state *stream = dc->current_state->streams[i]; + + link = stream->link; + if (!link) + continue; + + if (link->psr_settings.psr_feature_enabled) { + if (enable && !link->psr_settings.psr_allow_active) + return dc_link_set_psr_allow_active(link, true, false); + else if (!enable && link->psr_settings.psr_allow_active) + return dc_link_set_psr_allow_active(link, false, false); + } + } + + return true; +} + #if defined(CONFIG_DRM_AMD_DC_DCN3_0) void dc_allow_idle_optimizations(struct dc *dc, bool allow) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 772b3a6477008..f3ac9e3df7607 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1265,6 +1265,9 @@ void dc_unlock_memory_clock_frequency(struct dc *dc); void dc_lock_memory_clock_frequency(struct dc *dc); #endif + +bool dc_set_psr_allow_active(struct dc *dc, bool enable); + /******************************************************************************* * DSC Interfaces ******************************************************************************/ -- GitLab From ccc875052f829a03d1c9f67fc3a8709fe6c67c31 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun <yongqiang.sun@amd.com> Date: Wed, 5 Aug 2020 11:34:53 -0400 Subject: [PATCH 0474/1494] drm/amd/display: Add read backlight interface [Why & How] Add read backlight interface to get ABM data. Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 12 +++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 6 ++++-- .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 0257a900fe2bb..f42a17d765e37 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -708,3 +708,4 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream) "\tlink: %d\n", stream->link->link_index); } + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index a44effcda49f6..e84d216058543 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -46,6 +46,8 @@ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \ + SR(DC_ABM1_ACE_THRES_12), \ SR(BIOS_SCRATCH_2) #define ABM_DCN10_REG_LIST(id)\ @@ -60,6 +62,8 @@ SRI(BL1_PWM_USER_LEVEL, ABM, id), \ SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI(DC_ABM1_ACE_THRES_12, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) #define ABM_DCN20_REG_LIST() \ @@ -74,10 +78,12 @@ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \ + SR(DC_ABM1_ACE_THRES_12), \ NBIO_SR(BIOS_SCRATCH_2) #if defined(CONFIG_DRM_AMD_DC_DCN3_0) -#define ABM_DCN301_REG_LIST(id)\ +#define ABM_DCN30_REG_LIST(id)\ ABM_COMMON_REG_LIST_DCE_BASE(), \ SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ @@ -89,6 +95,8 @@ SRI(BL1_PWM_USER_LEVEL, ABM, id), \ SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI(DC_ABM1_ACE_THRES_12, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) #endif @@ -208,6 +216,8 @@ struct dce_abm_registers { uint32_t BL1_PWM_USER_LEVEL; uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES; uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; + uint32_t DC_ABM1_ACE_OFFSET_SLOPE_0; + uint32_t DC_ABM1_ACE_THRES_12; uint32_t MASTER_COMM_CNTL_REG; uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_DATA_REG1; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index 43781e77be431..a6d73d30837ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -46,13 +46,14 @@ #define FN(reg_name, field_name) \ dce_panel_cntl->shift->field_name, dce_panel_cntl->mask->field_name -static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_panel_cntl *dce_panel_cntl) +static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) { uint64_t current_backlight; uint32_t round_result; uint32_t pwm_period_cntl, bl_period, bl_int_count; uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; uint32_t bl_period_mask, bl_pwm_mask; + struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); @@ -150,7 +151,7 @@ static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) REG_UPDATE(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, 0); - current_backlight = calculate_16_bit_backlight_from_pwm(dce_panel_cntl); + current_backlight = dce_get_16_bit_backlight_from_pwm(panel_cntl); return current_backlight; } @@ -273,6 +274,7 @@ static const struct panel_cntl_funcs dce_link_panel_cntl_funcs = { .is_panel_powered_on = dce_is_panel_powered_on, .store_backlight_level = dce_store_backlight_level, .driver_set_backlight = dce_driver_set_backlight, + .get_current_backlight = dce_get_16_bit_backlight_from_pwm, }; void dce_panel_cntl_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index aa3ea6c79c278..3b4c356c5ba6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -340,7 +340,7 @@ static const struct dce110_clk_src_mask cs_mask = { #define abm_regs(id)\ [id] = {\ - ABM_DCN301_REG_LIST(id)\ + ABM_DCN30_REG_LIST(id)\ } static const struct dce_abm_registers abm_regs[] = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h index f9ab5abb64623..48eac622c6a0f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h @@ -49,6 +49,7 @@ struct panel_cntl_funcs { void (*store_backlight_level)(struct panel_cntl *panel_cntl); void (*driver_set_backlight)(struct panel_cntl *panel_cntl, uint32_t backlight_pwm_u16_16); + uint32_t (*get_current_backlight)(struct panel_cntl *panel_cntl); }; struct panel_cntl_init_data { -- GitLab From ce271b40a91f781af3dee985c39e841ac5148766 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo <qingqing.zhuo@amd.com> Date: Thu, 30 Jul 2020 15:35:41 -0400 Subject: [PATCH 0475/1494] drm/amd/display: Screen corruption on dual displays (DP+USB-C) [why] Current pipe merge and split logic only supports cases where new dc_state is allocated and relies on dc->current_state to gather information from previous dc_state. Calls to validate_bandwidth on UPDATE_TYPE_MED would cause an issue because there is no new dc_state allocated, and data in dc->current_state would be overwritten during pipe merge. [how] Only allow validate_bandwidth when new dc_state space is created. Signed-off-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a2084f279e7ba..dc463d99ef503 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2636,7 +2636,7 @@ void dc_commit_updates_for_stream(struct dc *dc, copy_stream_update_to_stream(dc, context, stream, stream_update); - if (update_type > UPDATE_TYPE_FAST) { + if (update_type >= UPDATE_TYPE_FULL) { if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { DC_ERROR("Mode validation failed for stream update!\n"); dc_release_state(context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index c31d1f30e505d..1b98744451345 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3209,6 +3209,9 @@ static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc, context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive = dc->debug.enable_dram_clock_change_one_display_vactive; + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + if (fast_validate) { return dcn20_validate_bandwidth_internal(dc, context, true); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index a828696668bfc..78743ae37851f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1184,6 +1184,9 @@ bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, BW_VAL_TRACE_COUNT(); + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel); if (pipe_cnt == 0) -- GitLab From 4bb23a544667a5c9f6dd158abf5158c120e1707f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Thu, 6 Aug 2020 13:57:08 -0400 Subject: [PATCH 0476/1494] drm/amd/display: fix dcn3 wide timing dsc validation Wide timing DSC requires odm. Since spreadsheet is missing this dsc validation we have to modify DML vba code ourselves. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Reviewed-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index b54814f11b74b..2beb284f89b0a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -63,6 +63,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff +#define DCN30_MAX_DSC_IMAGE_WIDTH 5184 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -3984,6 +3985,9 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; -- GitLab From bcc6aa61c82d4f12df3ecc884a9eef9d566edae9 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Fri, 19 Jun 2020 14:42:09 -0400 Subject: [PATCH 0477/1494] drm/amd/display: Fix DSC force enable on SST [why] Previously when force enabling DSC on SST display we unknowingly supressed lane count, which caused DSC to be enabled automatically. [how] By adding an additional flag to force enable DSC in dc_dsc.c DSC can always be enabled with debugfs dsc_clock_en forced to 1 Cc: stable@vger.kernel.org Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc_dsc.h | 3 +++ drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0d121a3f21031..ad6b95d65f7b0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4646,6 +4646,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, #if defined(CONFIG_DRM_AMD_DC_DCN) if (dsc_caps.is_dsc_supported) { + /* Set DSC policy according to dsc_clock_en */ + dc_dsc_policy_set_enable_dsc_when_not_needed(aconnector->dsc_settings.dsc_clock_en); + if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], &dsc_caps, aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index 3800340a5b4f6..768ab38d41cf9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -51,6 +51,7 @@ struct dc_dsc_policy { int min_slice_height; // Must not be less than 8 uint32_t max_target_bpp; uint32_t min_target_bpp; + bool enable_dsc_when_not_needed; }; bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, @@ -80,4 +81,6 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit); +void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 8cdaa6eef5d37..da1b654833d5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -34,6 +34,9 @@ /* default DSC policy target bitrate limit is 16bpp */ static uint32_t dsc_policy_max_target_bpp_limit = 16; +/* default DSC policy enables DSC only when needed */ +static bool dsc_policy_enable_dsc_when_not_needed; + static uint32_t dc_dsc_bandwidth_in_kbps_from_timing( const struct dc_crtc_timing *timing) { @@ -360,7 +363,7 @@ static bool decide_dsc_target_bpp_x16( get_dsc_bandwidth_range(policy->min_target_bpp, policy->max_target_bpp, dsc_common_caps, timing, &range); - if (target_bandwidth_kbps >= range.stream_kbps) { + if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) { /* enough bandwidth without dsc */ *target_bpp_x16 = 0; should_use_dsc = false; @@ -961,9 +964,20 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, struct dc /* internal upper limit, default 16 bpp */ if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) policy->max_target_bpp = dsc_policy_max_target_bpp_limit; + + /* enable DSC when not needed, default false */ + if (dsc_policy_enable_dsc_when_not_needed) + policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed; + else + policy->enable_dsc_when_not_needed = false; } void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit) { dsc_policy_max_target_bpp_limit = limit; } + +void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) +{ + dsc_policy_enable_dsc_when_not_needed = enable; +} -- GitLab From 6798d04205d171df94b016163b13094179878d67 Mon Sep 17 00:00:00 2001 From: Lewis Huang <Lewis.Huang@amd.com> Date: Thu, 30 Jul 2020 18:00:23 +0800 Subject: [PATCH 0478/1494] drm/amd/display: Add extra T3 delay [Why] For some special panel, it will have an invalid HPD high cause driver DPCD read/write fail. [How] Add extra T3 delay as a monitor patch in dce110_edp_wait_for_hpd_ready Signed-off-by: Lewis Huang <Lewis.Huang@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + .../gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 946ba929c6f64..aa8e0955db482 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -233,6 +233,7 @@ struct dc_panel_patch { unsigned int skip_scdc_overwrite; unsigned int delay_ignore_msa; unsigned int disable_fec; + unsigned int extra_t3_ms; }; struct dc_edid_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 45c9e90278862..0603ddca7bd06 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -720,6 +720,7 @@ void dce110_edp_wait_for_hpd_ready( struct dc_context *ctx = link->ctx; struct graphics_object_id connector = link->link_enc->connector; struct gpio *hpd; + struct dc_sink *sink = link->local_sink; bool edp_hpd_high = false; uint32_t time_elapsed = 0; uint32_t timeout = power_up ? @@ -752,6 +753,14 @@ void dce110_edp_wait_for_hpd_ready( return; } + if (sink != NULL) { + if (sink->edid_caps.panel_patch.extra_t3_ms > 0) { + int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms; + + msleep(extra_t3_in_ms); + } + } + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); /* wait until timeout or panel detected */ -- GitLab From 8cfc40cd97475fcddb2ca4671eaea2eb26b31e0a Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Thu, 6 Aug 2020 15:40:01 -0400 Subject: [PATCH 0479/1494] drm/amd/display: Reset scrambling on Test Pattern [Why] Programming is missing the sequence where for eDP the scrambling is reset when testing for eye diagram test pattern. [How] Include the required register in the definition Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 3b4c356c5ba6a..1ee9087eec761 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } static const struct dce110_aux_registers_shift aux_shift = { -- GitLab From 5ab7943187f22b572fd12d517bd699771b88ce91 Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Date: Thu, 6 Aug 2020 17:54:47 -0400 Subject: [PATCH 0480/1494] drm/amd/display: fix pow() crashing when given base 0 [Why&How] pow(a,x) is implemented as exp(x*log(a)). log(0) will crash. So return 0^x = 0, unless x=0, convention seems to be 0^0 = 1. Cc: stable@vger.kernel.org Signed-off-by: Krunoslav Kovac <Krunoslav.Kovac@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/include/fixed31_32.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 89ef9f6860e5b..16df2a485dd0d 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -431,6 +431,9 @@ struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg); */ static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2) { + if (arg1.value == 0) + return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero; + return dc_fixpt_exp( dc_fixpt_mul( dc_fixpt_log(arg1), -- GitLab From e0f7ff99c92ff5e033e169c30cff607ff7c17192 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung <jaehyun.chung@amd.com> Date: Wed, 5 Aug 2020 17:28:53 -0400 Subject: [PATCH 0481/1494] drm/amd/display: Mask DPCD field to avoid reading unsupported field value [Why] DSC will be disabled if DPCD 0006F[6:3] is set to a non-zero value because bits 6:3 are not currently supported. When 6:3 is populated, an unsupported INCREMENT OF bits_per_pixel value is read (DPCD 0006F[2:0]) [How] Mask the INCREMENT OF bits_per_pixel field so that values in the unsupported field are ignored. Signed-off-by: Jaehyun Chung <jaehyun.chung@amd.com> Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index da1b654833d5c..4c844cfaa9568 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -192,8 +192,10 @@ static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) } -static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div) +static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div) { + // Mask bpp increment dpcd field to avoid reading other fields + bpp_increment_dpcd &= 0x7; switch (bpp_increment_dpcd) { case 0: -- GitLab From 2ac685bfca27dd692b772fdd66b59ef1d83453be Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Fri, 7 Aug 2020 21:06:11 -0400 Subject: [PATCH 0482/1494] drm/amd/display: [FW Promotion] Release 0.0.29 [Header Changes] - Add command for panel power seq control Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index b58ed6538eab2..d7e7f2eda92fd 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x3f7e3738b +#define DMUB_FW_VERSION_GIT_HASH 0x4e5b2f46f #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 28 +#define DMUB_FW_VERSION_REVISION 29 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -213,6 +213,7 @@ enum dmub_cmd_vbios_type { DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL = 1, DMUB_CMD__VBIOS_SET_PIXEL_CLOCK = 2, DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING = 3, + DMUB_CMD__VBIOS_LVTMA_CONTROL = 15, }; //============================================================================== -- GitLab From 6fecfc82529d3cac41bb1f36b9b825926c1657e7 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Thu, 13 Aug 2020 16:51:09 -0400 Subject: [PATCH 0483/1494] drm/amd/display: Add DSC_DBG_EN shift/mask for dcn3 This field is not defined for DCN3 Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h | 1 + .../include/asic_reg/dcn/dcn_3_0_0_sh_mask.h | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h index 667640c4b288a..1118e33aaa2cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h @@ -94,6 +94,7 @@ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \ + DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, ICH_RESET_AT_END_OF_LINE, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \ diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h index 0e0319e98c07a..ea683f452bb33 100755 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h @@ -50271,6 +50271,10 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP0_DSC_DEBUG_CONTROL +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc0_dispdec_dsccif_dispdec //DSCCIF0_DSCCIF_CONFIG0 @@ -50789,6 +50793,9 @@ #define DSC_TOP1_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP1_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP1_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP1_DSC_DEBUG_CONTROL +#define DSC_TOP1_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP1_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L // addressBlock: dce_dc_dsc1_dispdec_dsccif_dispdec @@ -51308,6 +51315,10 @@ #define DSC_TOP2_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP2_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP2_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP2_DSC_DEBUG_CONTROL +#define DSC_TOP2_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP2_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc2_dispdec_dsccif_dispdec //DSCCIF2_DSCCIF_CONFIG0 @@ -51826,6 +51837,9 @@ #define DSC_TOP3_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP3_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP3_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP3_DSC_DEBUG_CONTROL +#define DSC_TOP3_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP3_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L // addressBlock: dce_dc_dsc3_dispdec_dsccif_dispdec @@ -52346,6 +52360,10 @@ #define DSC_TOP4_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP4_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP4_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP4_DSC_DEBUG_CONTROL +#define DSC_TOP4_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP4_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc4_dispdec_dsccif_dispdec //DSCCIF4_DSCCIF_CONFIG0 @@ -52864,6 +52882,10 @@ #define DSC_TOP5_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP5_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP5_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP5_DSC_DEBUG_CONTROL +#define DSC_TOP5_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP5_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc5_dispdec_dsccif_dispdec //DSCCIF5_DSCCIF_CONFIG0 -- GitLab From 83c0926f3e189e91137c5311f2d187eafc6091a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 14 Jul 2020 23:19:45 +0300 Subject: [PATCH 0484/1494] drm/i915/fbc: Limit cfb to the first 256MiB of stolen on g4x+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since g4x the CFB base only takes a 28bit offset into stolen. Not sure if the CFB is allowed to start below that limit but then extend beyond it. Let's assume not and just restrict the allocation to the first 256MiB (in the unlikely case we have more stolen than that). v2: s/BIT/BIT_ULL/ (Chris) Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714201945.18959-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 85723fba60020..3a4f980788a62 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -424,6 +424,14 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, fbc->no_fbc_reason = reason; } +static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915) +{ + if (INTEL_GEN(i915) >= 5 || IS_G4X(i915)) + return BIT_ULL(28); + else + return BIT_ULL(32); +} + static int find_compression_threshold(struct drm_i915_private *dev_priv, struct drm_mm_node *node, unsigned int size, @@ -442,6 +450,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, else end = U64_MAX; + end = min(end, intel_fbc_cfb_base_max(dev_priv)); + /* HACK: This code depends on what we will do in *_enable_fbc. If that * code changes, this code needs to change as well. * -- GitLab From 124c7088b87fdf97530fe96d7c025fce9198ed9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 14 Jul 2020 18:26:23 +0300 Subject: [PATCH 0485/1494] drm/i915: Pack struct intel_cdclk_vals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a pointless hole in struct intel_cdclk_vals, get rid of it. Fortunately we already use named initializers so the order does not matter. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_cdclk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 5731806e4cee9..6b31fde4be164 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -17,8 +17,8 @@ struct intel_atomic_state; struct intel_crtc_state; struct intel_cdclk_vals { - u16 refclk; u32 cdclk; + u16 refclk; u8 divider; /* CD2X divider * 2 */ u8 ratio; }; -- GitLab From 0e954383ff575d42095eeb8a8083ada693053e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 14 Jul 2020 18:26:24 +0300 Subject: [PATCH 0486/1494] drm/i915: Fix some whitespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some spaces have snuck in where we want tabs. Fix it. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index bb91dace304ad..72095ef144263 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2677,7 +2677,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv) */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_de_write(dev_priv, GMBUSFREQ_VLV, - DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000)); + DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000)); } static int cnp_rawclk(struct drm_i915_private *dev_priv) -- GitLab From 366ec167ea73c36ec2a2ccd144306623e8e49b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 14 Jul 2020 18:26:25 +0300 Subject: [PATCH 0487/1494] drm/i915: Make i830 .get_cdclk() assignment less confusing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly check for i830 when assigning the .get_cdclk() vfunc, and then deal with the case of not having assigned the vfunc separately. Less confusing, and gets rid of the checkpatch complaint about using {} on one branch but not the others. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-3-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_cdclk.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 72095ef144263..9d6cacbdb6919 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2903,9 +2903,10 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) dev_priv->display.get_cdclk = i85x_get_cdclk; else if (IS_I845G(dev_priv)) dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk; - else { /* 830 */ - drm_WARN(&dev_priv->drm, !IS_I830(dev_priv), - "Unknown platform. Assuming 133 MHz CDCLK\n"); + else if (IS_I830(dev_priv)) + dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk; + + if (drm_WARN(&dev_priv->drm, !dev_priv->display.get_cdclk, + "Unknown platform. Assuming 133 MHz CDCLK\n")) dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk; - } } -- GitLab From 963501bdd094acb4a382d185a9754cd30b8903ba Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Tue, 14 Jul 2020 18:31:40 +0300 Subject: [PATCH 0488/1494] drm/i915/ddi: Don't frob the DP link scramble disabling flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to BSpec this flag should not be changed while the DDI function is enabled. On BDW+ the DP_TP_CTL register spec also states it explicitly that the HW takes care of enabling/disabling the scrambling for training patterns (and it must stay enabled for normal pixel output). Assume that this HW automatic handling of scrambling is also true for HSW. BSpec: 8013, 7557, 50484 Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714153141.10280-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 2c484b55bcdf7..c467f18d5e1be 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4037,8 +4037,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) intel_wait_ddi_buf_idle(dev_priv, port); } - dp_tp_ctl = DP_TP_CTL_ENABLE | - DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; + dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1; if (intel_dp->link_mst) dp_tp_ctl |= DP_TP_CTL_MODE_MST; else { @@ -4066,11 +4065,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_ctl); - if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) - temp |= DP_TP_CTL_SCRAMBLE_DISABLE; - else - temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; - temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; switch (dp_train_pat & train_pat_mask) { case DP_TRAINING_PATTERN_DISABLE: -- GitLab From a5bcf8dde63142f36ae8ce720265d4c41a634d5c Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Tue, 14 Jul 2020 18:31:41 +0300 Subject: [PATCH 0489/1494] drm/i915/ddi: Don't rewrite DDI_BUF_CTL reg during DP link training MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value we program to DDI_BUF_CTL changes at the following places: - At enabling/disabling the output to configure the port width etc, and to enable/disable the DDI BUF function. - At the beginning/end of link re-training to disable/re-enable the DDI BUF function. - On HSW/BDW/SKL to change the voltage swing/pre-emph levels. Except of the above the value we program to the DDI_BUF_CTL register (intel_dp->DP) doesn't change, so no need to reprogram the register when changing the link training patterns (which is programmed via the DP_TP_CTL register on DDI platforms). v2: - Fix the commit message wrt. voltage/pre-emph level values in intel_dp->DP. (Ville) Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714153141.10280-2-imre.deak@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c467f18d5e1be..424d596715619 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4060,7 +4060,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd); - enum port port = dp_to_dig_port(intel_dp)->base.port; u32 temp; temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_ctl); @@ -4085,9 +4084,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, } intel_de_write(dev_priv, intel_dp->regs.dp_tp_ctl, temp); - - intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); - intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); } static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp) -- GitLab From 27e897beec1c59861f15d4d3562c39ad1143620f Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 16 Jul 2020 10:46:43 +0100 Subject: [PATCH 0490/1494] drm/i915: Provide the perf pmu.module Rather than manually implement our own module reference counting for perf pmu events, finally realise that there is a module parameter to struct pmu for this very purpose. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716094643.31410-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_pmu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 28bc5f13ae521..056994224c6bc 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -445,8 +445,6 @@ static void i915_pmu_event_destroy(struct perf_event *event) container_of(event->pmu, typeof(*i915), pmu.base); drm_WARN_ON(&i915->drm, event->parent); - - module_put(THIS_MODULE); } static int @@ -538,10 +536,8 @@ static int i915_pmu_event_init(struct perf_event *event) if (ret) return ret; - if (!event->parent) { - __module_get(THIS_MODULE); + if (!event->parent) event->destroy = i915_pmu_event_destroy; - } return 0; } @@ -1130,6 +1126,7 @@ void i915_pmu_register(struct drm_i915_private *i915) if (!pmu->base.attr_groups) goto err_attr; + pmu->base.module = THIS_MODULE; pmu->base.task_ctx_nr = perf_invalid_context; pmu->base.event_init = i915_pmu_event_init; pmu->base.add = i915_pmu_event_add; -- GitLab From f2bde2546b81b64fb58aa04888fdd82a090b3908 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov <apodtele@gmail.com> Date: Mon, 27 Apr 2020 23:47:52 -0400 Subject: [PATCH 0491/1494] drm/i915: Remove dubious Valleyview PCI IDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0x0155 is rather Ivy Bridge PCI-E Root Port. 0x0157 from the same commit ff049b6ce21d ("drm/i915: bind driver to ValleyView chipsets") is likely wrong too. Nowhere is it independetly confirmed or mentioned. Signed-off-by: Alexei Podtelezhnikov <apodtele@gmail.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200428034752.3975-1-apodtele@gmail.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- include/drm/i915_pciids.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 96e408b4bdc9f..8e7ae30ebcbb7 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -258,9 +258,7 @@ INTEL_VGA_DEVICE(0x0f30, info), \ INTEL_VGA_DEVICE(0x0f31, info), \ INTEL_VGA_DEVICE(0x0f32, info), \ - INTEL_VGA_DEVICE(0x0f33, info), \ - INTEL_VGA_DEVICE(0x0157, info), \ - INTEL_VGA_DEVICE(0x0155, info) + INTEL_VGA_DEVICE(0x0f33, info) #define INTEL_BDW_ULT_GT1_IDS(info) \ INTEL_VGA_DEVICE(0x1606, info), /* GT1 ULT */ \ -- GitLab From 81619f4a75ed75823d52f46e167fa82d72c1eeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Wed, 15 Jul 2020 10:56:37 -0700 Subject: [PATCH 0492/1494] drm/i915/display: Implement HOBL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hours Of Battery Life is a new GEN12+ power-saving feature that allows supported motherboards to use a special voltage swing table for eDP panels that uses less power. So here if supported by HW, OEM will set it in VBT and i915 will try to train link with HOBL vswing table if link training fails it fall back to the original table. intel_ddi_dp_preemph_max() was optimized to only check the HOBL flag instead of do something like is done in intel_ddi_dp_voltage_max() because it is only called after the first entry of the voltage swing table was loaded so the HOBL flag is valid at that point. v3: - removed a few parameters of icl_ddi_combo_vswing_program() that can be taken from encoder v4: - using the HOBL vswing table until training fails completely (Ville) v5: - not reducing lane or link rate when link training fails with HOBL active - duplicated the HOBL voltage swing entry to match DP spec requirement v6: - removed the optional VS 3 & pre-emp 0 from HOBL table - changed from u8:1 to bool to store hobl_failed/active BSpec: 49291 BSpec: 49399 Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Animesh Manna <animesh.manna@intel.com> Cc: Manasi Navare <manasi.d.navare@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200715175637.33763-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 43 +++++++++++++++++++ .../drm/i915/display/intel_display_types.h | 3 ++ .../drm/i915/display/intel_dp_link_training.c | 19 +++++--- drivers/gpu/drm/i915/i915_reg.h | 2 + 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 424d596715619..c52ad5ecb6451 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -706,6 +706,28 @@ static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; +/* + * Cloned the HOBL entry to comply with the voltage and pre-emphasis entries + * that DisplayPort specification requires + */ +static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_edp_hbr2_hobl[] = { + /* VS pre-emp */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 1 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 2 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 3 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 1 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 2 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 1 */ +}; + +static bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table) +{ + return table == tgl_combo_phy_ddi_translations_edp_hbr2_hobl; +} + static const struct ddi_buf_trans * bdw_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { @@ -1050,6 +1072,18 @@ static const struct cnl_ddi_buf_trans * tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.hobl) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (!intel_dp->hobl_failed && rate <= 540000) { + /* Same table applies to TGL, RKL and DG1 */ + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_edp_hbr2_hobl); + return tgl_combo_phy_ddi_translations_edp_hbr2_hobl; + } + } + if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } else if (rate > 270000) { @@ -2392,6 +2426,15 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, level = n_entries - 1; } + if (type == INTEL_OUTPUT_EDP) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED; + intel_dp->hobl_active = is_hobl_buf_trans(ddi_translations); + intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val, + intel_dp->hobl_active ? val : 0); + } + /* Set PORT_TX_DW5 */ val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN0(phy)); val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e8f809161c75f..f581260e8dbfd 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1375,6 +1375,9 @@ struct intel_dp { /* Display stream compression testing */ bool force_dsc_en; + + bool hobl_failed; + bool hobl_active; }; enum lspcon_vendor { diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index a23ed7290843a..f2c8b56be9ead 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -410,10 +410,17 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) intel_connector->base.base.id, intel_connector->base.name, intel_dp->link_rate, intel_dp->lane_count); - if (!intel_dp_get_link_train_fallback_values(intel_dp, - intel_dp->link_rate, - intel_dp->lane_count)) - /* Schedule a Hotplug Uevent to userspace to start modeset */ - schedule_work(&intel_connector->modeset_retry_work); - return; + + if (intel_dp->hobl_active) { + drm_dbg_kms(&dp_to_i915(intel_dp)->drm, + "Link Training failed with HOBL active, not enabling it from now on"); + intel_dp->hobl_failed = true; + } else if (intel_dp_get_link_train_fallback_values(intel_dp, + intel_dp->link_rate, + intel_dp->lane_count)) { + return; + } + + /* Schedule a Hotplug Uevent to userspace to start modeset */ + schedule_work(&intel_connector->modeset_retry_work); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4e796ff4d7d0f..b9607ac3620db 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1898,6 +1898,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define PWR_DOWN_LN_3_1_0 (0xb << 4) #define PWR_DOWN_LN_MASK (0xf << 4) #define PWR_DOWN_LN_SHIFT 4 +#define EDP4K2K_MODE_OVRD_EN (1 << 3) +#define EDP4K2K_MODE_OVRD_OPTIMIZED (1 << 2) #define ICL_PORT_CL_DW12(phy) _MMIO(_ICL_PORT_CL_DW(12, phy)) #define ICL_LANE_ENABLE_AUX (1 << 0) -- GitLab From f1421190d0abf55c34525cc88ab8c00ada9fbb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Thu, 16 Jul 2020 22:04:25 +0300 Subject: [PATCH 0493/1494] drm/i915: Move WaDisableDopClockGating:skl to skl_init_clock_gating() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's silly to have if(SKL) checks in gen9_init_clock_gating() when we can just move those bits into skl_init_clock_gating(). I'm not entirely convinced we even need this w/a, or if we do then maybe we want it for kbl/cfl as well. IIRC it was only listed in the wadb, but that is now dead so can't double check anymore. Bspec doesn't seem to have any purely skl specific DOP clock gating workarounds listed. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716190426.17047-1-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cfabbe0481ab8..0a1a95060f38b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -100,12 +100,6 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) */ I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | DISP_FBC_MEMORY_WAKE); - - if (IS_SKYLAKE(dev_priv)) { - /* WaDisableDopClockGating */ - I915_WRITE(GEN7_MISCCPCTL, I915_READ(GEN7_MISCCPCTL) - & ~GEN7_DOP_CLOCK_GATE_ENABLE); - } } static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) @@ -7251,6 +7245,10 @@ static void skl_init_clock_gating(struct drm_i915_private *dev_priv) { gen9_init_clock_gating(dev_priv); + /* WaDisableDopClockGating:skl */ + I915_WRITE(GEN7_MISCCPCTL, I915_READ(GEN7_MISCCPCTL) & + ~GEN7_DOP_CLOCK_GATE_ENABLE); + /* WAC6entrylatency:skl */ I915_WRITE(FBC_LLC_READ_CTRL, I915_READ(FBC_LLC_READ_CTRL) | FBC_LLC_FULLY_OPEN); -- GitLab From cd803bb4f8a8d7b2c27c464ae32af14005cce7a1 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Thu, 16 Jul 2020 15:05:47 -0700 Subject: [PATCH 0494/1494] drm/i915/rkl: Handle new DPCLKA_CFGCR0 layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RKL uses a slightly different bit layout for the DPCLKA_CFGCR0 register. v2: - Fix inverted mask application when updating ICL_DPCLKA_CFGCR0 - Checkpatch style fixes Bspec: 50287 Cc: Aditya Swarup <aditya.swarup@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-2-matthew.d.roper@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 18 +++++++++++++++--- drivers/gpu/drm/i915/display/intel_display.c | 15 ++++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c52ad5ecb6451..1ca70f9abc8d9 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2845,7 +2845,9 @@ hsw_set_signal_levels(struct intel_dp *intel_dp) static u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv, enum phy phy) { - if (intel_phy_is_combo(dev_priv, phy)) { + if (IS_ROCKETLAKE(dev_priv)) { + return RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + } else if (intel_phy_is_combo(dev_priv, phy)) { return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); } else if (intel_phy_is_tc(dev_priv, phy)) { enum tc_port tc_port = intel_port_to_tc(dev_priv, @@ -2872,6 +2874,16 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder, (val & icl_dpclka_cfgcr0_clk_off(dev_priv, phy)) == 0); if (intel_phy_is_combo(dev_priv, phy)) { + u32 mask, sel; + + if (IS_ROCKETLAKE(dev_priv)) { + mask = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + sel = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + } else { + mask = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + sel = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + } + /* * Even though this register references DDIs, note that we * want to pass the PHY rather than the port (DDI). For @@ -2882,8 +2894,8 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder, * Clock Select chooses the PLL for both DDIA and DDID and * drives port A in all cases." */ - val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); - val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + val &= ~mask; + val |= sel; intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 729ec6e0d43a0..6cb66580ad2c2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10802,9 +10802,18 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, u32 temp; if (intel_phy_is_combo(dev_priv, phy)) { - temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) & - ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); - id = temp >> ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + u32 mask, shift; + + if (IS_ROCKETLAKE(dev_priv)) { + mask = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + shift = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + } else { + mask = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + shift = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + } + + temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) & mask; + id = temp >> shift; port_dpll_id = ICL_PORT_DPLL_DEFAULT; } else if (intel_phy_is_tc(dev_priv, phy)) { u32 clk_sel = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b9607ac3620db..00414c457941d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10279,12 +10279,18 @@ enum skl_power_gate { #define ICL_DPCLKA_CFGCR0 _MMIO(0x164280) #define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) (1 << _PICK(phy, 10, 11, 24)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT((phy) + 10) #define ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) < PORT_TC4 ? \ (tc_port) + 12 : \ (tc_port) - PORT_TC4 + 21)) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) ((phy) * 2) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (3 << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) ((pll) << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) _PICK(phy, 0, 2, 4, 27) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) \ + (3 << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) \ + ((pll) << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) /* CNL PLL */ #define DPLL0_ENABLE 0x46010 -- GitLab From f52fa57ae70e2e411c0d72396d526d76bf8d3eda Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Thu, 16 Jul 2020 15:05:48 -0700 Subject: [PATCH 0495/1494] drm/i915/rkl: Add initial workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RKL and TGL share some general gen12 workarounds, but each platform also has its own platform-specific workarounds. v2: - Add Wa_1604555607 for RKL. This makes RKL's ctx WA list identical to TGL's, so we'll have both functions call the tgl_ function for now; this workaround isn't listed for DG1 so we don't want to add it to the general gen12_ function. Cc: Matt Atwood <matthew.s.atwood@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-3-matthew.d.roper@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_sprite.c | 5 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 89 +++++++++++++-------- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index d03860fef2d79..c26ca029fc0aa 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2843,8 +2843,9 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv, enum plane_id plane_id) { - /* Wa_14010477008:tgl[a0..c0] */ - if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) + /* Wa_14010477008:tgl[a0..c0],rkl[all] */ + if (IS_ROCKETLAKE(dev_priv) || + IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) return false; return plane_id < PLANE_SPRITE4; diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 5726cd0a37e04..cef1c122696fb 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -596,8 +596,8 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); } -static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, - struct i915_wa_list *wal) +static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, + struct i915_wa_list *wal) { /* * Wa_1409142259:tgl @@ -607,12 +607,28 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, * Wa_1409207793:tgl * Wa_1409178076:tgl * Wa_1408979724:tgl + * Wa_14010443199:rkl + * Wa_14010698770:rkl */ WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3, GEN12_DISABLE_CPS_AWARE_COLOR_PIPE); + /* WaDisableGPGPUMidThreadPreemption:gen12 */ + WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, + GEN9_PREEMPT_GPGPU_LEVEL_MASK, + GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL); +} + +static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, + struct i915_wa_list *wal) +{ + gen12_ctx_workarounds_init(engine, wal); + /* - * Wa_1604555607:gen12 and Wa_1608008084:gen12 + * Wa_1604555607:tgl,rkl + * + * Note that the implementation of this workaround is further modified + * according to the FF_MODE2 guidance given by Wa_1608008084:gen12. * FF_MODE2 register will return the wrong value when read. The default * value for this register is zero for all fields and there are no bit * masks. So instead of doing a RMW we should just write the GS Timer @@ -623,11 +639,6 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, FF_MODE2_GS_TIMER_MASK | FF_MODE2_TDS_TIMER_MASK, FF_MODE2_GS_TIMER_224 | FF_MODE2_TDS_TIMER_128, 0); - - /* WaDisableGPGPUMidThreadPreemption:tgl */ - WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, - GEN9_PREEMPT_GPGPU_LEVEL_MASK, - GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL); } static void @@ -642,8 +653,10 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine, wa_init_start(wal, name, engine->name); - if (IS_GEN(i915, 12)) + if (IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) tgl_ctx_workarounds_init(engine, wal); + else if (IS_GEN(i915, 12)) + gen12_ctx_workarounds_init(engine, wal); else if (IS_GEN(i915, 11)) icl_ctx_workarounds_init(engine, wal); else if (IS_CANNONLAKE(i915)) @@ -1176,9 +1189,16 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) } static void -tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) +gen12_gt_workarounds_init(struct drm_i915_private *i915, + struct i915_wa_list *wal) { wa_init_mcr(i915, wal); +} + +static void +tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) +{ + gen12_gt_workarounds_init(i915, wal); /* Wa_1409420604:tgl */ if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) @@ -1196,8 +1216,10 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) static void gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal) { - if (IS_GEN(i915, 12)) + if (IS_TIGERLAKE(i915)) tgl_gt_workarounds_init(i915, wal); + else if (IS_GEN(i915, 12)) + gen12_gt_workarounds_init(i915, wal); else if (IS_GEN(i915, 11)) icl_gt_workarounds_init(i915, wal); else if (IS_CANNONLAKE(i915)) @@ -1629,18 +1651,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN9_CTX_PREEMPT_REG, GEN12_DISABLE_POSH_BUSY_FF_DOP_CG); - /* - * Wa_1607030317:tgl - * Wa_1607186500:tgl - * Wa_1607297627:tgl there is 3 entries for this WA on BSpec, 2 - * of then says it is fixed on B0 the other one says it is - * permanent - */ - wa_masked_en(wal, - GEN6_RC_SLEEP_PSMI_CONTROL, - GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | - GEN8_RC_SEMA_IDLE_MSG_DISABLE); - /* * Wa_1606679103:tgl * (see also Wa_1606682166:icl) @@ -1654,22 +1664,17 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) VSUNIT_CLKGATE_DIS_TGL); } - if (IS_TIGERLAKE(i915)) { - /* Wa_1606931601:tgl */ + if (IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) { + /* Wa_1606931601:tgl,rkl */ wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ); - /* Wa_1409804808:tgl */ + /* Wa_1409804808:tgl,rkl */ wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_PUSH_CONST_DEREF_HOLD_DIS); - /* Wa_1606700617:tgl */ - wa_masked_en(wal, - GEN9_CS_DEBUG_MODE1, - FF_DOP_CLOCK_GATE_DISABLE); - /* * Wa_1409085225:tgl - * Wa_14010229206:tgl + * Wa_14010229206:tgl,rkl */ wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH); @@ -1677,9 +1682,29 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) * Wa_1407928979:tgl A* * Wa_18011464164:tgl B0+ * Wa_22010931296:tgl B0+ + * Wa_14010919138:rkl */ wa_write_or(wal, GEN7_FF_THREAD_MODE, GEN12_FF_TESSELATION_DOP_GATE_DISABLE); + + /* + * Wa_1607030317:tgl + * Wa_1607186500:tgl + * Wa_1607297627:tgl,rkl there are multiple entries for this + * WA in the BSpec; some indicate this is an A0-only WA, + * others indicate it applies to all steppings. + */ + wa_masked_en(wal, + GEN6_RC_SLEEP_PSMI_CONTROL, + GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | + GEN8_RC_SEMA_IDLE_MSG_DISABLE); + } + + if (IS_TIGERLAKE(i915)) { + /* Wa_1606700617:tgl */ + wa_masked_en(wal, + GEN9_CS_DEBUG_MODE1, + FF_DOP_CLOCK_GATE_DISABLE); } if (IS_GEN(i915, 11)) { -- GitLab From e66f609baeee0d8354d3e1aa7d171a54ce72cb34 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Thu, 16 Jul 2020 15:05:49 -0700 Subject: [PATCH 0496/1494] drm/i915/rkl: Add DPLL4 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rocket Lake has a third DPLL (called 'DPLL4') that must be used to enable a third display. Unlike EHL's variant of DPLL4, the RKL variant behaves the same as DPLL0/1. And despite its name, the DPLL4 registers are offset as if it were DPLL2. v2: - Add new .update_ref_clks() hook. v3: - Renumber TBT PLL to '3' and switch _MMIO_PLL3 to _MMIO_PLL (Lucas) v4: - Don't drop _MMIO_PLL3; although it's now unused, we're going to need it very soon again for upcoming DG1 patches. (Lucas) v5: - Don't re-number TBT PLL and beyond, just use new RKL_DPLL_CFGCR macros to lookup the proper registers instead. Although renumbering the PLLs might be something we want to consider down the road, it opens a big can of worms right now since a bunch of places in the code have an assumption that the PLL table has idx==id and no holes. Renumbering creates a hole for TGL, so we'd either need to allow holes in the table or break the idx==id invariant, both of which are somewhat invasive changes to the design. Bspec: 49202 Bspec: 49443 Bspec: 50288 Bspec: 50289 Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-4-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 41 ++++++++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 6 ++- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index aeb6ee395cce5..134c2ecf4c80f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3504,13 +3504,19 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); - if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) + if (IS_ROCKETLAKE(dev_priv)) { dpll_mask = BIT(DPLL_ID_EHL_DPLL4) | BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); - else + } else if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) { + dpll_mask = + BIT(DPLL_ID_EHL_DPLL4) | + BIT(DPLL_ID_ICL_DPLL1) | + BIT(DPLL_ID_ICL_DPLL0); + } else { dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); + } port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, @@ -3791,7 +3797,12 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv, if (!(val & PLL_ENABLE)) goto out; - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + hw_state->cfgcr0 = intel_de_read(dev_priv, + RKL_DPLL_CFGCR0(id)); + hw_state->cfgcr1 = intel_de_read(dev_priv, + RKL_DPLL_CFGCR1(id)); + } else if (INTEL_GEN(dev_priv) >= 12) { hw_state->cfgcr0 = intel_de_read(dev_priv, TGL_DPLL_CFGCR0(id)); hw_state->cfgcr1 = intel_de_read(dev_priv, @@ -3844,7 +3855,10 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv, const enum intel_dpll_id id = pll->info->id; i915_reg_t cfgcr0_reg, cfgcr1_reg; - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + cfgcr0_reg = RKL_DPLL_CFGCR0(id); + cfgcr1_reg = RKL_DPLL_CFGCR1(id); + } else if (INTEL_GEN(dev_priv) >= 12) { cfgcr0_reg = TGL_DPLL_CFGCR0(id); cfgcr1_reg = TGL_DPLL_CFGCR1(id); } else { @@ -4276,6 +4290,21 @@ static const struct intel_dpll_mgr tgl_pll_mgr = { .dump_hw_state = icl_dump_hw_state, }; +static const struct dpll_info rkl_plls[] = { + { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, + { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, + { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 }, + { }, +}; + +static const struct intel_dpll_mgr rkl_pll_mgr = { + .dpll_info = rkl_plls, + .get_dplls = icl_get_dplls, + .put_dplls = icl_put_dplls, + .update_ref_clks = icl_update_dpll_ref_clks, + .dump_hw_state = icl_dump_hw_state, +}; + /** * intel_shared_dpll_init - Initialize shared DPLLs * @dev: drm device @@ -4289,7 +4318,9 @@ void intel_shared_dpll_init(struct drm_device *dev) const struct dpll_info *dpll_info; int i; - if (INTEL_GEN(dev_priv) >= 12) + if (IS_ROCKETLAKE(dev_priv)) + dpll_mgr = &rkl_pll_mgr; + else if (INTEL_GEN(dev_priv) >= 12) dpll_mgr = &tgl_pll_mgr; else if (IS_ELKHARTLAKE(dev_priv)) dpll_mgr = &ehl_pll_mgr; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00414c457941d..bfdb6d23b5d8e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10511,19 +10511,21 @@ enum skl_power_gate { #define _TGL_DPLL0_CFGCR0 0x164284 #define _TGL_DPLL1_CFGCR0 0x16428C -/* TODO: add DPLL4 */ #define _TGL_TBTPLL_CFGCR0 0x16429C #define TGL_DPLL_CFGCR0(pll) _MMIO_PLL3(pll, _TGL_DPLL0_CFGCR0, \ _TGL_DPLL1_CFGCR0, \ _TGL_TBTPLL_CFGCR0) +#define RKL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR0, \ + _TGL_DPLL1_CFGCR0) #define _TGL_DPLL0_CFGCR1 0x164288 #define _TGL_DPLL1_CFGCR1 0x164290 -/* TODO: add DPLL4 */ #define _TGL_TBTPLL_CFGCR1 0x1642A0 #define TGL_DPLL_CFGCR1(pll) _MMIO_PLL3(pll, _TGL_DPLL0_CFGCR1, \ _TGL_DPLL1_CFGCR1, \ _TGL_TBTPLL_CFGCR1) +#define RKL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR1, \ + _TGL_DPLL1_CFGCR1) #define _DKL_PHY1_BASE 0x168000 #define _DKL_PHY2_BASE 0x169000 -- GitLab From ddff9a602e5e65e99ca6516151ee775560156697 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Thu, 16 Jul 2020 15:05:50 -0700 Subject: [PATCH 0497/1494] drm/i915/rkl: Handle HTI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If HTI (also sometimes called HDPORT) is enabled at startup, it may be using some of the PHYs and DPLLs making them unavailable for general usage. Let's read out the HDPORT_STATE register and avoid making use of resources that HTI is already using. v2: - Fix minor checkpatch warnings v3: - Just readout HDPORT_STATE register once during init and then parse it later as needed. - Add a 'has_hti' device info flag to track whether we should readout HDPORT_STATE or not. We can skip the platform/flag tests later since the hti_state in dev_priv will remain 0 for platforms it does not apply to. - Move PLL masking into icl_get_combo_phy_dpll() since at the moment RKL is the only platform that has HTI. (Jose) Bspec: 49189 Bspec: 53707 Cc: Lucas De Marchi <lucas.demarchi@intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-5-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 11 +++++++++++ drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_device_info.h | 1 + 7 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1ca70f9abc8d9..714b2bc96f23c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4923,6 +4923,13 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port) return max_lanes; } +static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy) +{ + return i915->hti_state & HDPORT_ENABLED && + (i915->hti_state & HDPORT_PHY_USED_DP(phy) || + i915->hti_state & HDPORT_PHY_USED_HDMI(phy)); +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *dig_port; @@ -4930,6 +4937,18 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) bool init_hdmi, init_dp, init_lspcon = false; enum phy phy = intel_port_to_phy(dev_priv, port); + /* + * On platforms with HTI (aka HDPORT), if it's enabled at boot it may + * have taken over some of the PHYs and made them unavailable to the + * driver. In that case we should skip initializing the corresponding + * outputs. + */ + if (hti_uses_phy(dev_priv, phy)) { + drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n", + port_name(port), phy_name(phy)); + return; + } + init_hdmi = intel_bios_port_supports_dvi(dev_priv, port) || intel_bios_port_supports_hdmi(dev_priv, port); init_dp = intel_bios_port_supports_dp(dev_priv, port); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6cb66580ad2c2..db2a5a1a9b351 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -47,6 +47,7 @@ #include "display/intel_ddi.h" #include "display/intel_dp.h" #include "display/intel_dp_mst.h" +#include "display/intel_dpll_mgr.h" #include "display/intel_dsi.h" #include "display/intel_dvo.h" #include "display/intel_gmbus.h" @@ -17903,6 +17904,13 @@ int intel_modeset_init(struct drm_i915_private *i915) if (i915->max_cdclk_freq == 0) intel_update_max_cdclk(i915); + /* + * If the platform has HTI, we need to find out whether it has reserved + * any display resources before we create our display outputs. + */ + if (INTEL_INFO(i915)->display.has_hti) + i915->hti_state = intel_de_read(i915, HDPORT_STATE); + /* Just disable it once at startup */ intel_vga_disable(i915); intel_setup_outputs(i915); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 134c2ecf4c80f..81ab975fe4f05 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3475,6 +3475,14 @@ static void icl_update_active_dpll(struct intel_atomic_state *state, icl_set_active_port_dpll(crtc_state, port_dpll_id); } +static u32 intel_get_hti_plls(struct drm_i915_private *i915) +{ + if (!(i915->hti_state & HDPORT_ENABLED)) + return 0; + + return REG_FIELD_GET(HDPORT_DPLL_USED_MASK, i915->hti_state); +} + static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -3518,6 +3526,9 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); } + /* Eliminate DPLLs from consideration if reserved by HTI */ + dpll_mask &= ~intel_get_hti_plls(dev_priv); + port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, dpll_mask); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e4f7f6518945b..56dfc6d98caa3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1044,6 +1044,14 @@ struct drm_i915_private { struct intel_l3_parity l3_parity; + /* + * HTI (aka HDPORT) state read during initial hw readout. Most + * platforms don't have HTI, so this will just stay 0. Those that do + * will use this later to figure out which PLLs and PHYs are unavailable + * for driver usage. + */ + u32 hti_state; + /* * edram size in MB. * Cannot be determined by PCIID. You must always read a register. diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 2338f92ce4900..366ddfc8df6b6 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -890,6 +890,7 @@ static const struct intel_device_info rkl_info = { .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), .require_force_probe = 1, + .display.has_hti = 1, .display.has_psr_hw_tracking = 0, .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0), diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bfdb6d23b5d8e..89a9f2d8110e0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2921,6 +2921,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define MBUS_BBOX_CTL_S1 _MMIO(0x45040) #define MBUS_BBOX_CTL_S2 _MMIO(0x45044) +#define HDPORT_STATE _MMIO(0x45050) +#define HDPORT_DPLL_USED_MASK REG_GENMASK(14, 12) +#define HDPORT_PHY_USED_DP(phy) REG_BIT(2 * (phy) + 2) +#define HDPORT_PHY_USED_HDMI(phy) REG_BIT(2 * (phy) + 1) +#define HDPORT_ENABLED REG_BIT(0) + /* Make render/texture TLB fetches lower priorty than associated data * fetches. This is not turned on by default */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index fd2385457ab66..6a3d607218aac 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -146,6 +146,7 @@ enum intel_ppgtt_type { func(has_gmch); \ func(has_hdcp); \ func(has_hotplug); \ + func(has_hti); \ func(has_ipc); \ func(has_modular_fia); \ func(has_overlay); \ -- GitLab From a3db3f8496bfa138cb7ddabde6baaf3d1beb01e2 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Thu, 16 Jul 2020 15:05:51 -0700 Subject: [PATCH 0498/1494] drm/i915/rkl: Add Wa_14011224835 for PHY B initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After doing normal PHY-B initialization on Rocket Lake, we need to manually copy some additional PHY-A register values into PHY-B registers. Note that the bspec's combo phy page doesn't specify that this workaround is restricted to specific platform steppings (and doesn't even do a very good job of specifying that RKL is the only platform this is needed on), but the RKL workaround page lists this as relevant only for A and B steppings, so I'm trusting that information for now. v2: Make rkl_combo_phy_b_init_wa() static v3: - Minimize variables in WA function. (Jose) - Fix timeout duration (usec vs msec). (Jose) - Add verification of workaround. (Jose) - Fix stepping bounds in comment. Bspec: 49291 Bspec: 53273 Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-6-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- .../gpu/drm/i915/display/intel_combo_phy.c | 50 +++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 13 ++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index eccaa79cb4a9d..d88f910384285 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -255,6 +255,26 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) return phy == PHY_A; } +static bool verify_wa14011224835(struct drm_i915_private *i915) +{ + u32 grccode, val; + bool ret = true; + + grccode = REG_FIELD_GET(GRCCODE, + intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); + val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); + ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), + IREF_RCAL_ORD, val); + + grccode = REG_FIELD_GET(GRCCODE_LDO, + intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); + val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); + ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), + IREF_RCAL_ORD, val); + + return ret; +} + static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { @@ -295,6 +315,11 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy), CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE); + /* Wa_14011224835:rkl[a0..b0] */ + if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && + phy == PHY_B) + ret &= verify_wa14011224835(dev_priv); + return ret; } @@ -350,6 +375,26 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val); } +static void rkl_combo_phy_b_init_wa(struct drm_i915_private *i915) +{ + u32 grccode, val; + + wait_for_us(intel_de_read(i915, ICL_PORT_COMP_DW3(PHY_A)) & + FIRST_COMP_DONE, 100); + + grccode = REG_FIELD_GET(GRCCODE, + intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); + val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); + intel_de_rmw(i915, ICL_PORT_COMP_DW2(PHY_B), IREF_RCAL_ORD, + val | IREF_RCAL_ORD_EN); + + grccode = REG_FIELD_GET(GRCCODE_LDO, + intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); + val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); + intel_de_rmw(i915, ICL_PORT_COMP_DW6(PHY_B), RCOMPCODE_LD_CAP_OV, + val | RCOMPCODEOVEN_LDO_SYNC); +} + static void icl_combo_phys_init(struct drm_i915_private *dev_priv) { enum phy phy; @@ -415,6 +460,11 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv) val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)); val |= CL_POWER_DOWN_ENABLE; intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy), val); + + if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && + phy == PHY_B) + /* Wa_14011224835:rkl[a0..b0] */ + rkl_combo_phy_b_init_wa(dev_priv); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 89a9f2d8110e0..a0d31f3bf6345 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1911,11 +1911,16 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define CNL_PORT_COMP_DW0 _MMIO(0x162100) #define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy)) -#define COMP_INIT (1 << 31) +#define COMP_INIT REG_BIT(31) +#define GRCCODE_LDO REG_GENMASK(7, 0) #define CNL_PORT_COMP_DW1 _MMIO(0x162104) #define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy)) +#define ICL_PORT_COMP_DW2(phy) _MMIO(_ICL_PORT_COMP_DW(2, phy)) +#define IREF_RCAL_ORD_EN REG_BIT(7) +#define IREF_RCAL_ORD REG_GENMASK(6, 0) + #define CNL_PORT_COMP_DW3 _MMIO(0x16210c) #define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy)) #define PROCESS_INFO_DOT_0 (0 << 26) @@ -1928,6 +1933,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VOLTAGE_INFO_1_05V (2 << 24) #define VOLTAGE_INFO_MASK (3 << 24) #define VOLTAGE_INFO_SHIFT 24 +#define FIRST_COMP_DONE REG_BIT(22) + +#define ICL_PORT_COMP_DW6(phy) _MMIO(_ICL_PORT_COMP_DW(6, phy)) +#define GRCCODE REG_GENMASK(30, 24) +#define RCOMPCODEOVEN_LDO_SYNC REG_BIT(23) +#define RCOMPCODE_LD_CAP_OV REG_GENMASK(22, 16) #define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy)) #define IREFGEN (1 << 24) -- GitLab From 90e1329296fda234669ff97c12e39816b948de72 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 23 Jul 2020 16:38:05 +0100 Subject: [PATCH 0499/1494] drm/i915/selftests: Downgrade severity of CS/SRM frequency scaling tests Gracefully skip over the failures in the frequency scaling for the moment, the results are under review. References: https://gitlab.freedesktop.org/drm/intel/-/issues/1754 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Sundaresan, Sujaritha" <sujaritha.sundaresan@intel.com> Cc: "Ewins, Jon" <jon.ewins@intel.com> Reviewed-by: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200723153805.8076-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/selftest_rps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 8624f5d2a1f35..34b403d47840c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -700,7 +700,7 @@ int live_rps_frequency_cs(void *arg) f = act; /* may skip ahead [pcu granularity] */ } - err = -EINVAL; + err = -EINTR; /* ignore error, continue on with test */ } err_vma: @@ -841,7 +841,7 @@ int live_rps_frequency_srm(void *arg) f = act; /* may skip ahead [pcu granularity] */ } - err = -EINVAL; + err = -EINTR; /* ignore error, continue on with test */ } err_vma: -- GitLab From c746063ab14644592abfb61be3486989ff990cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Mon, 27 Jul 2020 09:47:29 -0700 Subject: [PATCH 0500/1494] drm/i915: Implement WA 14011294188 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the WA description targets the platforms it is a workaround for the affected PCHs, that is why it is being checked. v2: excluding DG1 fake PCH from WA BSpec: 52890 BSpec: 53273 BSpec: 52888 Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200727164729.28836-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display_power.c | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0c713e83274dd..788bd4516365a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5302,6 +5302,12 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + /* Wa_14011294188:ehl,jsl,tgl,rkl */ + if (INTEL_PCH_TYPE(dev_priv) >= PCH_JSP && + INTEL_PCH_TYPE(dev_priv) < PCH_DG1) + intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, 0, + PCH_DPMGUNIT_CLOCK_GATE_DISABLE); + /* 1. Enable PCH reset handshake. */ intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a0d31f3bf6345..5eae593ee784f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8730,6 +8730,7 @@ enum { #define PCH_GMBUSUNIT_CLOCK_GATE_DISABLE (1 << 31) #define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1 << 30) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1 << 29) +#define PCH_DPMGUNIT_CLOCK_GATE_DISABLE (1 << 15) #define PCH_CPUNIT_CLOCK_GATE_DISABLE (1 << 14) #define CNP_PWM_CGE_GATING_DISABLE (1 << 13) #define PCH_LP_PARTITION_LEVEL_DISABLE (1 << 12) -- GitLab From 2982ded2ff5ce0cf1a49bc39a526da182782b664 Mon Sep 17 00:00:00 2001 From: Uma Shankar <uma.shankar@intel.com> Date: Thu, 16 Jul 2020 20:28:57 +0530 Subject: [PATCH 0501/1494] drm/i915/display/fbc: Disable fbc by default on TGL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fbc is causing random underruns in CI execution on TGL platforms. Disabling the same while the problem is being debugged and analyzed. v2: Moved the check below the module param check (Ville) Cc: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Uma Shankar <uma.shankar@intel.com> Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716145857.6911-1-uma.shankar@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_fbc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3a4f980788a62..195b8be4532af 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1426,6 +1426,13 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) if (!HAS_FBC(dev_priv)) return 0; + /* + * Fbc is causing random underruns in CI execution on TGL platforms. + * Disabling the same while the problem is being debugged and analyzed. + */ + if (IS_TIGERLAKE(dev_priv)) + return 0; + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) return 1; -- GitLab From 98ef067453709444a264939940f7b3a5dfdfa09e Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:06:00 +0100 Subject: [PATCH 0502/1494] drm/i915: Copy default modparams to mock i915_device Since we use the module parameters stored inside the drm_i915_device itself, we need to ensure the mock i915_device also sets up the right defaults. Fixes: 8a25c4be583d ("drm/i915/params: switch to device specific parameters") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Jani Nikula <jani.nikula@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728150600.4509-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 9a46be05425a4..ce4d4303229c9 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -77,6 +77,7 @@ static void mock_device_release(struct drm_device *dev) drm_mode_config_cleanup(&i915->drm); out: + i915_params_free(&i915->params); put_device(&i915->drm.pdev->dev); i915->drm.pdev = NULL; } @@ -159,6 +160,8 @@ struct drm_i915_private *mock_gem_device(void) i915->drm.pdev = pdev; drmm_add_final_kfree(&i915->drm, i915); + i915_params_copy(&i915->params, &i915_modparams); + intel_runtime_pm_init_early(&i915->runtime_pm); /* Using the global GTT may ask questions about KMS users, so prepare */ -- GitLab From e310b4352cf471ba73119ec31abb1ef72086824d Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:21:10 +0100 Subject: [PATCH 0503/1494] drm/i915/selftests: Add compiler paranoia for checking HWSP values Since we want to read the values from the HWSP as written to by the GPU, warn the compiler that the values are volatile. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728152110.830-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/selftest_timeline.c | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index fb5b7d3498a67..6564c989dbee4 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -491,7 +491,7 @@ checked_intel_timeline_create(struct intel_gt *gt) if (IS_ERR(tl)) return tl; - if (*tl->hwsp_seqno != tl->seqno) { + if (READ_ONCE(*tl->hwsp_seqno) != tl->seqno) { pr_err("Timeline created with incorrect breadcrumb, found %x, expected %x\n", *tl->hwsp_seqno, tl->seqno); intel_timeline_put(tl); @@ -561,9 +561,9 @@ static int live_hwsp_engine(void *arg) for (n = 0; n < count; n++) { struct intel_timeline *tl = timelines[n]; - if (!err && *tl->hwsp_seqno != n) { - pr_err("Invalid seqno stored in timeline %lu @ %x, found 0x%x\n", - n, tl->hwsp_offset, *tl->hwsp_seqno); + if (!err && READ_ONCE(*tl->hwsp_seqno) != n) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x, found 0x%x\n", + n, tl->fence_context, tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } @@ -633,9 +633,9 @@ static int live_hwsp_alternate(void *arg) for (n = 0; n < count; n++) { struct intel_timeline *tl = timelines[n]; - if (!err && *tl->hwsp_seqno != n) { - pr_err("Invalid seqno stored in timeline %lu @ %x, found 0x%x\n", - n, tl->hwsp_offset, *tl->hwsp_seqno); + if (!err && READ_ONCE(*tl->hwsp_seqno) != n) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x, found 0x%x\n", + n, tl->fence_context, tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } @@ -733,7 +733,8 @@ static int live_hwsp_wrap(void *arg) goto out; } - if (*hwsp_seqno[0] != seqno[0] || *hwsp_seqno[1] != seqno[1]) { + if (READ_ONCE(*hwsp_seqno[0]) != seqno[0] || + READ_ONCE(*hwsp_seqno[1]) != seqno[1]) { pr_err("Bad timeline values: found (%x, %x), expected (%x, %x)\n", *hwsp_seqno[0], *hwsp_seqno[1], seqno[0], seqno[1]); @@ -966,9 +967,10 @@ static int live_hwsp_recycle(void *arg) break; } - if (*tl->hwsp_seqno != count) { - pr_err("Invalid seqno stored in timeline %lu @ tl->hwsp_offset, found 0x%x\n", - count, *tl->hwsp_seqno); + if (READ_ONCE(*tl->hwsp_seqno) != count) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x found 0x%x\n", + count, tl->fence_context, + tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } -- GitLab From 1840d40ac690e2ad60fa52fc3156249802e27aa9 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:22:19 +0100 Subject: [PATCH 0504/1494] drm/i915: Remove gen check before calling intel_rps_boost It's been a while since gen6_rps_boost() [that only worked on gen6+] was replaced by intel_rps_boost() that understood itself when rps was active. Since the intel_rps_boost() is gen-agnostic, just call it. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728152219.1387-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_request.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 0b2fe55e61945..7a05850ca9318 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1783,11 +1783,8 @@ long i915_request_wait(struct i915_request *rq, * but at a cost of spending more power processing the workload * (bad for battery). */ - if (flags & I915_WAIT_PRIORITY) { - if (!i915_request_started(rq) && - INTEL_GEN(rq->engine->i915) >= 6) - intel_rps_boost(rq); - } + if (flags & I915_WAIT_PRIORITY && !i915_request_started(rq)) + intel_rps_boost(rq); wait.tsk = current; if (dma_fence_add_callback(&rq->fence, &wait.cb, request_wait_wake)) -- GitLab From a22b1a9bb0d72a58d5b836653f28d97ee8fea1c4 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 14:09:12 +0100 Subject: [PATCH 0505/1494] drm/i915/display: Check for an LPSP encoder before dereferencing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid a GPF at <1>[ 20.177320] BUG: kernel NULL pointer dereference, address: 000000000000007c <1>[ 20.177322] #PF: supervisor read access in kernel mode <1>[ 20.177323] #PF: error_code(0x0000) - not-present page <6>[ 20.177324] PGD 0 P4D 0 <4>[ 20.177327] Oops: 0000 [#1] PREEMPT SMP PTI <4>[ 20.177328] CPU: 1 PID: 944 Comm: debugfs_test Not tainted 5.8.0-rc7-CI-CI_DRM_8814+ #1 <4>[ 20.177330] Hardware name: Dell Inc. XPS 13 9360/0823VW, BIOS 2.9.0 07/09/2018 <4>[ 20.177372] RIP: 0010:i915_lpsp_capability_show+0x44/0xc0 [i915] <4>[ 20.177374] Code: 0f b6 81 ca 0d 00 00 3c 0b 74 77 76 19 3c 0c 75 44 83 7e 7c 01 7e 2f 48 c7 c6 d7 b9 47 a0 e8 43 df 06 e1 31 c0 c3 3c 09 72 2b <8b> 46 7c 85 c0 75 e6 8b 82 e4 00 00 00 89 c2 83 e2 fb 83 fa 0a 74 <4>[ 20.177376] RSP: 0018:ffffc90000cebe38 EFLAGS: 00010246 <4>[ 20.177377] RAX: 0000000000000009 RBX: ffff888267fe6a58 RCX: ffff888252d10000 <4>[ 20.177378] RDX: ffff88824a9a4000 RSI: 0000000000000000 RDI: ffff888267fe6a30 <4>[ 20.177379] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001 <4>[ 20.177380] R10: 0000000000000001 R11: 0000000000000000 R12: ffffc90000cebf08 <4>[ 20.177381] R13: 00000000ffffffff R14: 0000000000000001 R15: ffff888267fe6a30 <4>[ 20.177383] FS: 00007f6f9c6b5e40(0000) GS:ffff888276480000(0000) knlGS:0000000000000000 <4>[ 20.177384] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 20.177385] CR2: 000000000000007c CR3: 0000000255f04006 CR4: 00000000003606e0 <4>[ 20.177386] Call Trace: <4>[ 20.177390] seq_read+0xcb/0x420 which is presumably from having no encoder attached at that time. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2175 Fixes: 8806211fe7b3 ("drm/i915: Add i915_lpsp_capability debugfs") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Animesh Manna <animesh.manna@intel.com> Cc: Anshuman Gupta <anshuman.gupta@intel.com> Cc: Uma Shankar <uma.shankar@intel.com> Cc: "Ville Syrjälä" <ville.syrjala@linux.intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729130912.30093-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3644752cc5ece..5a5cfe25085b4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -2044,9 +2044,12 @@ DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability); static int i915_lpsp_capability_show(struct seq_file *m, void *data) { struct drm_connector *connector = m->private; - struct intel_encoder *encoder = - intel_attached_encoder(to_intel_connector(connector)); struct drm_i915_private *i915 = to_i915(connector->dev); + struct intel_encoder *encoder; + + encoder = intel_attached_encoder(to_intel_connector(connector)); + if (!encoder) + return -ENODEV; if (connector->status != connector_status_connected) return -ENODEV; -- GitLab From 9a0a3bebb0c5885784a048a65f4661a2464cc920 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:09 +0100 Subject: [PATCH 0506/1494] drm/i915: Add a couple of missing i915_active_fini() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use i915_active_fini() as a debug check on the i915_active state before freeing. If we forget to call it, we may end up angering the debugobjects contained within. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_frontbuffer.c | 2 ++ drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 2979ed2588eb9..d898b370d7a4f 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -232,6 +232,8 @@ static void frontbuffer_release(struct kref *ref) RCU_INIT_POINTER(obj->frontbuffer, NULL); spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock); + i915_active_fini(&front->write); + i915_gem_object_put(obj); kfree_rcu(front, rcu); } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index 73243ba59c7d2..e73854dd2fe0d 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -47,7 +47,10 @@ static int pulse_active(struct i915_active *active) static void pulse_free(struct kref *kref) { - kfree(container_of(kref, struct pulse, kref)); + struct pulse *p = container_of(kref, typeof(*p), kref); + + i915_active_fini(&p->active); + kfree(p); } static void pulse_put(struct pulse *p) -- GitLab From ecb40d0826fda213ebb58d49e7d5b4752480e130 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Fri, 12 Jun 2020 13:47:34 -0700 Subject: [PATCH 0507/1494] drm/i915: Update bw_buddy pagemask table A recent bspec update removed the LPDDR4 single channel entry from the buddy register table, but added a new four-channel entry. Workaround 1409767108 hasn't been updated with any guidance for four channel configurations, so we leave that alternate table unchanged for now. Bspec 49218 Fixes: 3fa01d642fa7 ("drm/i915/tgl: Program BW_BUDDY registers during display init") Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200612204734.3674650-1-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 788bd4516365a..9f0241a53a452 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5240,10 +5240,10 @@ struct buddy_page_mask { }; static const struct buddy_page_mask tgl_buddy_page_masks[] = { - { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0xE }, { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0xF }, { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1C }, { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x1F }, + { .num_channels = 4, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x38 }, {} }; -- GitLab From e714977eef8fb40ea8234527d1b0c9d238bf1661 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Date: Sun, 2 Aug 2020 12:56:55 +0100 Subject: [PATCH 0508/1494] drm/i915: Fix wrong return value In function i915_active_acquire_preallocate_barrier(), not all paths have the return value set correctly, and in case of memory allocation failure, a negative error code should be returned. Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200802115655.25568-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_active.c | 7 ++----- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index d960d0be5bd2f..1e12532074258 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -758,7 +758,6 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, intel_engine_mask_t tmp, mask = engine->mask; struct llist_node *first = NULL, *last = NULL; struct intel_gt *gt = engine->gt; - int err; GEM_BUG_ON(i915_active_is_idle(ref)); @@ -781,10 +780,8 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, node = reuse_idle_barrier(ref, idx); if (!node) { node = kmem_cache_alloc(global.slab_cache, GFP_KERNEL); - if (!node) { - err = ENOMEM; + if (!node) goto unwind; - } RCU_INIT_POINTER(node->base.fence, NULL); node->base.cb.func = node_retire; @@ -832,7 +829,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, kmem_cache_free(global.slab_cache, node); } - return err; + return -ENOMEM; } void i915_active_acquire_barrier(struct i915_active *ref) diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 57dd6f5122eed..c1dcd4b91bda0 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -331,7 +331,7 @@ static int __igt_breadcrumbs_smoketest(void *arg) if (!wait) { i915_sw_fence_commit(submit); heap_fence_put(submit); - err = ENOMEM; + err = -ENOMEM; break; } -- GitLab From 66b51b801d05ee54a0f23628cb8220189adb715e Mon Sep 17 00:00:00 2001 From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Date: Sun, 2 Aug 2020 19:15:35 +0800 Subject: [PATCH 0509/1494] drm/i915: Fix wrong return value in intel_atomic_check() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case of calling check_digital_port_conflicts() failed, a negative error code -EINVAL should be returned. Fixes: bf5da83e4bd80 ("drm/i915: Move check_digital_port_conflicts() earier") Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200802111535.5200-1-tianjia.zhang@linux.alibaba.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index db2a5a1a9b351..522c772a21117 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14940,7 +14940,7 @@ static int intel_atomic_check(struct drm_device *dev, if (any_ms && !check_digital_port_conflicts(state)) { drm_dbg_kms(&dev_priv->drm, "rejecting conflicting digital port configuration\n"); - ret = EINVAL; + ret = -EINVAL; goto fail; } -- GitLab From 3f8210fd22d0c02faa18b36974debf1ad25b7f92 Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Mon, 3 Aug 2020 21:40:24 -0700 Subject: [PATCH 0510/1494] Revert "drm/i915/rkl: Add Wa_14011224835 for PHY B initialization" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware team has dropped this workaround from the bspec; it is no longer needed. This reverts commit 111822b21be995a3a4a731066db3d820523c57f7. Bspec: 49291 Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200804044024.1931170-1-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- .../gpu/drm/i915/display/intel_combo_phy.c | 50 ------------------- drivers/gpu/drm/i915/i915_reg.h | 13 +---- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index d88f910384285..eccaa79cb4a9d 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -255,26 +255,6 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) return phy == PHY_A; } -static bool verify_wa14011224835(struct drm_i915_private *i915) -{ - u32 grccode, val; - bool ret = true; - - grccode = REG_FIELD_GET(GRCCODE, - intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); - val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); - ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), - IREF_RCAL_ORD, val); - - grccode = REG_FIELD_GET(GRCCODE_LDO, - intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); - val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); - ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), - IREF_RCAL_ORD, val); - - return ret; -} - static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { @@ -315,11 +295,6 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy), CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE); - /* Wa_14011224835:rkl[a0..b0] */ - if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && - phy == PHY_B) - ret &= verify_wa14011224835(dev_priv); - return ret; } @@ -375,26 +350,6 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val); } -static void rkl_combo_phy_b_init_wa(struct drm_i915_private *i915) -{ - u32 grccode, val; - - wait_for_us(intel_de_read(i915, ICL_PORT_COMP_DW3(PHY_A)) & - FIRST_COMP_DONE, 100); - - grccode = REG_FIELD_GET(GRCCODE, - intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); - val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); - intel_de_rmw(i915, ICL_PORT_COMP_DW2(PHY_B), IREF_RCAL_ORD, - val | IREF_RCAL_ORD_EN); - - grccode = REG_FIELD_GET(GRCCODE_LDO, - intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); - val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); - intel_de_rmw(i915, ICL_PORT_COMP_DW6(PHY_B), RCOMPCODE_LD_CAP_OV, - val | RCOMPCODEOVEN_LDO_SYNC); -} - static void icl_combo_phys_init(struct drm_i915_private *dev_priv) { enum phy phy; @@ -460,11 +415,6 @@ static void icl_combo_phys_init(struct drm_i915_private *dev_priv) val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)); val |= CL_POWER_DOWN_ENABLE; intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy), val); - - if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && - phy == PHY_B) - /* Wa_14011224835:rkl[a0..b0] */ - rkl_combo_phy_b_init_wa(dev_priv); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5eae593ee784f..2b403df03404f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1911,16 +1911,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define CNL_PORT_COMP_DW0 _MMIO(0x162100) #define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy)) -#define COMP_INIT REG_BIT(31) -#define GRCCODE_LDO REG_GENMASK(7, 0) +#define COMP_INIT (1 << 31) #define CNL_PORT_COMP_DW1 _MMIO(0x162104) #define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy)) -#define ICL_PORT_COMP_DW2(phy) _MMIO(_ICL_PORT_COMP_DW(2, phy)) -#define IREF_RCAL_ORD_EN REG_BIT(7) -#define IREF_RCAL_ORD REG_GENMASK(6, 0) - #define CNL_PORT_COMP_DW3 _MMIO(0x16210c) #define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy)) #define PROCESS_INFO_DOT_0 (0 << 26) @@ -1933,12 +1928,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VOLTAGE_INFO_1_05V (2 << 24) #define VOLTAGE_INFO_MASK (3 << 24) #define VOLTAGE_INFO_SHIFT 24 -#define FIRST_COMP_DONE REG_BIT(22) - -#define ICL_PORT_COMP_DW6(phy) _MMIO(_ICL_PORT_COMP_DW(6, phy)) -#define GRCCODE REG_GENMASK(30, 24) -#define RCOMPCODEOVEN_LDO_SYNC REG_BIT(23) -#define RCOMPCODE_LD_CAP_OV REG_GENMASK(22, 16) #define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy)) #define IREFGEN (1 << 24) -- GitLab From cda9edd02425d7902714c60a6f6e31881d2f2741 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Date: Tue, 4 Aug 2020 11:59:53 +0300 Subject: [PATCH 0511/1494] drm/i915: introduce a mechanism to extend execbuf2 We're planning to use this for a couple of new feature where we need to provide additional parameters to execbuf. v2: Check for invalid flags in execbuffer2 (Lionel) v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris) v4: Rebase Move array fence parsing in i915_gem_do_execbuffer() Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200804085954.350343-2-lionel.g.landwerlin@intel.com Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2901 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 131 +++++++++++------- include/uapi/drm/i915_drm.h | 25 +++- 2 files changed, 102 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 6b4ec66cb558d..09d2f955b11e3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -26,6 +26,7 @@ #include "i915_gem_ioctls.h" #include "i915_sw_fence_work.h" #include "i915_trace.h" +#include "i915_user_extensions.h" struct eb_vma { struct i915_vma *vma; @@ -281,6 +282,13 @@ struct i915_execbuffer { int lut_size; struct hlist_head *buckets; /** ht for relocation handles */ struct eb_vma_array *array; + + struct i915_eb_fence { + struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ + } *fences; + u32 n_fences; + + u64 extension_flags; /** Available extensions parameters */ }; static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) @@ -1622,7 +1630,8 @@ static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) return -EINVAL; /* Kernel clipping was a DRI1 misfeature */ - if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) { + if (!(exec->flags & (I915_EXEC_FENCE_ARRAY | + I915_EXEC_USE_EXTENSIONS))) { if (exec->num_cliprects || exec->cliprects_ptr) return -EINVAL; } @@ -2201,41 +2210,41 @@ eb_pin_engine(struct i915_execbuffer *eb, } static void -__free_fence_array(struct drm_syncobj **fences, unsigned int n) +__free_fence_array(struct i915_eb_fence *fences, unsigned int n) { while (n--) - drm_syncobj_put(ptr_mask_bits(fences[n], 2)); + drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2)); kvfree(fences); } -static struct drm_syncobj ** +static int get_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct drm_file *file) + struct i915_execbuffer *eb) { const unsigned long nfences = args->num_cliprects; struct drm_i915_gem_exec_fence __user *user; - struct drm_syncobj **fences; + struct i915_eb_fence *fences; unsigned long n; int err; if (!(args->flags & I915_EXEC_FENCE_ARRAY)) - return NULL; + return 0; /* Check multiplication overflow for access_ok() and kvmalloc_array() */ BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); if (nfences > min_t(unsigned long, ULONG_MAX / sizeof(*user), SIZE_MAX / sizeof(*fences))) - return ERR_PTR(-EINVAL); + return -EINVAL; user = u64_to_user_ptr(args->cliprects_ptr); if (!access_ok(user, nfences * sizeof(*user))) - return ERR_PTR(-EFAULT); + return -EFAULT; fences = kvmalloc_array(nfences, sizeof(*fences), __GFP_NOWARN | GFP_KERNEL); if (!fences) - return ERR_PTR(-ENOMEM); + return -ENOMEM; for (n = 0; n < nfences; n++) { struct drm_i915_gem_exec_fence fence; @@ -2251,7 +2260,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args, goto err; } - syncobj = drm_syncobj_find(file, fence.handle); + syncobj = drm_syncobj_find(eb->file, fence.handle); if (!syncobj) { DRM_DEBUG("Invalid syncobj handle provided\n"); err = -ENOENT; @@ -2261,38 +2270,31 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args, BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); - fences[n] = ptr_pack_bits(syncobj, fence.flags, 2); + fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2); } - return fences; + eb->fences = fences; + eb->n_fences = nfences; + + return 0; err: __free_fence_array(fences, n); - return ERR_PTR(err); -} - -static void -put_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct drm_syncobj **fences) -{ - if (fences) - __free_fence_array(fences, args->num_cliprects); + return err; } static int -await_fence_array(struct i915_execbuffer *eb, - struct drm_syncobj **fences) +await_fence_array(struct i915_execbuffer *eb) { - const unsigned int nfences = eb->args->num_cliprects; unsigned int n; int err; - for (n = 0; n < nfences; n++) { + for (n = 0; n < eb->n_fences; n++) { struct drm_syncobj *syncobj; struct dma_fence *fence; unsigned int flags; - syncobj = ptr_unpack_bits(fences[n], &flags, 2); + syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); if (!(flags & I915_EXEC_FENCE_WAIT)) continue; @@ -2310,18 +2312,16 @@ await_fence_array(struct i915_execbuffer *eb, } static void -signal_fence_array(struct i915_execbuffer *eb, - struct drm_syncobj **fences) +signal_fence_array(struct i915_execbuffer *eb) { - const unsigned int nfences = eb->args->num_cliprects; struct dma_fence * const fence = &eb->request->fence; unsigned int n; - for (n = 0; n < nfences; n++) { + for (n = 0; n < eb->n_fences; n++) { struct drm_syncobj *syncobj; unsigned int flags; - syncobj = ptr_unpack_bits(fences[n], &flags, 2); + syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); if (!(flags & I915_EXEC_FENCE_SIGNAL)) continue; @@ -2370,12 +2370,38 @@ static void eb_request_add(struct i915_execbuffer *eb) mutex_unlock(&tl->mutex); } +static const i915_user_extension_fn execbuf_extensions[] = { +}; + +static int +parse_execbuf2_extensions(struct drm_i915_gem_execbuffer2 *args, + struct i915_execbuffer *eb) +{ + eb->extension_flags = 0; + + if (!(args->flags & I915_EXEC_USE_EXTENSIONS)) + return 0; + + /* The execbuf2 extension mechanism reuses cliprects_ptr. So we cannot + * have another flag also using it at the same time. + */ + if (eb->args->flags & I915_EXEC_FENCE_ARRAY) + return -EINVAL; + + if (args->num_cliprects != 0) + return -EINVAL; + + return i915_user_extensions(u64_to_user_ptr(args->cliprects_ptr), + execbuf_extensions, + ARRAY_SIZE(execbuf_extensions), + eb); +} + static int i915_gem_do_execbuffer(struct drm_device *dev, struct drm_file *file, struct drm_i915_gem_execbuffer2 *args, - struct drm_i915_gem_exec_object2 *exec, - struct drm_syncobj **fences) + struct drm_i915_gem_exec_object2 *exec) { struct drm_i915_private *i915 = to_i915(dev); struct i915_execbuffer eb; @@ -2405,6 +2431,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.batch_len = args->batch_len; eb.trampoline = NULL; + eb.fences = NULL; + eb.n_fences = 0; + eb.batch_flags = 0; if (args->flags & I915_EXEC_SECURE) { if (INTEL_GEN(i915) >= 11) @@ -2441,10 +2470,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, } } - err = eb_create(&eb); + err = parse_execbuf2_extensions(args, &eb); if (err) goto err_out_fence; + err = get_fence_array(args, &eb); + if (err) + goto err_arr_fence; + + err = eb_create(&eb); + if (err) + goto err_arr_fence; + GEM_BUG_ON(!eb.lut_size); err = eb_select_context(&eb); @@ -2539,8 +2576,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_request; } - if (fences) { - err = await_fence_array(&eb, fences); + if (eb.n_fences) { + err = await_fence_array(&eb); if (err) goto err_request; } @@ -2571,8 +2608,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, i915_request_get(eb.request); eb_request_add(&eb); - if (fences) - signal_fence_array(&eb, fences); + if (eb.n_fences) + signal_fence_array(&eb); if (out_fence) { if (err == 0) { @@ -2600,6 +2637,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, i915_gem_context_put(eb.gem_context); err_destroy: eb_destroy(&eb); +err_arr_fence: + __free_fence_array(eb.fences, eb.n_fences); err_out_fence: if (out_fence_fd != -1) put_unused_fd(out_fence_fd); @@ -2699,7 +2738,7 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, exec2_list[i].flags = 0; } - err = i915_gem_do_execbuffer(dev, file, &exec2, exec2_list, NULL); + err = i915_gem_do_execbuffer(dev, file, &exec2, exec2_list); if (exec2.flags & __EXEC_HAS_RELOC) { struct drm_i915_gem_exec_object __user *user_exec_list = u64_to_user_ptr(args->buffers_ptr); @@ -2731,7 +2770,6 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_execbuffer2 *args = data; struct drm_i915_gem_exec_object2 *exec2_list; - struct drm_syncobj **fences = NULL; const size_t count = args->buffer_count; int err; @@ -2759,15 +2797,7 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, return -EFAULT; } - if (args->flags & I915_EXEC_FENCE_ARRAY) { - fences = get_fence_array(args, file); - if (IS_ERR(fences)) { - kvfree(exec2_list); - return PTR_ERR(fences); - } - } - - err = i915_gem_do_execbuffer(dev, file, args, exec2_list, fences); + err = i915_gem_do_execbuffer(dev, file, args, exec2_list); /* * Now that we have begun execution of the batchbuffer, we ignore @@ -2808,7 +2838,6 @@ end:; } args->flags &= ~__I915_EXEC_UNKNOWN_FLAGS; - put_fence_array(args, fences); kvfree(exec2_list); return err; } diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 00546062e0235..dcada8c3a6933 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1046,6 +1046,10 @@ struct drm_i915_gem_exec_fence { __u32 flags; }; +enum drm_i915_gem_execbuffer_ext { + DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */ +}; + struct drm_i915_gem_execbuffer2 { /** * List of gem_exec_object2 structs @@ -1062,8 +1066,14 @@ struct drm_i915_gem_execbuffer2 { __u32 num_cliprects; /** * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY - * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a - * struct drm_i915_gem_exec_fence *fences. + * & I915_EXEC_USE_EXTENSIONS are not set. + * + * If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array + * of struct drm_i915_gem_exec_fence and num_cliprects is the length + * of the array. + * + * If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a + * single struct i915_user_extension and num_cliprects is 0. */ __u64 cliprects_ptr; #define I915_EXEC_RING_MASK (0x3f) @@ -1181,7 +1191,16 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_FENCE_SUBMIT (1 << 20) -#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1)) +/* + * Setting I915_EXEC_USE_EXTENSIONS implies that + * drm_i915_gem_execbuffer2.cliprects_ptr is treated as a pointer to an linked + * list of i915_user_extension. Each i915_user_extension node is the base of a + * larger structure. The list of supported structures are listed in the + * drm_i915_gem_execbuffer_ext enum. + */ +#define I915_EXEC_USE_EXTENSIONS (1 << 21) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1)) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ -- GitLab From 13149e8bafc4657254831ba6c16ed8780aa64a06 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Date: Tue, 4 Aug 2020 11:59:54 +0300 Subject: [PATCH 0512/1494] drm/i915: add syncobj timeline support Introduces a new parameters to execbuf so that we can specify syncobj handles as well as timeline points. v2: Reuse i915_user_extension_fn v3: Check that the chained extension is only present once (Chris) v4: Check that dma_fence_chain_find_seqno returns a non NULL fence (Lionel) v5: Use BIT_ULL (Chris) v6: Fix issue with already signaled timeline points, dma_fence_chain_find_seqno() setting fence to NULL (Chris) v7: Report ENOENT with invalid syncobj handle (Lionel) v8: Check for out of order timeline point insertion (Chris) v9: After explanations on https://lists.freedesktop.org/archives/dri-devel/2019-August/229287.html drop the ordering check from v8 (Lionel) v10: Set first extension enum item to 1 (Jason) v11: Rebase v12: Allow multiple extension nodes of timeline syncobj (Chris) Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Co-authored-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v11) Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200804085954.350343-3-lionel.g.landwerlin@intel.com Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2901 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 312 ++++++++++++++---- drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/i915/i915_getparam.c | 1 + include/uapi/drm/i915_drm.h | 38 ++- 4 files changed, 279 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 09d2f955b11e3..02b1630f513e8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -223,6 +223,13 @@ struct eb_vma_array { * the batchbuffer in trusted mode, otherwise the ioctl is rejected. */ +struct eb_fence { + struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ + struct dma_fence *dma_fence; + u64 value; + struct dma_fence_chain *chain_fence; +}; + struct i915_execbuffer { struct drm_i915_private *i915; /** i915 backpointer */ struct drm_file *file; /** per-file lookup tables and limits */ @@ -283,12 +290,8 @@ struct i915_execbuffer { struct hlist_head *buckets; /** ht for relocation handles */ struct eb_vma_array *array; - struct i915_eb_fence { - struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ - } *fences; - u32 n_fences; - - u64 extension_flags; /** Available extensions parameters */ + struct eb_fence *fences; + unsigned long num_fences; }; static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) @@ -2210,77 +2213,222 @@ eb_pin_engine(struct i915_execbuffer *eb, } static void -__free_fence_array(struct i915_eb_fence *fences, unsigned int n) +__free_fence_array(struct eb_fence *fences, unsigned int n) { - while (n--) + while (n--) { drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2)); + dma_fence_put(fences[n].dma_fence); + kfree(fences[n].chain_fence); + } kvfree(fences); } static int -get_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct i915_execbuffer *eb) +add_timeline_fence_array(struct i915_execbuffer *eb, + const struct drm_i915_gem_execbuffer_ext_timeline_fences *timeline_fences) { - const unsigned long nfences = args->num_cliprects; - struct drm_i915_gem_exec_fence __user *user; - struct i915_eb_fence *fences; - unsigned long n; - int err; + struct drm_i915_gem_exec_fence __user *user_fences; + u64 __user *user_values; + struct eb_fence *f; + u64 nfences; + int err = 0; - if (!(args->flags & I915_EXEC_FENCE_ARRAY)) + nfences = timeline_fences->fence_count; + if (!nfences) return 0; /* Check multiplication overflow for access_ok() and kvmalloc_array() */ BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); if (nfences > min_t(unsigned long, - ULONG_MAX / sizeof(*user), - SIZE_MAX / sizeof(*fences))) + ULONG_MAX / sizeof(*user_fences), + SIZE_MAX / sizeof(*f)) - eb->num_fences) return -EINVAL; - user = u64_to_user_ptr(args->cliprects_ptr); - if (!access_ok(user, nfences * sizeof(*user))) + user_fences = u64_to_user_ptr(timeline_fences->handles_ptr); + if (!access_ok(user_fences, nfences * sizeof(*user_fences))) + return -EFAULT; + + user_values = u64_to_user_ptr(timeline_fences->values_ptr); + if (!access_ok(user_values, nfences * sizeof(*user_values))) return -EFAULT; - fences = kvmalloc_array(nfences, sizeof(*fences), - __GFP_NOWARN | GFP_KERNEL); - if (!fences) + f = krealloc(eb->fences, + (eb->num_fences + nfences) * sizeof(*f), + __GFP_NOWARN | GFP_KERNEL); + if (!f) return -ENOMEM; - for (n = 0; n < nfences; n++) { - struct drm_i915_gem_exec_fence fence; + eb->fences = f; + f += eb->num_fences; + + BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & + ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); + + while (nfences--) { + struct drm_i915_gem_exec_fence user_fence; struct drm_syncobj *syncobj; + struct dma_fence *fence = NULL; + u64 point; + + if (__copy_from_user(&user_fence, + user_fences++, + sizeof(user_fence))) + return -EFAULT; + + if (user_fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) + return -EINVAL; + + if (__get_user(point, user_values++)) + return -EFAULT; + + syncobj = drm_syncobj_find(eb->file, user_fence.handle); + if (!syncobj) { + DRM_DEBUG("Invalid syncobj handle provided\n"); + return -ENOENT; + } + + fence = drm_syncobj_fence_get(syncobj); - if (__copy_from_user(&fence, user++, sizeof(fence))) { - err = -EFAULT; - goto err; + if (!fence && user_fence.flags && + !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + DRM_DEBUG("Syncobj handle has no fence\n"); + drm_syncobj_put(syncobj); + return -EINVAL; } - if (fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) { - err = -EINVAL; - goto err; + if (fence) + err = dma_fence_chain_find_seqno(&fence, point); + + if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + DRM_DEBUG("Syncobj handle missing requested point %llu\n", point); + drm_syncobj_put(syncobj); + return err; + } + + /* + * A point might have been signaled already and + * garbage collected from the timeline. In this case + * just ignore the point and carry on. + */ + if (!fence && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + drm_syncobj_put(syncobj); + continue; + } + + /* + * For timeline syncobjs we need to preallocate chains for + * later signaling. + */ + if (point != 0 && user_fence.flags & I915_EXEC_FENCE_SIGNAL) { + /* + * Waiting and signaling the same point (when point != + * 0) would break the timeline. + */ + if (user_fence.flags & I915_EXEC_FENCE_WAIT) { + DRM_DEBUG("Trying to wait & signal the same timeline point.\n"); + dma_fence_put(fence); + drm_syncobj_put(syncobj); + return -EINVAL; + } + + f->chain_fence = + kmalloc(sizeof(*f->chain_fence), + GFP_KERNEL); + if (!f->chain_fence) { + drm_syncobj_put(syncobj); + dma_fence_put(fence); + return -ENOMEM; + } + } else { + f->chain_fence = NULL; } - syncobj = drm_syncobj_find(eb->file, fence.handle); + f->syncobj = ptr_pack_bits(syncobj, user_fence.flags, 2); + f->dma_fence = fence; + f->value = point; + f++; + eb->num_fences++; + } + + return 0; +} + +static int add_fence_array(struct i915_execbuffer *eb) +{ + struct drm_i915_gem_execbuffer2 *args = eb->args; + struct drm_i915_gem_exec_fence __user *user; + unsigned long num_fences = args->num_cliprects; + struct eb_fence *f; + + if (!(args->flags & I915_EXEC_FENCE_ARRAY)) + return 0; + + if (!num_fences) + return 0; + + /* Check multiplication overflow for access_ok() and kvmalloc_array() */ + BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); + if (num_fences > min_t(unsigned long, + ULONG_MAX / sizeof(*user), + SIZE_MAX / sizeof(*f) - eb->num_fences)) + return -EINVAL; + + user = u64_to_user_ptr(args->cliprects_ptr); + if (!access_ok(user, num_fences * sizeof(*user))) + return -EFAULT; + + f = krealloc(eb->fences, + (eb->num_fences + num_fences) * sizeof(*f), + __GFP_NOWARN | GFP_KERNEL); + if (!f) + return -ENOMEM; + + eb->fences = f; + f += eb->num_fences; + while (num_fences--) { + struct drm_i915_gem_exec_fence user_fence; + struct drm_syncobj *syncobj; + struct dma_fence *fence = NULL; + + if (__copy_from_user(&user_fence, user++, sizeof(user_fence))) + return -EFAULT; + + if (user_fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) + return -EINVAL; + + syncobj = drm_syncobj_find(eb->file, user_fence.handle); if (!syncobj) { DRM_DEBUG("Invalid syncobj handle provided\n"); - err = -ENOENT; - goto err; + return -ENOENT; + } + + if (user_fence.flags & I915_EXEC_FENCE_WAIT) { + fence = drm_syncobj_fence_get(syncobj); + if (!fence) { + DRM_DEBUG("Syncobj handle has no fence\n"); + drm_syncobj_put(syncobj); + return -EINVAL; + } } BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); - fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2); + f->syncobj = ptr_pack_bits(syncobj, user_fence.flags, 2); + f->dma_fence = fence; + f->value = 0; + f->chain_fence = NULL; + f++; + eb->num_fences++; } - eb->fences = fences; - eb->n_fences = nfences; - return 0; +} -err: - __free_fence_array(fences, n); - return err; +static void put_fence_array(struct eb_fence *fences, int num_fences) +{ + if (fences) + __free_fence_array(fences, num_fences); } static int @@ -2289,21 +2437,17 @@ await_fence_array(struct i915_execbuffer *eb) unsigned int n; int err; - for (n = 0; n < eb->n_fences; n++) { + for (n = 0; n < eb->num_fences; n++) { struct drm_syncobj *syncobj; - struct dma_fence *fence; unsigned int flags; syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); - if (!(flags & I915_EXEC_FENCE_WAIT)) - continue; - fence = drm_syncobj_fence_get(syncobj); - if (!fence) - return -EINVAL; + if (!eb->fences[n].dma_fence) + continue; - err = i915_request_await_dma_fence(eb->request, fence); - dma_fence_put(fence); + err = i915_request_await_dma_fence(eb->request, + eb->fences[n].dma_fence); if (err < 0) return err; } @@ -2311,13 +2455,12 @@ await_fence_array(struct i915_execbuffer *eb) return 0; } -static void -signal_fence_array(struct i915_execbuffer *eb) +static void signal_fence_array(const struct i915_execbuffer *eb) { struct dma_fence * const fence = &eb->request->fence; unsigned int n; - for (n = 0; n < eb->n_fences; n++) { + for (n = 0; n < eb->num_fences; n++) { struct drm_syncobj *syncobj; unsigned int flags; @@ -2325,10 +2468,34 @@ signal_fence_array(struct i915_execbuffer *eb) if (!(flags & I915_EXEC_FENCE_SIGNAL)) continue; - drm_syncobj_replace_fence(syncobj, fence); + if (eb->fences[n].chain_fence) { + drm_syncobj_add_point(syncobj, + eb->fences[n].chain_fence, + fence, + eb->fences[n].value); + /* + * The chain's ownership is transferred to the + * timeline. + */ + eb->fences[n].chain_fence = NULL; + } else { + drm_syncobj_replace_fence(syncobj, fence); + } } } +static int +parse_timeline_fences(struct i915_user_extension __user *ext, void *data) +{ + struct i915_execbuffer *eb = data; + struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences; + + if (copy_from_user(&timeline_fences, ext, sizeof(timeline_fences))) + return -EFAULT; + + return add_timeline_fence_array(eb, &timeline_fences); +} + static void retire_requests(struct intel_timeline *tl, struct i915_request *end) { struct i915_request *rq, *rn; @@ -2371,14 +2538,13 @@ static void eb_request_add(struct i915_execbuffer *eb) } static const i915_user_extension_fn execbuf_extensions[] = { + [DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES] = parse_timeline_fences, }; static int parse_execbuf2_extensions(struct drm_i915_gem_execbuffer2 *args, struct i915_execbuffer *eb) { - eb->extension_flags = 0; - if (!(args->flags & I915_EXEC_USE_EXTENSIONS)) return 0; @@ -2432,7 +2598,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.trampoline = NULL; eb.fences = NULL; - eb.n_fences = 0; + eb.num_fences = 0; eb.batch_flags = 0; if (args->flags & I915_EXEC_SECURE) { @@ -2451,14 +2617,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (args->flags & I915_EXEC_IS_PINNED) eb.batch_flags |= I915_DISPATCH_PINNED; + err = parse_execbuf2_extensions(args, &eb); + if (err) + goto err_ext; + + err = add_fence_array(&eb); + if (err) + goto err_ext; + #define IN_FENCES (I915_EXEC_FENCE_IN | I915_EXEC_FENCE_SUBMIT) if (args->flags & IN_FENCES) { if ((args->flags & IN_FENCES) == IN_FENCES) return -EINVAL; in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2)); - if (!in_fence) - return -EINVAL; + if (!in_fence) { + err = -EINVAL; + goto err_ext; + } } #undef IN_FENCES @@ -2470,17 +2646,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, } } - err = parse_execbuf2_extensions(args, &eb); - if (err) - goto err_out_fence; - - err = get_fence_array(args, &eb); - if (err) - goto err_arr_fence; - err = eb_create(&eb); if (err) - goto err_arr_fence; + goto err_out_fence; GEM_BUG_ON(!eb.lut_size); @@ -2576,7 +2744,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_request; } - if (eb.n_fences) { + if (eb.fences) { err = await_fence_array(&eb); if (err) goto err_request; @@ -2608,7 +2776,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, i915_request_get(eb.request); eb_request_add(&eb); - if (eb.n_fences) + if (eb.fences) signal_fence_array(&eb); if (out_fence) { @@ -2637,13 +2805,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, i915_gem_context_put(eb.gem_context); err_destroy: eb_destroy(&eb); -err_arr_fence: - __free_fence_array(eb.fences, eb.n_fences); err_out_fence: if (out_fence_fd != -1) put_unused_fd(out_fence_fd); err_in_fence: dma_fence_put(in_fence); +err_ext: + put_fence_array(eb.fences, eb.num_fences); return err; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5fd5af4bc8551..2d10f6a2c0422 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1846,7 +1846,8 @@ static struct drm_driver driver = { */ .driver_features = DRIVER_GEM | - DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ, + DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ | + DRIVER_SYNCOBJ_TIMELINE, .release = i915_driver_release, .open = i915_driver_open, .lastclose = i915_driver_lastclose, diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index 421613219ae9c..f96032c60a12d 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -132,6 +132,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_BATCH_FIRST: case I915_PARAM_HAS_EXEC_FENCE_ARRAY: case I915_PARAM_HAS_EXEC_SUBMIT_FENCE: + case I915_PARAM_HAS_EXEC_TIMELINE_FENCES: /* For the time being all of these are always true; * if some supported hardware does not have one of these * features this value needs to be provided from diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index dcada8c3a6933..fa1f3d62f9a6c 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -619,6 +619,12 @@ typedef struct drm_i915_irq_wait { */ #define I915_PARAM_PERF_REVISION 54 +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * timeline syncobj through drm_i915_gem_execbuffer_ext_timeline_fences. See + * I915_EXEC_USE_EXTENSIONS. + */ +#define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55 + /* Must be kept compact -- no holes and well documented */ typedef struct drm_i915_getparam { @@ -1046,8 +1052,36 @@ struct drm_i915_gem_exec_fence { __u32 flags; }; -enum drm_i915_gem_execbuffer_ext { - DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */ +/** + * See drm_i915_gem_execbuffer_ext_timeline_fences. + */ +#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0 + +/** + * This structure describes an array of drm_syncobj and associated points for + * timeline variants of drm_syncobj. It is invalid to append this structure to + * the execbuf if I915_EXEC_FENCE_ARRAY is set. + */ +struct drm_i915_gem_execbuffer_ext_timeline_fences { + struct i915_user_extension base; + + /** + * Number of element in the handles_ptr & value_ptr arrays. + */ + __u64 fence_count; + + /** + * Pointer to an array of struct drm_i915_gem_exec_fence of length + * fence_count. + */ + __u64 handles_ptr; + + /** + * Pointer to an array of u64 values of length fence_count. Values + * must be 0 for a binary drm_syncobj. A Value of 0 for a timeline + * drm_syncobj is invalid as it turns a drm_syncobj into a binary one. + */ + __u64 values_ptr; }; struct drm_i915_gem_execbuffer2 { -- GitLab From 21118e8e56479ef33460fbd63a5ad0535843b666 Mon Sep 17 00:00:00 2001 From: George Spelvin <lkml@SDF.ORG> Date: Wed, 25 Mar 2020 19:24:29 +0000 Subject: [PATCH 0513/1494] drm/i915/selftests: Avoid passing a random 0 into ilog2 igt_mm_config() calls ilog2() on the (pseudo)random 21-bit number s>>12. Once in 2 million seeds, this is zero and ilog2 summons the nasal demons. There was an attempt to handle this case with a max(), but that's too late; ms could already be something bizarre. Given that the low 12 bits of s and ms are always zero, it's a lot simpler just to divide them by 4096, then everything fits into 32 bits, and we can easily generate a random number 1 <= s <= 0x1fffff. Fixes: 14d1b9a6247c ("drm/i915: buddy allocator") Signed-off-by: George Spelvin <lkml@sdf.org> Cc: Matthew Auld <matthew.auld@intel.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Matthew Auld <matthew.auld@intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200325192429.GA8865@SDF.ORG Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/selftests/i915_buddy.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c b/drivers/gpu/drm/i915/selftests/i915_buddy.c index 939a6caebb034..632b912b0bc9b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_buddy.c +++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c @@ -8,8 +8,6 @@ #include "../i915_selftest.h" #include "i915_random.h" -#define SZ_8G (1ULL << 33) - static void __igt_dump_block(struct i915_buddy_mm *mm, struct i915_buddy_block *block, bool buddy) @@ -281,18 +279,22 @@ static int igt_check_mm(struct i915_buddy_mm *mm) static void igt_mm_config(u64 *size, u64 *chunk_size) { I915_RND_STATE(prng); - u64 s, ms; + u32 s, ms; /* Nothing fancy, just try to get an interesting bit pattern */ prandom_seed_state(&prng, i915_selftest.random_seed); - s = i915_prandom_u64_state(&prng) & (SZ_8G - 1); - ms = BIT_ULL(12 + (prandom_u32_state(&prng) % ilog2(s >> 12))); - s = max(s & -ms, ms); + /* Let size be a random number of pages up to 8 GB (2M pages) */ + s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); + /* Let the chunk size be a random power of 2 less than size */ + ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng)); + /* Round size down to the chunk size */ + s &= -ms; - *chunk_size = ms; - *size = s; + /* Convert from pages to bytes */ + *chunk_size = (u64)ms << 12; + *size = (u64)s << 12; } static int igt_buddy_alloc_smoke(void *arg) -- GitLab From b302a2e68807604af2a5015816c1d117747989b6 Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Tue, 21 Jul 2020 02:29:52 +0300 Subject: [PATCH 0514/1494] drm/i915/tgl: Make sure TC-cold is blocked before enabling TC AUX power wells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dependency between power wells is determined by the ordering of the power well list: when enabling the power wells for a domain, this happens walking the power well list forward, while disabling them happens in the reverse direction. Accordingly a power well on the list must follow any other power well it depends on. Since the TC AUX power wells depend on TC-cold being blocked, move the TC-cold off power well before all AUX power wells. Fixes: 3c02934b24e3 ("drm/i915/tc/tgl: Implement TC cold sequences") Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200720232952.16228-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display_power.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9f0241a53a452..3c800aa9cf3f1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4146,6 +4146,12 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6, }, }, + { + .name = "TC cold off", + .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, + .ops = &tgl_tc_cold_off_ops, + .id = DISP_PW_ID_NONE, + }, { .name = "AUX A", .domains = TGL_AUX_A_IO_POWER_DOMAINS, @@ -4332,12 +4338,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.irq_pipe_mask = BIT(PIPE_D), }, }, - { - .name = "TC cold off", - .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, - .ops = &tgl_tc_cold_off_ops, - .id = DISP_PW_ID_NONE, - }, }; static const struct i915_power_well_desc rkl_power_wells[] = { -- GitLab From 05e31dd78e26d8c4d9d0dd68addead8d19c367c2 Mon Sep 17 00:00:00 2001 From: Imre Deak <imre.deak@intel.com> Date: Wed, 5 Aug 2020 18:00:56 +0300 Subject: [PATCH 0515/1494] drm/i915/tgl: Fix TC-cold block/unblock sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The command register is the PCODE MBOX low register not the high one as described by the spec. This left the system with the TC-cold power state being blocked all the time. Fix things by using the correct register. Also to make sure we retry a request for at least 600usec, when the PCODE MBOX command itself succeeded, but the TC-cold block command failed, sleep for 1msec unconditionally after any fail. The change was tested with JTAG register read of the HW/FW's actual TC-cold state, which reported the expected states after this change. Tested-by: Nivedita Swaminathan <nivedita.swaminathan@intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805150056.24248-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display_power.c | 10 +++++----- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 3c800aa9cf3f1..7946c6af4b1e7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3927,12 +3927,13 @@ tgl_tc_cold_request(struct drm_i915_private *i915, bool block) int ret; while (1) { - u32 low_val = 0, high_val; + u32 low_val; + u32 high_val = 0; if (block) - high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ; + low_val = TGL_PCODE_EXIT_TCCOLD_DATA_L_BLOCK_REQ; else - high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ; + low_val = TGL_PCODE_EXIT_TCCOLD_DATA_L_UNBLOCK_REQ; /* * Spec states that we should timeout the request after 200us @@ -3951,8 +3952,7 @@ tgl_tc_cold_request(struct drm_i915_private *i915, bool block) if (++tries == 3) break; - if (ret == -EAGAIN) - msleep(1); + msleep(1); } if (ret) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2b403df03404f..e85c6fc1f3cb5 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9226,8 +9226,8 @@ enum { #define DISPLAY_IPS_CONTROL 0x19 #define TGL_PCODE_TCCOLD 0x26 #define TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED REG_BIT(0) -#define TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ 0 -#define TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ REG_BIT(0) +#define TGL_PCODE_EXIT_TCCOLD_DATA_L_BLOCK_REQ 0 +#define TGL_PCODE_EXIT_TCCOLD_DATA_L_UNBLOCK_REQ REG_BIT(0) /* See also IPS_CTL */ #define IPS_PCODE_CONTROL (1 << 30) #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A -- GitLab From 1d3cc7ab2b00f849c94bd7e5fcffc7899dc4039a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Fri, 7 Aug 2020 12:26:28 -0700 Subject: [PATCH 0516/1494] drm/i915/tgl: Set subplatforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no way to differentiate TGL-U from TGL-Y by the PCI ids as some ids are available in both SKUs. So here using the root device id in the PCI bus that iGPU is in to differentiate between U and Y. BSpec: 44455 Reviewed-by: Swathi Dhanavanthri <swathi.dhanavanthri@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200807192629.64134-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_device_info.c | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 56dfc6d98caa3..a59f648219201 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1497,6 +1497,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_ICL_WITH_PORT_F(dev_priv) \ IS_SUBPLATFORM(dev_priv, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF) +#define IS_TGL_U(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_ULT) + +#define IS_TGL_Y(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_ULX) + #define SKL_REVID_A0 0x0 #define SKL_REVID_B0 0x1 #define SKL_REVID_C0 0x2 diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e85c6fc1f3cb5..14d8c3fbcc0de 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -12353,4 +12353,10 @@ enum skl_power_gate { #define DSB_ENABLE (1 << 31) #define DSB_STATUS (1 << 0) +#define TGL_ROOT_DEVICE_ID 0x9A00 +#define TGL_ROOT_DEVICE_MASK 0xFF00 +#define TGL_ROOT_DEVICE_SKU_MASK 0xF +#define TGL_ROOT_DEVICE_SKU_ULX 0x2 +#define TGL_ROOT_DEVICE_SKU_ULT 0x4 + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 40c590db3c761..e2aa5bc3a6e01 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -346,6 +346,25 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915) mask = BIT(INTEL_SUBPLATFORM_PORTF); } + if (IS_TIGERLAKE(i915)) { + struct pci_dev *root, *pdev = i915->drm.pdev; + + root = list_first_entry(&pdev->bus->devices, typeof(*root), bus_list); + + drm_WARN_ON(&i915->drm, mask); + drm_WARN_ON(&i915->drm, (root->device & TGL_ROOT_DEVICE_MASK) != + TGL_ROOT_DEVICE_ID); + + switch (root->device & TGL_ROOT_DEVICE_SKU_MASK) { + case TGL_ROOT_DEVICE_SKU_ULX: + mask = BIT(INTEL_SUBPLATFORM_ULX); + break; + case TGL_ROOT_DEVICE_SKU_ULT: + mask = BIT(INTEL_SUBPLATFORM_ULT); + break; + } + } + GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_BITS); RUNTIME_INFO(i915)->platform_mask[pi] |= mask; -- GitLab From 04dfb1acbae6a70703183fc6c1366bb7d997d015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Fri, 7 Aug 2020 12:26:29 -0700 Subject: [PATCH 0517/1494] drm/i915/tgl: Add new voltage swing table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new HBR2 table for TGL-U and TGL-Y is required to pass DisplayPort compliance. BSpec: 49291 Cc: Khaled Almahallawy <khaled.almahallawy@intel.com> Reviewed-by: Khaled Almahallawy<khaled.almahallawy@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200807192629.64134-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 714b2bc96f23c..de5b216561d8f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -706,6 +706,20 @@ static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; +static const struct cnl_ddi_buf_trans tgl_uy_combo_phy_ddi_translations_dp_hbr2[] = { + /* NT mV Trans mV db */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ + { 0xA, 0x4F, 0x36, 0x00, 0x09 }, /* 350 500 3.1 */ + { 0xC, 0x60, 0x32, 0x00, 0x0D }, /* 350 700 6.0 */ + { 0xC, 0x7F, 0x2D, 0x00, 0x12 }, /* 350 900 8.2 */ + { 0xC, 0x47, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */ + { 0xC, 0x6F, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */ + { 0x6, 0x7D, 0x32, 0x00, 0x0D }, /* 500 900 5.1 */ + { 0x6, 0x60, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */ + { 0x6, 0x7F, 0x34, 0x00, 0x0B }, /* 600 900 3.5 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ +}; + /* * Cloned the HOBL entry to comply with the voltage and pre-emphasis entries * that DisplayPort specification requires @@ -1087,6 +1101,11 @@ tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } else if (rate > 270000) { + if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) { + *n_entries = ARRAY_SIZE(tgl_uy_combo_phy_ddi_translations_dp_hbr2); + return tgl_uy_combo_phy_ddi_translations_dp_hbr2; + } + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2); return tgl_combo_phy_ddi_translations_dp_hbr2; } -- GitLab From 96c5a15f9f3973aca11137671afa9d433639f8ce Mon Sep 17 00:00:00 2001 From: Matt Roper <matthew.d.roper@intel.com> Date: Mon, 10 Aug 2020 20:21:05 -0700 Subject: [PATCH 0518/1494] drm/i915/kbl: Fix revision ID checks We usually assume that increasing PCI device revision ID's translates to newer steppings; macros like IS_KBL_REVID() that we use rely on this behavior. Unfortunately this turns out to not be true on KBL; the newer device 2 revision ID's sometimes go backward to older steppings. The situation is further complicated by different GT and display steppings associated with each revision ID. Let's work around this by providing a table to map the revision ID to specific GT and display steppings, and then perform our comparisons on the mapped values. v2: - Move the kbl_revids[] array to intel_workarounds.c to avoid compiler warnings about an unused variable in files that don't call the macros (kernel test robot). Bspec: 18329 Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200811032105.2819370-1-matthew.d.roper@intel.com Reviewed-by: Swathi Dhanavanthri <swathi.dhanavanthri@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 24 ++++++++++++-- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 36 ++++++++++++++++----- drivers/gpu/drm/i915/intel_pm.c | 4 +-- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e0280a672f1d7..94d8c9d76a260 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4555,7 +4555,7 @@ static int gen8_emit_flush_render(struct i915_request *request, vf_flush_wa = true; /* WaForGAMHang:kbl */ - if (IS_KBL_REVID(request->engine->i915, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(request->engine->i915, 0, KBL_REVID_B0)) dc_flush_wa = true; } diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index cef1c122696fb..be5a4685c9915 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -52,6 +52,24 @@ * - Public functions to init or apply the given workaround type. */ +/* + * KBL revision ID ordering is bizarre; higher revision ID's map to lower + * steppings in some cases. So rather than test against the revision ID + * directly, let's map that into our own range of increasing ID's that we + * can test against in a regular manner. + */ + +const struct i915_rev_steppings kbl_revids[] = { + [0] = { .gt_stepping = KBL_REVID_A0, .disp_stepping = KBL_REVID_A0 }, + [1] = { .gt_stepping = KBL_REVID_B0, .disp_stepping = KBL_REVID_B0 }, + [2] = { .gt_stepping = KBL_REVID_C0, .disp_stepping = KBL_REVID_B0 }, + [3] = { .gt_stepping = KBL_REVID_D0, .disp_stepping = KBL_REVID_B0 }, + [4] = { .gt_stepping = KBL_REVID_F0, .disp_stepping = KBL_REVID_C0 }, + [5] = { .gt_stepping = KBL_REVID_C0, .disp_stepping = KBL_REVID_B1 }, + [6] = { .gt_stepping = KBL_REVID_D1, .disp_stepping = KBL_REVID_B1 }, + [7] = { .gt_stepping = KBL_REVID_G0, .disp_stepping = KBL_REVID_C0 }, +}; + static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name) { wal->name = name; @@ -470,7 +488,7 @@ static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine, gen9_ctx_workarounds_init(engine, wal); /* WaToEnableHwFixForPushConstHWBug:kbl */ - if (IS_KBL_REVID(i915, KBL_REVID_C0, REVID_FOREVER)) + if (IS_KBL_GT_REVID(i915, KBL_REVID_C0, REVID_FOREVER)) WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); @@ -1008,7 +1026,7 @@ kbl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) gen9_gt_workarounds_init(i915, wal); /* WaDisableDynamicCreditSharing:kbl */ - if (IS_KBL_REVID(i915, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(i915, 0, KBL_REVID_B0)) wa_write_or(wal, GAMT_CHKN_BIT_REG, GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); @@ -1923,7 +1941,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) struct drm_i915_private *i915 = engine->i915; /* WaKBLVECSSemaphoreWaitPoll:kbl */ - if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) { + if (IS_KBL_GT_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) { wa_write(wal, RING_SEMA_WAIT_POLL(engine->mmio_base), 1); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2d10f6a2c0422..e6918c7c07098 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -392,7 +392,7 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) pre |= IS_HSW_EARLY_SDV(dev_priv); pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0); pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST); - pre |= IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0); + pre |= IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_A0); pre |= IS_GLK_REVID(dev_priv, 0, GLK_REVID_A2); if (pre) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a59f648219201..023eb28ea4eca 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1523,14 +1523,34 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_BXT_REVID(dev_priv, since, until) \ (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until)) -#define KBL_REVID_A0 0x0 -#define KBL_REVID_B0 0x1 -#define KBL_REVID_C0 0x2 -#define KBL_REVID_D0 0x3 -#define KBL_REVID_E0 0x4 - -#define IS_KBL_REVID(dev_priv, since, until) \ - (IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until)) +enum { + KBL_REVID_A0, + KBL_REVID_B0, + KBL_REVID_B1, + KBL_REVID_C0, + KBL_REVID_D0, + KBL_REVID_D1, + KBL_REVID_E0, + KBL_REVID_F0, + KBL_REVID_G0, +}; + +struct i915_rev_steppings { + u8 gt_stepping; + u8 disp_stepping; +}; + +/* Defined in intel_workarounds.c */ +extern const struct i915_rev_steppings kbl_revids[]; + +#define IS_KBL_GT_REVID(dev_priv, since, until) \ + (IS_KABYLAKE(dev_priv) && \ + kbl_revids[INTEL_REVID(dev_priv)].gt_stepping >= since && \ + kbl_revids[INTEL_REVID(dev_priv)].gt_stepping <= until) +#define IS_KBL_DISP_REVID(dev_priv, since, until) \ + (IS_KABYLAKE(dev_priv) && \ + kbl_revids[INTEL_REVID(dev_priv)].disp_stepping >= since && \ + kbl_revids[INTEL_REVID(dev_priv)].disp_stepping <= until) #define GLK_REVID_A0 0x0 #define GLK_REVID_A1 0x1 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a1a95060f38b..b4bd19266b8c5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7217,12 +7217,12 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) gen9_init_clock_gating(dev_priv); /* WaDisableSDEUnitClockGating:kbl */ - if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0)) I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_SDEUNIT_CLOCK_GATE_DISABLE); /* WaDisableGamClockGating:kbl */ - if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0)) I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) | GEN6_GAMUNIT_CLOCK_GATE_DISABLE); -- GitLab From 6e43e276b8c94ecfeebfcc32eabad2ba27e90299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Mon, 10 Aug 2020 10:41:43 -0700 Subject: [PATCH 0519/1494] drm/i915: Initial implementation of PSR2 selective fetch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All GEN12 platforms supports PSR2 selective fetch but not all GEN12 platforms supports PSR2 hardware tracking(aka RKL). This feature consists in software programming registers with the damaged area of each plane this way hardware will only fetch from memory those areas and sent the PSR2 selective update blocks to panel, saving even more power. But as initial step it is only enabling the full frame fetch at every flip, the actual selective fetch part will come in a future patch. Also this is only handling the page flip side, it is still completely missing frontbuffer modifications, that is why the enable_psr2_sel_fetch parameter was added. v3: - calling intel_psr2_sel_fetch_update() during the atomic check phase (Ville) BSpec: 55229 Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200810174144.76761-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 5 + .../drm/i915/display/intel_display_debugfs.c | 3 + .../drm/i915/display/intel_display_types.h | 3 + drivers/gpu/drm/i915/display/intel_psr.c | 95 ++++++++++++++++--- drivers/gpu/drm/i915/display/intel_psr.h | 5 + drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_params.c | 5 + drivers/gpu/drm/i915/i915_params.h | 1 + 8 files changed, 105 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 522c772a21117..2ddabf92adde1 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12770,6 +12770,9 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, } + if (!mode_changed) + intel_psr2_sel_fetch_update(state, crtc); + return 0; } @@ -15146,6 +15149,8 @@ static void commit_pipe_config(struct intel_atomic_state *state, if (new_crtc_state->update_pipe) intel_pipe_fastset(old_crtc_state, new_crtc_state); + + intel_psr2_program_trans_man_trk_ctl(new_crtc_state); } if (dev_priv->display.atomic_update_watermarks) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 5a5cfe25085b4..f549381048b3c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -417,6 +417,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); seq_printf(m, "%d\t%d\n", frame, su_blocks); } + + seq_printf(m, "PSR2 selective fetch: %s\n", + enableddisabled(psr->psr2_sel_fetch_enabled)); } unlock: diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f581260e8dbfd..9349b15afff67 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -931,6 +931,7 @@ struct intel_crtc_state { bool has_psr; bool has_psr2; + bool enable_psr2_sel_fetch; u32 dc3co_exitline; /* @@ -1073,6 +1074,8 @@ struct intel_crtc_state { /* For DSB related info */ struct intel_dsb *dsb; + + u32 psr2_man_track_ctl; }; enum intel_pipe_crc_source { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index bf9e320c547da..d30a3560b7942 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -553,6 +553,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FAST_WAKE(7); } + if (dev_priv->psr.psr2_sel_fetch_enabled) + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), + PSR2_MAN_TRK_CTL_ENABLE); + else if (HAS_PSR2_SEL_FETCH(dev_priv)) + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0); + /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is * recommending keep this bit unset while PSR2 is enabled. @@ -663,6 +671,38 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp, crtc_state->dc3co_exitline = crtc_vdisplay - exit_scanlines; } +static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_plane_state *plane_state; + struct intel_plane *plane; + int i; + + if (!dev_priv->params.enable_psr2_sel_fetch) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, disabled by parameter\n"); + return false; + } + + if (crtc_state->uapi.async_flip) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, async flip enabled\n"); + return false; + } + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane_state->uapi.rotation != DRM_MODE_ROTATE_0) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, plane rotated\n"); + return false; + } + } + + return crtc_state->enable_psr2_sel_fetch = true; +} + static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -732,22 +772,17 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - /* - * Some platforms lack PSR2 HW tracking and instead require manual - * tracking by software. In this case, the driver is required to track - * the areas that need updates and program hardware to send selective - * updates. - * - * So until the software tracking is implemented, PSR2 needs to be - * disabled for platforms without PSR2 HW tracking. - */ - if (!HAS_PSR_HW_TRACKING(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "No PSR2 HW tracking in the platform\n"); - return false; + if (HAS_PSR2_SEL_FETCH(dev_priv)) { + if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && + !HAS_PSR_HW_TRACKING(dev_priv)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, selective fetch not valid and no HW tracking available\n"); + return false; + } } - if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) { + if (!crtc_state->enable_psr2_sel_fetch && + (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", crtc_hdisplay, crtc_vdisplay, @@ -898,6 +933,11 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, val |= EXITLINE_ENABLE; intel_de_write(dev_priv, EXITLINE(cpu_transcoder), val); } + + if (HAS_PSR_HW_TRACKING(dev_priv)) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING, + dev_priv->psr.psr2_sel_fetch_enabled ? + IGNORE_PSR2_HW_TRACKING : 0); } static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, @@ -919,6 +959,7 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, /* DC5/DC6 requires at least 6 idle frames */ val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6); dev_priv->psr.dc3co_exit_delay = val; + dev_priv->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch; /* * If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR @@ -1115,6 +1156,32 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv) intel_psr_exit(dev_priv); } +void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct i915_psr *psr = &dev_priv->psr; + + if (!HAS_PSR2_SEL_FETCH(dev_priv) || + !crtc_state->enable_psr2_sel_fetch) + return; + + intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(psr->transcoder), + crtc_state->psr2_man_track_ctl); +} + +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + + if (!crtc_state->enable_psr2_sel_fetch) + return; + + crtc_state->psr2_man_track_ctl = PSR2_MAN_TRK_CTL_ENABLE | + PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME; +} + /** * intel_psr_update - Update PSR state * @intel_dp: Intel DP diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index b4515186d5f46..6a83c8e682e6d 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -13,6 +13,8 @@ struct drm_connector_state; struct drm_i915_private; struct intel_crtc_state; struct intel_dp; +struct intel_crtc; +struct intel_atomic_state; #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) void intel_psr_init_dpcd(struct intel_dp *intel_dp); @@ -43,5 +45,8 @@ void intel_psr_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp); +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_PSR_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 023eb28ea4eca..4b5c25a018b7f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -506,6 +506,7 @@ struct i915_psr { bool link_standby; bool colorimetry_support; bool psr2_enabled; + bool psr2_sel_fetch_enabled; u8 sink_sync_latency; ktime_t last_entry_attempt; ktime_t last_exit; @@ -1699,6 +1700,7 @@ extern const struct i915_rev_steppings kbl_revids[]; #define HAS_PSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_psr) #define HAS_PSR_HW_TRACKING(dev_priv) \ (INTEL_INFO(dev_priv)->display.has_psr_hw_tracking) +#define HAS_PSR2_SEL_FETCH(dev_priv) (INTEL_GEN(dev_priv) >= 12) #define HAS_TRANSCODER(dev_priv, trans) ((INTEL_INFO(dev_priv)->cpu_transcoder_mask & BIT(trans)) != 0) #define HAS_RC6(dev_priv) (INTEL_INFO(dev_priv)->has_rc6) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 8d8db9ff0a484..7f139ea4a90b2 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -102,6 +102,11 @@ i915_param_named(psr_safest_params, bool, 0400, "is helpful to detect if PSR issues are related to bad values set in " " VBT. (0=use VBT parameters, 1=use safest parameters)"); +i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, + "Enable PSR2 selective fetch " + "(0=disabled, 1=enabled) " + "Default: 0"); + i915_param_named_unsafe(force_probe, charp, 0400, "Force probe the driver for specified devices. " "See CONFIG_DRM_I915_FORCE_PROBE for details."); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 53fb5ba8fbed6..330c03e2b4f70 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -54,6 +54,7 @@ struct drm_printer; param(int, enable_fbc, -1, 0600) \ param(int, enable_psr, -1, 0600) \ param(bool, psr_safest_params, false, 0600) \ + param(bool, enable_psr2_sel_fetch, false, 0600) \ param(int, disable_power_well, -1, 0400) \ param(int, enable_ips, 1, 0600) \ param(int, invert_brightness, 0, 0600) \ -- GitLab From a170f4f1b128128d35b732cdc799dc5824f8e2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Mon, 10 Aug 2020 10:41:44 -0700 Subject: [PATCH 0520/1494] drm/i915/display: Implement WA 1408330847 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the 3 WAs for PSR2 man track/selective fetch this is only one needed when doing single full frames at every flip. Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200810174144.76761-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_psr.c | 19 +++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d30a3560b7942..2b004ee9619cd 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -553,13 +553,21 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FAST_WAKE(7); } - if (dev_priv->psr.psr2_sel_fetch_enabled) + if (dev_priv->psr.psr2_sel_fetch_enabled) { + /* WA 1408330847 */ + if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, + DIS_RAM_BYPASS_PSR2_MAN_TRACK, + DIS_RAM_BYPASS_PSR2_MAN_TRACK); + intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), PSR2_MAN_TRK_CTL_ENABLE); - else if (HAS_PSR2_SEL_FETCH(dev_priv)) + } else if (HAS_PSR2_SEL_FETCH(dev_priv)) { intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0); + } /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is @@ -1099,6 +1107,13 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) psr_status_mask, 2000)) drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n"); + /* WA 1408330847 */ + if (dev_priv->psr.psr2_sel_fetch_enabled && + (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, + DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); + /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 14d8c3fbcc0de..ac691927e29d8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7878,6 +7878,7 @@ enum { # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 _MMIO(0x42080) +#define DIS_RAM_BYPASS_PSR2_MAN_TRACK (1 << 16) #define SKL_DE_COMPRESSED_HASH_MODE (1 << 15) #define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) -- GitLab From 5bf7919d530a2e1456ae602fccf365c213a4db4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Thu, 13 Aug 2020 13:00:28 -0700 Subject: [PATCH 0521/1494] drm/i915: Update TGL and RKL DMC firmware versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes around DC5, DC6 and DC3CO in those new firmwares. Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200813200029.25307-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_csr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_csr.c b/drivers/gpu/drm/i915/display/intel_csr.c index f22a7645c249d..d5db16764619c 100644 --- a/drivers/gpu/drm/i915/display/intel_csr.c +++ b/drivers/gpu/drm/i915/display/intel_csr.c @@ -40,12 +40,12 @@ #define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE -#define RKL_CSR_PATH "i915/rkl_dmc_ver2_01.bin" -#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 1) +#define RKL_CSR_PATH "i915/rkl_dmc_ver2_02.bin" +#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 2) MODULE_FIRMWARE(RKL_CSR_PATH); -#define TGL_CSR_PATH "i915/tgl_dmc_ver2_06.bin" -#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 6) +#define TGL_CSR_PATH "i915/tgl_dmc_ver2_08.bin" +#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 8) #define TGL_CSR_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(TGL_CSR_PATH); -- GitLab From 25a322fde74f8ca3368f4ff28b452af7cb5fa0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Thu, 13 Aug 2020 13:00:29 -0700 Subject: [PATCH 0522/1494] drm/i915: Update TGL and RKL HuC firmware versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major upgrade of HuC firmware with fixes and new features. Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200813200029.25307-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 59b27aba15c6f..80e8b6c3bc8c5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -51,8 +51,8 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * Note that RKL uses the same firmware as TGL. */ #define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \ - fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 0, 12)) \ - fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 0, 12)) \ + fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ + fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ fw_def(ELKHARTLAKE, 0, guc_def(ehl, 33, 0, 4), huc_def(ehl, 9, 0, 0)) \ fw_def(ICELAKE, 0, guc_def(icl, 33, 0, 0), huc_def(icl, 9, 0, 0)) \ fw_def(COMETLAKE, 5, guc_def(cml, 33, 0, 0), huc_def(cml, 4, 0, 0)) \ -- GitLab From a0308938ec81cd0dca9d75833ec0dd1b8708917e Mon Sep 17 00:00:00 2001 From: David Stevens <stevensd@chromium.org> Date: Tue, 18 Aug 2020 16:13:41 +0900 Subject: [PATCH 0523/1494] virtio: add dma-buf support for exported objects This change adds a new flavor of dma-bufs that can be used by virtio drivers to share exported objects. A virtio dma-buf can be queried by virtio drivers to obtain the UUID which identifies the underlying exported object. Signed-off-by: David Stevens <stevensd@chromium.org> Acked-by: Michael S. Tsirkin <mst@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200818071343.3461203-2-stevensd@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/virtio/Makefile | 2 +- drivers/virtio/virtio.c | 6 +++ drivers/virtio/virtio_dma_buf.c | 85 +++++++++++++++++++++++++++++++++ include/linux/virtio.h | 1 + include/linux/virtio_dma_buf.h | 37 ++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 drivers/virtio/virtio_dma_buf.c create mode 100644 include/linux/virtio_dma_buf.h diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index 4d993791f2d72..49da768ee7fde 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o +obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o virtio_dma_buf.o obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index a977e32a88f2f..5d46f0ded92d4 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -357,6 +357,12 @@ int register_virtio_device(struct virtio_device *dev) } EXPORT_SYMBOL_GPL(register_virtio_device); +bool is_virtio_device(struct device *dev) +{ + return dev->bus == &virtio_bus; +} +EXPORT_SYMBOL_GPL(is_virtio_device); + void unregister_virtio_device(struct virtio_device *dev) { int index = dev->index; /* save for after device release */ diff --git a/drivers/virtio/virtio_dma_buf.c b/drivers/virtio/virtio_dma_buf.c new file mode 100644 index 0000000000000..45d6e8647dcf1 --- /dev/null +++ b/drivers/virtio/virtio_dma_buf.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * dma-bufs for virtio exported objects + * + * Copyright (C) 2020 Google, Inc. + */ + +#include <linux/virtio_dma_buf.h> + +/** + * virtio_dma_buf_export - Creates a new dma-buf for a virtio exported object + * @exp_info: [in] see dma_buf_export(). ops MUST refer to a dma_buf_ops + * struct embedded in a virtio_dma_buf_ops. + * + * This wraps dma_buf_export() to allow virtio drivers to create a dma-buf + * for an virtio exported object that can be queried by other virtio drivers + * for the object's UUID. + */ +struct dma_buf *virtio_dma_buf_export + (const struct dma_buf_export_info *exp_info) +{ + const struct virtio_dma_buf_ops *virtio_ops = + container_of(exp_info->ops, + const struct virtio_dma_buf_ops, ops); + + if (!exp_info->ops || + exp_info->ops->attach != &virtio_dma_buf_attach || + !virtio_ops->get_uuid) { + return ERR_PTR(-EINVAL); + } + + return dma_buf_export(exp_info); +} +EXPORT_SYMBOL(virtio_dma_buf_export); + +/** + * virtio_dma_buf_attach - mandatory attach callback for virtio dma-bufs + */ +int virtio_dma_buf_attach(struct dma_buf *dma_buf, + struct dma_buf_attachment *attach) +{ + int ret; + const struct virtio_dma_buf_ops *ops = + container_of(dma_buf->ops, + const struct virtio_dma_buf_ops, ops); + + if (ops->device_attach) { + ret = ops->device_attach(dma_buf, attach); + if (ret) + return ret; + } + return 0; +} +EXPORT_SYMBOL(virtio_dma_buf_attach); + +/** + * is_virtio_dma_buf - returns true if the given dma-buf is a virtio dma-buf + * @dma_buf: buffer to query + */ +bool is_virtio_dma_buf(struct dma_buf *dma_buf) +{ + return dma_buf->ops->attach == &virtio_dma_buf_attach; +} +EXPORT_SYMBOL(is_virtio_dma_buf); + +/** + * virtio_dma_buf_get_uuid - gets a virtio dma-buf's exported object's uuid + * @dma_buf: [in] buffer to query + * @uuid: [out] the uuid + * + * Returns: 0 on success, negative on failure. + */ +int virtio_dma_buf_get_uuid(struct dma_buf *dma_buf, + uuid_t *uuid) +{ + const struct virtio_dma_buf_ops *ops = + container_of(dma_buf->ops, + const struct virtio_dma_buf_ops, ops); + + if (!is_virtio_dma_buf(dma_buf)) + return -EINVAL; + + return ops->get_uuid(dma_buf, uuid); +} +EXPORT_SYMBOL(virtio_dma_buf_get_uuid); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index a493eac083933..55ea329fe72a4 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -127,6 +127,7 @@ static inline struct virtio_device *dev_to_virtio(struct device *_dev) void virtio_add_status(struct virtio_device *dev, unsigned int status); int register_virtio_device(struct virtio_device *dev); void unregister_virtio_device(struct virtio_device *dev); +bool is_virtio_device(struct device *dev); void virtio_break_device(struct virtio_device *dev); diff --git a/include/linux/virtio_dma_buf.h b/include/linux/virtio_dma_buf.h new file mode 100644 index 0000000000000..a2fdf217ac622 --- /dev/null +++ b/include/linux/virtio_dma_buf.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * dma-bufs for virtio exported objects + * + * Copyright (C) 2020 Google, Inc. + */ + +#ifndef _LINUX_VIRTIO_DMA_BUF_H +#define _LINUX_VIRTIO_DMA_BUF_H + +#include <linux/dma-buf.h> +#include <linux/uuid.h> +#include <linux/virtio.h> + +/** + * struct virtio_dma_buf_ops - operations possible on exported object dma-buf + * @ops: the base dma_buf_ops. ops.attach MUST be virtio_dma_buf_attach. + * @device_attach: [optional] callback invoked by virtio_dma_buf_attach during + * all attach operations. + * @get_uid: [required] callback to get the uuid of the exported object. + */ +struct virtio_dma_buf_ops { + struct dma_buf_ops ops; + int (*device_attach)(struct dma_buf *dma_buf, + struct dma_buf_attachment *attach); + int (*get_uuid)(struct dma_buf *dma_buf, uuid_t *uuid); +}; + +int virtio_dma_buf_attach(struct dma_buf *dma_buf, + struct dma_buf_attachment *attach); + +struct dma_buf *virtio_dma_buf_export + (const struct dma_buf_export_info *exp_info); +bool is_virtio_dma_buf(struct dma_buf *dma_buf); +int virtio_dma_buf_get_uuid(struct dma_buf *dma_buf, uuid_t *uuid); + +#endif /* _LINUX_VIRTIO_DMA_BUF_H */ -- GitLab From 592d9fba33c275b72cb4dae99c187444daafcd33 Mon Sep 17 00:00:00 2001 From: David Stevens <stevensd@chromium.org> Date: Tue, 18 Aug 2020 16:13:42 +0900 Subject: [PATCH 0524/1494] virtio-gpu: add VIRTIO_GPU_F_RESOURCE_UUID feature This feature allows the guest to request a UUID from the host for a particular virtio_gpu resource. The UUID can then be shared with other virtio devices, to allow the other host devices to access the virtio_gpu's corresponding host resource. Signed-off-by: David Stevens <stevensd@chromium.org> Acked-by: Michael S. Tsirkin <mst@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200818071343.3461203-3-stevensd@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- include/uapi/linux/virtio_gpu.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h index 0c85914d93692..9721d58b4d581 100644 --- a/include/uapi/linux/virtio_gpu.h +++ b/include/uapi/linux/virtio_gpu.h @@ -50,6 +50,10 @@ * VIRTIO_GPU_CMD_GET_EDID */ #define VIRTIO_GPU_F_EDID 1 +/* + * VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID + */ +#define VIRTIO_GPU_F_RESOURCE_UUID 2 enum virtio_gpu_ctrl_type { VIRTIO_GPU_UNDEFINED = 0, @@ -66,6 +70,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_CMD_GET_CAPSET_INFO, VIRTIO_GPU_CMD_GET_CAPSET, VIRTIO_GPU_CMD_GET_EDID, + VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID, /* 3d commands */ VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, @@ -87,6 +92,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_RESP_OK_CAPSET_INFO, VIRTIO_GPU_RESP_OK_CAPSET, VIRTIO_GPU_RESP_OK_EDID, + VIRTIO_GPU_RESP_OK_RESOURCE_UUID, /* error responses */ VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, @@ -340,4 +346,17 @@ enum virtio_gpu_formats { VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134, }; +/* VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID */ +struct virtio_gpu_resource_assign_uuid { + struct virtio_gpu_ctrl_hdr hdr; + __le32 resource_id; + __le32 padding; +}; + +/* VIRTIO_GPU_RESP_OK_RESOURCE_UUID */ +struct virtio_gpu_resp_resource_uuid { + struct virtio_gpu_ctrl_hdr hdr; + __u8 uuid[16]; +}; + #endif -- GitLab From c84adb304c100cb9555f64f49c1d84a01fac3616 Mon Sep 17 00:00:00 2001 From: David Stevens <stevensd@chromium.org> Date: Tue, 18 Aug 2020 16:13:43 +0900 Subject: [PATCH 0525/1494] drm/virtio: Support virtgpu exported resources Add support for UUID-based resource sharing mechanism to virtgpu. This implements the new virtgpu commands and hooks them up to dma-buf's get_uuid callback. Signed-off-by: David Stevens <stevensd@chromium.org> Acked-by: Michael S. Tsirkin <mst@redhat.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200818071343.3461203-4-stevensd@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_drv.c | 3 + drivers/gpu/drm/virtio/virtgpu_drv.h | 21 ++++++ drivers/gpu/drm/virtio/virtgpu_kms.c | 4 ++ drivers/gpu/drm/virtio/virtgpu_prime.c | 96 +++++++++++++++++++++++++- drivers/gpu/drm/virtio/virtgpu_vq.c | 55 +++++++++++++++ 5 files changed, 176 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index ab4bed78e656c..b039f493bda99 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -165,6 +165,7 @@ static unsigned int features[] = { VIRTIO_GPU_F_VIRGL, #endif VIRTIO_GPU_F_EDID, + VIRTIO_GPU_F_RESOURCE_UUID, }; static struct virtio_driver virtio_gpu_driver = { .feature_table = features, @@ -202,6 +203,8 @@ static struct drm_driver driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_mmap = drm_gem_prime_mmap, + .gem_prime_export = virtgpu_gem_prime_export, + .gem_prime_import = virtgpu_gem_prime_import, .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table, .gem_create_object = virtio_gpu_create_object, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9ff9f4ac0522a..9a8bfbf85412c 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -49,6 +49,10 @@ #define DRIVER_MINOR 1 #define DRIVER_PATCHLEVEL 0 +#define UUID_INITIALIZING 0 +#define UUID_INITIALIZED 1 +#define UUID_INITIALIZATION_FAILED 2 + struct virtio_gpu_object_params { uint32_t format; uint32_t width; @@ -71,6 +75,9 @@ struct virtio_gpu_object { uint32_t hw_res_handle; bool dumb; bool created; + + int uuid_state; + uuid_t uuid; }; #define gem_to_virtio_gpu_obj(gobj) \ container_of((gobj), struct virtio_gpu_object, base.base) @@ -200,6 +207,7 @@ struct virtio_gpu_device { bool has_virgl_3d; bool has_edid; bool has_indirect; + bool has_resource_assign_uuid; struct work_struct config_changed_work; @@ -210,6 +218,9 @@ struct virtio_gpu_device { struct virtio_gpu_drv_capset *capsets; uint32_t num_capsets; struct list_head cap_cache; + + /* protects resource state when exporting */ + spinlock_t resource_export_lock; }; struct virtio_gpu_fpriv { @@ -336,6 +347,10 @@ void virtio_gpu_dequeue_fence_func(struct work_struct *work); void virtio_gpu_notify(struct virtio_gpu_device *vgdev); +int +virtio_gpu_cmd_resource_assign_uuid(struct virtio_gpu_device *vgdev, + struct virtio_gpu_object_array *objs); + /* virtgpu_display.c */ void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev); @@ -367,6 +382,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, bool virtio_gpu_is_shmem(struct virtio_gpu_object *bo); /* virtgpu_prime.c */ +struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj, + int flags); +struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev, + struct dma_buf *buf); +int virtgpu_gem_prime_get_uuid(struct drm_gem_object *obj, + uuid_t *uuid); struct drm_gem_object *virtgpu_gem_prime_import_sg_table( struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 0a5c8cf409fb8..bf060c69850fd 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -118,6 +118,7 @@ int virtio_gpu_init(struct drm_device *dev) vgdev->dev = dev->dev; spin_lock_init(&vgdev->display_info_lock); + spin_lock_init(&vgdev->resource_export_lock); ida_init(&vgdev->ctx_id_ida); ida_init(&vgdev->resource_ida); init_waitqueue_head(&vgdev->resp_wq); @@ -146,6 +147,9 @@ int virtio_gpu_init(struct drm_device *dev) if (virtio_has_feature(vgdev->vdev, VIRTIO_RING_F_INDIRECT_DESC)) { vgdev->has_indirect = true; } + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_RESOURCE_UUID)) { + vgdev->has_resource_assign_uuid = true; + } DRM_INFO("features: %cvirgl %cedid\n", vgdev->has_virgl_3d ? '+' : '-', diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 050d24c39a8f6..acd14ef73d563 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -23,12 +23,102 @@ */ #include <drm/drm_prime.h> +#include <linux/virtio_dma_buf.h> #include "virtgpu_drv.h" -/* Empty Implementations as there should not be any other driver for a virtual - * device that might share buffers with virtgpu - */ +static int virtgpu_virtio_get_uuid(struct dma_buf *buf, + uuid_t *uuid) +{ + struct drm_gem_object *obj = buf->priv; + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_device *vgdev = obj->dev->dev_private; + + wait_event(vgdev->resp_wq, bo->uuid_state != UUID_INITIALIZING); + if (bo->uuid_state != UUID_INITIALIZED) + return -ENODEV; + + uuid_copy(uuid, &bo->uuid); + + return 0; +} + +const struct virtio_dma_buf_ops virtgpu_dmabuf_ops = { + .ops = { + .cache_sgt_mapping = true, + .attach = virtio_dma_buf_attach, + .detach = drm_gem_map_detach, + .map_dma_buf = drm_gem_map_dma_buf, + .unmap_dma_buf = drm_gem_unmap_dma_buf, + .release = drm_gem_dmabuf_release, + .mmap = drm_gem_dmabuf_mmap, + .vmap = drm_gem_dmabuf_vmap, + .vunmap = drm_gem_dmabuf_vunmap, + }, + .device_attach = drm_gem_map_attach, + .get_uuid = virtgpu_virtio_get_uuid, +}; + +struct dma_buf *virtgpu_gem_prime_export(struct drm_gem_object *obj, + int flags) +{ + struct dma_buf *buf; + struct drm_device *dev = obj->dev; + struct virtio_gpu_device *vgdev = dev->dev_private; + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_object_array *objs; + int ret = 0; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + + if (vgdev->has_resource_assign_uuid) { + objs = virtio_gpu_array_alloc(1); + if (!objs) + return ERR_PTR(-ENOMEM); + virtio_gpu_array_add_obj(objs, &bo->base.base); + + ret = virtio_gpu_cmd_resource_assign_uuid(vgdev, objs); + if (ret) + return ERR_PTR(ret); + virtio_gpu_notify(vgdev); + } else { + bo->uuid_state = UUID_INITIALIZATION_FAILED; + } + + exp_info.ops = &virtgpu_dmabuf_ops.ops; + exp_info.size = obj->size; + exp_info.flags = flags; + exp_info.priv = obj; + exp_info.resv = obj->resv; + + buf = virtio_dma_buf_export(&exp_info); + if (IS_ERR(buf)) + return buf; + + drm_dev_get(dev); + drm_gem_object_get(obj); + + return buf; +} + +struct drm_gem_object *virtgpu_gem_prime_import(struct drm_device *dev, + struct dma_buf *buf) +{ + struct drm_gem_object *obj; + + if (buf->ops == &virtgpu_dmabuf_ops.ops) { + 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 *virtgpu_gem_prime_import_sg_table( struct drm_device *dev, struct dma_buf_attachment *attach, diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 9e663a5d99526..823223b0bb75a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -1107,3 +1107,58 @@ void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev, memcpy(cur_p, &output->cursor, sizeof(output->cursor)); virtio_gpu_queue_cursor(vgdev, vbuf); } + +static void virtio_gpu_cmd_resource_uuid_cb(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) +{ + struct virtio_gpu_object *obj = + gem_to_virtio_gpu_obj(vbuf->objs->objs[0]); + struct virtio_gpu_resp_resource_uuid *resp = + (struct virtio_gpu_resp_resource_uuid *)vbuf->resp_buf; + uint32_t resp_type = le32_to_cpu(resp->hdr.type); + + spin_lock(&vgdev->resource_export_lock); + WARN_ON(obj->uuid_state != UUID_INITIALIZING); + + if (resp_type == VIRTIO_GPU_RESP_OK_RESOURCE_UUID && + obj->uuid_state == UUID_INITIALIZING) { + memcpy(&obj->uuid.b, resp->uuid, sizeof(obj->uuid.b)); + obj->uuid_state = UUID_INITIALIZED; + } else { + obj->uuid_state = UUID_INITIALIZATION_FAILED; + } + spin_unlock(&vgdev->resource_export_lock); + + wake_up_all(&vgdev->resp_wq); +} + +int +virtio_gpu_cmd_resource_assign_uuid(struct virtio_gpu_device *vgdev, + struct virtio_gpu_object_array *objs) +{ + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(objs->objs[0]); + struct virtio_gpu_resource_assign_uuid *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + struct virtio_gpu_resp_resource_uuid *resp_buf; + + resp_buf = kzalloc(sizeof(*resp_buf), GFP_KERNEL); + if (!resp_buf) { + spin_lock(&vgdev->resource_export_lock); + bo->uuid_state = UUID_INITIALIZATION_FAILED; + spin_unlock(&vgdev->resource_export_lock); + virtio_gpu_array_put_free(objs); + return -ENOMEM; + } + + cmd_p = virtio_gpu_alloc_cmd_resp + (vgdev, virtio_gpu_cmd_resource_uuid_cb, &vbuf, sizeof(*cmd_p), + sizeof(struct virtio_gpu_resp_resource_uuid), resp_buf); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID); + cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); + + vbuf->objs = objs; + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + return 0; +} -- GitLab From f13478c9da834f2d092192c0097587bd07ab8928 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn <rikard.falkeborn@gmail.com> Date: Tue, 4 Aug 2020 23:53:37 +0200 Subject: [PATCH 0526/1494] drm/sun4i: Constify static structs A number of static variables are not modified and can be made const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200804215337.54594-1-rikard.falkeborn@gmail.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +- drivers/gpu/drm/sun4i/sun4i_framebuffer.c | 2 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 2 +- drivers/gpu/drm/sun4i/sun4i_lvds.c | 2 +- drivers/gpu/drm/sun4i/sun4i_rgb.c | 4 ++-- drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +- drivers/gpu/drm/sun4i/sun4i_tv.c | 6 +++--- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +- drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 +- drivers/gpu/drm/sun4i/sun8i_mixer.c | 2 +- drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 +- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 072ea113e6be5..f025534eb30cc 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -769,7 +769,7 @@ static const struct sunxi_engine_ops sun4i_backend_engine_ops = { .vblank_quirk = sun4i_backend_vblank_quirk, }; -static struct regmap_config sun4i_backend_regmap_config = { +static const struct regmap_config sun4i_backend_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c index 1568f68f9a9ef..6825ef46f43fe 100644 --- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c +++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c @@ -35,7 +35,7 @@ static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = { .fb_create = drm_gem_fb_create, }; -static struct drm_mode_config_helper_funcs sun4i_de_mode_config_helpers = { +static const struct drm_mode_config_helper_funcs sun4i_de_mode_config_helpers = { .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, }; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index ec2a032e07b97..b51cc685c13ad 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -545,7 +545,7 @@ int sun4i_frontend_enable(struct sun4i_frontend *frontend) } EXPORT_SYMBOL(sun4i_frontend_enable); -static struct regmap_config sun4i_frontend_regmap_config = { +static const struct regmap_config sun4i_frontend_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c index d06dd313d3c01..ac570437172e2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -47,7 +47,7 @@ static int sun4i_lvds_get_modes(struct drm_connector *connector) return drm_panel_get_modes(lvds->panel, connector); } -static struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { +static const struct drm_connector_helper_funcs sun4i_lvds_con_helper_funcs = { .get_modes = sun4i_lvds_get_modes, }; diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 23df1ec034162..e172426eb7e9e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -138,7 +138,7 @@ static enum drm_mode_status sun4i_rgb_mode_valid(struct drm_encoder *crtc, return MODE_OK; } -static struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = { +static const struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = { .get_modes = sun4i_rgb_get_modes, }; @@ -180,7 +180,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) } } -static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = { +static const struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = { .disable = sun4i_rgb_encoder_disable, .enable = sun4i_rgb_encoder_enable, .mode_valid = sun4i_rgb_mode_valid, diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 359b56e43b83c..ae177b2bcf4b9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -825,7 +825,7 @@ static int sun4i_tcon_init_irq(struct device *dev, return 0; } -static struct regmap_config sun4i_tcon_regmap_config = { +static const struct regmap_config sun4i_tcon_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index 63f4428ac3bf7..cb91bc11a0c7e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -468,7 +468,7 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0); } -static struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = { +static const struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = { .disable = sun4i_tv_disable, .enable = sun4i_tv_enable, .mode_set = sun4i_tv_mode_set, @@ -504,7 +504,7 @@ static int sun4i_tv_comp_mode_valid(struct drm_connector *connector, return MODE_OK; } -static struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = { +static const struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = { .get_modes = sun4i_tv_comp_get_modes, .mode_valid = sun4i_tv_comp_mode_valid, }; @@ -523,7 +523,7 @@ static const struct drm_connector_funcs sun4i_tv_comp_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static struct regmap_config sun4i_tv_regmap_config = { +static const struct regmap_config sun4i_tv_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index a78aebfe773db..9abde2817e1b3 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -820,7 +820,7 @@ static int sun6i_dsi_get_modes(struct drm_connector *connector) return drm_panel_get_modes(dsi->panel, connector); } -static struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = { +static const struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = { .get_modes = sun6i_dsi_get_modes, }; diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index 156d00e5165ba..35c2133724e2d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c @@ -534,7 +534,7 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, } } -static struct regmap_config sun8i_hdmi_phy_regmap_config = { +static const struct regmap_config sun8i_hdmi_phy_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index cc4fb916318f3..4b59806b30df2 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -303,7 +303,7 @@ static const struct sunxi_engine_ops sun8i_engine_ops = { .layers_init = sun8i_layers_init, }; -static struct regmap_config sun8i_mixer_regmap_config = { +static const struct regmap_config sun8i_mixer_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index 54f937a7d5e7a..816ad4ce8996f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -298,7 +298,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, true, zpos, old_zpos); } -static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { +static const struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = sun8i_ui_layer_atomic_check, .atomic_disable = sun8i_ui_layer_atomic_disable, diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 22c8c5375d0db..a360697a4a4ae 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -401,7 +401,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, true, zpos, old_zpos); } -static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { +static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = sun8i_vi_layer_atomic_check, .atomic_disable = sun8i_vi_layer_atomic_disable, -- GitLab From 652bcaec7da0f06f00be578c200e1c57099449d2 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Tue, 11 Aug 2020 16:23:06 +0800 Subject: [PATCH 0527/1494] MAINTAINERS: Change maintainer for hisilicon DRM driver Remove Rongrong Zou and change tiantao as hisilicon DRM maintainer. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: xinliang.liu <xinliang.liu@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/1597134186-58423-1-git-send-email-tiantao6@hisilicon.com --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index bebc222504346..dfbd5df0b8b77 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5694,7 +5694,7 @@ F: drivers/gpu/drm/gma500/ DRM DRIVERS FOR HISILICON M: Xinliang Liu <xinliang.liu@linaro.org> -M: Rongrong Zou <zourongrong@gmail.com> +M: Tian Tao <tiantao6@hisilicon.com> R: John Stultz <john.stultz@linaro.org> R: Xinwei Kong <kong.kongxinwei@hisilicon.com> R: Chen Feng <puck.chen@hisilicon.com> -- GitLab From d3d1bbe794ab4f7cce13e8ba08a2ac978133375e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Fri, 7 Aug 2020 13:10:22 +0200 Subject: [PATCH 0528/1494] drm/malidp: Use struct drm_gem_object_funcs.get_sg_table internally The malidp driver uses GEM object functions for callbacks. Fix it to use them internally as well. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Daniel Vetter <daniel@ffwll.ch> Fixes: ecdd6474644f ("drm/malidp: Use GEM CMA object functions") Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Emil Velikov <emil.velikov@collabora.com> Cc: Liviu Dudau <liviu.dudau@arm.com> Cc: Brian Starkey <brian.starkey@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200807111022.12117-1-tzimmermann@suse.de --- drivers/gpu/drm/arm/malidp_planes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index ab45ac445045a..351a85088d0ec 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -346,7 +346,7 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms, if (cma_obj->sgt) sgt = cma_obj->sgt; else - sgt = obj->dev->driver->gem_prime_get_sg_table(obj); + sgt = obj->funcs->get_sg_table(obj); if (!sgt) return false; -- GitLab From faa962bbae312eaf84838bbdc96ccc216ba248ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> Date: Mon, 17 Aug 2020 10:14:34 +0200 Subject: [PATCH 0529/1494] dt-bindings: vendor-prefixes: Add mantix vendor prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add prefix for Mantix Display Technology Co.,Ltd. Signed-off-by: Guido Günther <agx@sigxcpu.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/b6bcfe27d9393a07a5cdd82fcf211620c774a273.1597652012.git.agx@sigxcpu.org --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 25c89f92b5372..a1e4356cf522f 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -615,6 +615,8 @@ patternProperties: description: Linux Automation GmbH "^macnica,.*": description: Macnica Americas + "^mantix,.*": + description: Mantix Display Technology Co.,Ltd. "^mapleboard,.*": description: Mapleboard.org "^marvell,.*": -- GitLab From b9ab1248d801bfa4fb7c35762d172455cf3795f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> Date: Mon, 17 Aug 2020 10:14:35 +0200 Subject: [PATCH 0530/1494] dt-bindings: Add Mantix MLAF057WE51-X panel bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The panel uses a Focaltech FT8006p, the touch part is handled by the already existing edt-ft5x06. Signed-off-by: Guido Günther <agx@sigxcpu.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/b84c8c00ee1dcf545903a475872e1ae62b5f43ea.1597652012.git.agx@sigxcpu.org --- .../display/panel/mantix,mlaf057we51-x.yaml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml diff --git a/Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml b/Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml new file mode 100644 index 0000000000000..937323cc9aaac --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/mantix,mlaf057we51-x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mantix MLAF057WE51-X 5.7" 720x1440 TFT LCD panel + +maintainers: + - Guido Günther <agx@sigxcpu.org> + +description: + Mantix MLAF057WE51 X is a 720x1440 TFT LCD panel connected using + a MIPI-DSI video interface. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + enum: + - mantix,mlaf057we51-x + + port: true + reg: + maxItems: 1 + description: DSI virtual channel + + avdd-supply: + description: Positive analog power supply + + avee-supply: + description: Negative analog power supply + + vddi-supply: + description: 1.8V I/O voltage supply + + reset-gpios: true + + backlight: true + +required: + - compatible + - reg + - avdd-supply + - avee-supply + - vddi-supply + - reset-gpios + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + dsi { + #address-cells = <1>; + #size-cells = <0>; + panel@0 { + compatible = "mantix,mlaf057we51-x"; + reg = <0>; + avdd-supply = <®_avdd>; + avee-supply = <®_avee>; + vddi-supply = <®_1v8_p>; + reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>; + backlight = <&backlight>; + }; + }; + +... -- GitLab From 72967d5616d3f0c714f8eb6c4e258179a9031c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org> Date: Mon, 17 Aug 2020 10:14:36 +0200 Subject: [PATCH 0531/1494] drm/panel: Add panel driver for the Mantix MLAF057WE51-X DSI panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The panel uses a Focaltech FT8006p, the touch part is handled by the already existing edt-ft5x06. Signed-off-by: Guido Günther <agx@sigxcpu.org> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/118c6e03dd0ff6e86e495579102cbf7d0cfca6f4.1597652012.git.agx@sigxcpu.org --- MAINTAINERS | 7 + drivers/gpu/drm/panel/Kconfig | 11 + drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-mantix-mlaf057we51.c | 328 ++++++++++++++++++ 4 files changed, 347 insertions(+) create mode 100644 drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c diff --git a/MAINTAINERS b/MAINTAINERS index 9e1873182f2ee..01fb9ee6b951e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5474,6 +5474,13 @@ S: Maintained F: drivers/gpu/drm/panel/panel-lvds.c F: Documentation/devicetree/bindings/display/panel/lvds.yaml +DRM DRIVER FOR MANTIX MLAF057WE51 PANELS +M: Guido Günther <agx@sigxcpu.org> +R: Purism Kernel Team <kernel@puri.sm> +S: Maintained +F: Documentation/devicetree/bindings/display/panel/mantix,mlaf057we51-x.yaml +F: drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c + DRM DRIVER FOR MATROX G200/G400 GRAPHICS CARDS S: Orphan / Obsolete F: drivers/gpu/drm/mga/ diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index de2f2a452be55..8d97d07c58713 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -217,6 +217,17 @@ config DRM_PANEL_NOVATEK_NT39016 Say Y here if you want to enable support for the panels built around the Novatek NT39016 display controller. +config DRM_PANEL_MANTIX_MLAF057WE51 + tristate "Mantix MLAF057WE51-X MIPI-DSI LCD panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the Mantix + MLAF057WE51-X MIPI DSI panel as e.g. used in the Librem 5. It + has a resolution of 720x1440 pixels, a built in backlight and touch + controller. + config DRM_PANEL_OLIMEX_LCD_OLINUXINO tristate "Olimex LCD-OLinuXino panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index e45ceac6286fd..15a4e77529514 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o +obj-$(CONFIG_DRM_PANEL_MANTIX_MLAF057WE51) += panel-mantix-mlaf057we51.o obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o diff --git a/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c new file mode 100644 index 0000000000000..3482e28e30fc9 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mantix MLAF057WE51 5.7" MIPI-DSI panel driver + * + * Copyright (C) Purism SPC 2020 + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +#define DRV_NAME "panel-mantix-mlaf057we51" + +/* Manufacturer specific Commands send via DSI */ +#define MANTIX_CMD_OTP_STOP_RELOAD_MIPI 0x41 +#define MANTIX_CMD_INT_CANCEL 0x4C + +struct mantix { + struct device *dev; + struct drm_panel panel; + struct gpio_desc *reset_gpio; + + struct regulator *avdd; + struct regulator *avee; + struct regulator *vddi; +}; + +static inline struct mantix *panel_to_mantix(struct drm_panel *panel) +{ + return container_of(panel, struct mantix, panel); +} + +#define dsi_generic_write_seq(dsi, seq...) do { \ + static const u8 d[] = { seq }; \ + int ret; \ + ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ + if (ret < 0) \ + return ret; \ + } while (0) + +static int mantix_init_sequence(struct mantix *ctx) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + struct device *dev = ctx->dev; + + /* + * Init sequence was supplied by the panel vendor. + */ + dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A); + + dsi_generic_write_seq(dsi, MANTIX_CMD_INT_CANCEL, 0x03); + dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x03); + dsi_generic_write_seq(dsi, 0x80, 0xA9, 0x00); + + dsi_generic_write_seq(dsi, MANTIX_CMD_OTP_STOP_RELOAD_MIPI, 0x5A, 0x09); + dsi_generic_write_seq(dsi, 0x80, 0x64, 0x00, 0x64, 0x00, 0x00); + msleep(20); + + dev_dbg(dev, "Panel init sequence done\n"); + return 0; +} + +static int mantix_enable(struct drm_panel *panel) +{ + struct mantix *ctx = panel_to_mantix(panel); + struct device *dev = ctx->dev; + struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + int ret; + + ret = mantix_init_sequence(ctx); + if (ret < 0) { + dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); + return ret; + } + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + dev_err(dev, "Failed to exit sleep mode\n"); + return ret; + } + msleep(20); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret) + return ret; + usleep_range(10000, 12000); + + ret = mipi_dsi_turn_on_peripheral(dsi); + if (ret < 0) { + dev_err(dev, "Failed to turn on peripheral\n"); + return ret; + } + + return 0; +} + +static int mantix_disable(struct drm_panel *panel) +{ + struct mantix *ctx = panel_to_mantix(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); + int ret; + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret < 0) + dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret); + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret < 0) + dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); + + + return 0; +} + +static int mantix_unprepare(struct drm_panel *panel) +{ + struct mantix *ctx = panel_to_mantix(panel); + + regulator_disable(ctx->avee); + regulator_disable(ctx->avdd); + /* T11 */ + usleep_range(5000, 6000); + regulator_disable(ctx->vddi); + /* T14 */ + msleep(50); + + return 0; +} + +static int mantix_prepare(struct drm_panel *panel) +{ + struct mantix *ctx = panel_to_mantix(panel); + int ret; + + /* Focaltech FT8006P, section 7.3.1 and 7.3.4 */ + dev_dbg(ctx->dev, "Resetting the panel\n"); + ret = regulator_enable(ctx->vddi); + if (ret < 0) { + dev_err(ctx->dev, "Failed to enable vddi supply: %d\n", ret); + return ret; + } + + /* T1 + T2 */ + usleep_range(8000, 10000); + + ret = regulator_enable(ctx->avdd); + if (ret < 0) { + dev_err(ctx->dev, "Failed to enable avdd supply: %d\n", ret); + return ret; + } + + /* T2d */ + usleep_range(3500, 4000); + ret = regulator_enable(ctx->avee); + if (ret < 0) { + dev_err(ctx->dev, "Failed to enable avee supply: %d\n", ret); + return ret; + } + + /* T3+T5 */ + usleep_range(10000, 12000); + + gpiod_set_value_cansleep(ctx->reset_gpio, 1); + usleep_range(5150, 7000); + + gpiod_set_value_cansleep(ctx->reset_gpio, 0); + + /* T6 */ + msleep(50); + + return 0; +} + +static const struct drm_display_mode default_mode = { + .hdisplay = 720, + .hsync_start = 720 + 45, + .hsync_end = 720 + 45 + 14, + .htotal = 720 + 45 + 14 + 25, + .vdisplay = 1440, + .vsync_start = 1440 + 130, + .vsync_end = 1440 + 130 + 8, + .vtotal = 1440 + 130 + 8 + 106, + .clock = 85298, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + .width_mm = 65, + .height_mm = 130, +}; + +static int mantix_get_modes(struct drm_panel *panel, + struct drm_connector *connector) +{ + struct mantix *ctx = panel_to_mantix(panel); + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &default_mode); + if (!mode) { + dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(mode)); + return -ENOMEM; + } + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + drm_mode_probed_add(connector, mode); + + return 1; +} + +static const struct drm_panel_funcs mantix_drm_funcs = { + .disable = mantix_disable, + .unprepare = mantix_unprepare, + .prepare = mantix_prepare, + .enable = mantix_enable, + .get_modes = mantix_get_modes, +}; + +static int mantix_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct mantix *ctx; + int ret; + + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ctx->reset_gpio)) { + dev_err(dev, "cannot get reset gpio\n"); + return PTR_ERR(ctx->reset_gpio); + } + + mipi_dsi_set_drvdata(dsi, ctx); + ctx->dev = dev; + + dsi->lanes = 4; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + + ctx->avdd = devm_regulator_get(dev, "avdd"); + if (IS_ERR(ctx->avdd)) + return dev_err_probe(dev, PTR_ERR(ctx->avdd), "Failed to request avdd regulator\n"); + + ctx->avee = devm_regulator_get(dev, "avee"); + if (IS_ERR(ctx->avee)) + return dev_err_probe(dev, PTR_ERR(ctx->avee), "Failed to request avee regulator\n"); + + ctx->vddi = devm_regulator_get(dev, "vddi"); + if (IS_ERR(ctx->vddi)) + return dev_err_probe(dev, PTR_ERR(ctx->vddi), "Failed to request vddi regulator\n"); + + drm_panel_init(&ctx->panel, dev, &mantix_drm_funcs, + DRM_MODE_CONNECTOR_DSI); + + ret = drm_panel_of_backlight(&ctx->panel); + if (ret) + return ret; + + drm_panel_add(&ctx->panel); + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret); + drm_panel_remove(&ctx->panel); + return ret; + } + + dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode), + mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); + + return 0; +} + +static void mantix_shutdown(struct mipi_dsi_device *dsi) +{ + struct mantix *ctx = mipi_dsi_get_drvdata(dsi); + + drm_panel_unprepare(&ctx->panel); + drm_panel_disable(&ctx->panel); +} + +static int mantix_remove(struct mipi_dsi_device *dsi) +{ + struct mantix *ctx = mipi_dsi_get_drvdata(dsi); + + mantix_shutdown(dsi); + + mipi_dsi_detach(dsi); + drm_panel_remove(&ctx->panel); + + return 0; +} + +static const struct of_device_id mantix_of_match[] = { + { .compatible = "mantix,mlaf057we51-x" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mantix_of_match); + +static struct mipi_dsi_driver mantix_driver = { + .probe = mantix_probe, + .remove = mantix_remove, + .shutdown = mantix_shutdown, + .driver = { + .name = DRV_NAME, + .of_match_table = mantix_of_match, + }, +}; +module_mipi_dsi_driver(mantix_driver); + +MODULE_AUTHOR("Guido Günther <agx@sigxcpu.org>"); +MODULE_DESCRIPTION("DRM driver for Mantix MLAF057WE51-X MIPI DSI panel"); +MODULE_LICENSE("GPL v2"); -- GitLab From 5936b3bdaa888907596df0a954db4d14657ec621 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sat, 15 Aug 2020 14:54:02 +0200 Subject: [PATCH 0532/1494] drm/panel: samsung: Use dev_ based logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on the dev_ based logging and drop the include of drm_print.h. Fix a few cases where "x@" was used when printing the mode. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Reviewed-by: Guido Günther <agx@sigxcpu.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Guido Günther <agx@sigxcpu.org> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200815125406.1153224-2-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-samsung-ld9040.c | 3 +-- drivers/gpu/drm/panel/panel-samsung-s6d16d0.c | 23 +++++++------------ drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 3 +-- .../gpu/drm/panel/panel-samsung-s6e63j0x03.c | 3 +-- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 22 ++++++++---------- drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c | 3 +-- 6 files changed, 21 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c index 358168ed8355d..f484147fc3a66 100644 --- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c +++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c @@ -21,7 +21,6 @@ #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> /* Manufacturer Command Set */ #define MCS_MANPWR 0xb0 @@ -269,7 +268,7 @@ static int ld9040_get_modes(struct drm_panel *panel, mode = drm_mode_create(connector->dev); if (!mode) { - DRM_ERROR("failed to create a new display mode\n"); + dev_err(panel->dev, "failed to create a new display mode\n"); return 0; } diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c index e88af6f8bf60d..4aac0d1573dd0 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c @@ -7,7 +7,6 @@ #include <drm/drm_modes.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> @@ -55,8 +54,7 @@ static int s6d16d0_unprepare(struct drm_panel *panel) /* Enter sleep mode */ ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to enter sleep mode (%d)\n", - ret); + dev_err(s6->dev, "failed to enter sleep mode (%d)\n", ret); return ret; } @@ -75,7 +73,7 @@ static int s6d16d0_prepare(struct drm_panel *panel) ret = regulator_enable(s6->supply); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to enable supply (%d)\n", ret); + dev_err(s6->dev, "failed to enable supply (%d)\n", ret); return ret; } @@ -90,15 +88,13 @@ static int s6d16d0_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to enable vblank TE (%d)\n", - ret); + dev_err(s6->dev, "failed to enable vblank TE (%d)\n", ret); return ret; } /* Exit sleep mode and power on */ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to exit sleep mode (%d)\n", - ret); + dev_err(s6->dev, "failed to exit sleep mode (%d)\n", ret); return ret; } @@ -113,8 +109,7 @@ static int s6d16d0_enable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to turn display on (%d)\n", - ret); + dev_err(s6->dev, "failed to turn display on (%d)\n", ret); return ret; } @@ -129,8 +124,7 @@ static int s6d16d0_disable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret) { - DRM_DEV_ERROR(s6->dev, "failed to turn display off (%d)\n", - ret); + dev_err(s6->dev, "failed to turn display off (%d)\n", ret); return ret; } @@ -144,7 +138,7 @@ static int s6d16d0_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &samsung_s6d16d0_mode); if (!mode) { - DRM_ERROR("bad mode or failed to add mode\n"); + dev_err(panel->dev, "bad mode or failed to add mode\n"); return -EINVAL; } drm_mode_set_name(mode); @@ -204,8 +198,7 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi) if (IS_ERR(s6->reset_gpio)) { ret = PTR_ERR(s6->reset_gpio); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n", - ret); + dev_err(dev, "failed to request GPIO (%d)\n", ret); return ret; } diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c index 2c84036c6a65e..1d1c79a186139 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c @@ -18,7 +18,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define S6E3HA2_MIN_BRIGHTNESS 0 #define S6E3HA2_MAX_BRIGHTNESS 100 @@ -651,7 +650,7 @@ static int s6e3ha2_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); if (!mode) { - DRM_ERROR("failed to add mode %ux%ux@%u\n", + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, drm_mode_vrefresh(ctx->desc->mode)); return -ENOMEM; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c index 7a43eb3545cfb..b962c817fb307 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c @@ -19,7 +19,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define MCS_LEVEL2_KEY 0xf0 #define MCS_MTP_KEY 0xf1 @@ -406,7 +405,7 @@ static int s6e63j0x03_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_ERROR("failed to add mode %ux%ux@%u\n", + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", default_mode.hdisplay, default_mode.vdisplay, drm_mode_vrefresh(&default_mode)); return -ENOMEM; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index e086efea29505..2cc772fdc456d 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -10,7 +10,6 @@ #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <linux/backlight.h> #include <linux/delay.h> @@ -157,7 +156,7 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len) if (ctx->error < 0 || len == 0) return; - DRM_DEV_DEBUG(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data); + dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data); ret = s6e63m0_spi_write_word(ctx, *data); while (!ret && --len) { @@ -166,8 +165,7 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len) } if (ret) { - DRM_DEV_ERROR(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, - (int)len, data); + dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, (int)len, data); ctx->error = ret; } @@ -368,9 +366,9 @@ static int s6e63m0_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_ERROR("failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -425,8 +423,7 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx) &props); if (IS_ERR(ctx->bl_dev)) { ret = PTR_ERR(ctx->bl_dev); - DRM_DEV_ERROR(dev, "error registering backlight device (%d)\n", - ret); + dev_err(dev, "error registering backlight device (%d)\n", ret); } return ret; @@ -453,14 +450,13 @@ static int s6e63m0_probe(struct spi_device *spi) ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ctx->supplies), ctx->supplies); if (ret < 0) { - DRM_DEV_ERROR(dev, "failed to get regulators: %d\n", ret); + dev_err(dev, "failed to get regulators: %d\n", ret); return ret; } ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset-gpios %ld\n", - PTR_ERR(ctx->reset_gpio)); + dev_err(dev, "cannot get reset-gpios %ld\n", PTR_ERR(ctx->reset_gpio)); return PTR_ERR(ctx->reset_gpio); } @@ -468,7 +464,7 @@ static int s6e63m0_probe(struct spi_device *spi) spi->mode = SPI_MODE_3; ret = spi_setup(spi); if (ret < 0) { - DRM_DEV_ERROR(dev, "spi setup failed.\n"); + dev_err(dev, "spi setup failed.\n"); return ret; } diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c index e36cb1a253187..5273711202661 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c @@ -25,7 +25,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define LDI_MTP_LENGTH 24 #define GAMMA_LEVEL_NUM 25 @@ -928,7 +927,7 @@ static int s6e8aa0_get_modes(struct drm_panel *panel, mode = drm_mode_create(connector->dev); if (!mode) { - DRM_ERROR("failed to create a new display mode\n"); + dev_err(panel->dev, "failed to create a new display mode\n"); return 0; } -- GitLab From b75efff5f542fe31a1a894ed72f57f8e3139d22d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sat, 15 Aug 2020 14:54:03 +0200 Subject: [PATCH 0533/1494] drm/panel: leadtek: Use dev_ based logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on the dev_ based logging and drop the include of drm_print.h. Fix a few cases where "x@" was used when printing the mode. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Guido Günther <agx@sigxcpu.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Guido Günther <agx@sigxcpu.org> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200815125406.1153224-3-sam@ravnborg.org --- .../drm/panel/panel-leadtek-ltk050h3146w.c | 58 +++++++------------ .../drm/panel/panel-leadtek-ltk500hd1829.c | 49 ++++++---------- 2 files changed, 37 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c index eaa9da3ebbeaf..ed0d5f959037d 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c @@ -17,7 +17,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct ltk050h3146w_cmd { char cmd; @@ -314,8 +313,7 @@ static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx) ret = mipi_dsi_dcs_set_tear_on(dsi, 1); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to set tear on: %d\n", - ret); + dev_err(ctx->dev, "failed to set tear on: %d\n", ret); return ret; } @@ -360,8 +358,7 @@ static int ltk050h3146w_a2_write_page(struct ltk050h3146w *ctx, int page, ret = ltk050h3146w_a2_select_page(ctx, page); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to select page %d: %d\n", - page, ret); + dev_err(ctx->dev, "failed to select page %d: %d\n", page, ret); return ret; } @@ -369,9 +366,7 @@ static int ltk050h3146w_a2_write_page(struct ltk050h3146w *ctx, int page, ret = mipi_dsi_generic_write(dsi, &cmds[i], sizeof(struct ltk050h3146w_cmd)); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "failed to write page %d init cmds: %d\n", - page, ret); + dev_err(ctx->dev, "failed to write page %d init cmds: %d\n", page, ret); return ret; } } @@ -405,15 +400,14 @@ static int ltk050h3146w_a2_init_sequence(struct ltk050h3146w *ctx) ret = ltk050h3146w_a2_select_page(ctx, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to select page 0: %d\n", ret); + dev_err(ctx->dev, "failed to select page 0: %d\n", ret); return ret; } /* vendor code called this without param, where there should be one */ ret = mipi_dsi_dcs_set_tear_on(dsi, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to set tear on: %d\n", - ret); + dev_err(ctx->dev, "failed to set tear on: %d\n", ret); return ret; } @@ -452,15 +446,13 @@ static int ltk050h3146w_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to set display off: %d\n", - ret); + dev_err(ctx->dev, "failed to set display off: %d\n", ret); return ret; } mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret); return ret; } @@ -481,17 +473,15 @@ static int ltk050h3146w_prepare(struct drm_panel *panel) if (ctx->prepared) return 0; - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); + dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vci); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable vci supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); return ret; } ret = regulator_enable(ctx->iovcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable iovcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); goto disable_vci; } @@ -502,14 +492,13 @@ static int ltk050h3146w_prepare(struct drm_panel *panel) ret = ctx->panel_desc->init(ctx); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", - ret); + dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); goto disable_iovcc; } ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to exit sleep mode: %d\n", ret); + dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); goto disable_iovcc; } @@ -518,7 +507,7 @@ static int ltk050h3146w_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to set display on: %d\n", ret); + dev_err(ctx->dev, "Failed to set display on: %d\n", ret); goto disable_iovcc; } @@ -577,7 +566,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); + dev_err(dev, "cannot get reset gpio\n"); return PTR_ERR(ctx->reset_gpio); } @@ -585,9 +574,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vci)) { ret = PTR_ERR(ctx->vci); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request vci regulator: %d\n", - ret); + dev_err(dev, "Failed to request vci regulator: %d\n", ret); return ret; } @@ -595,9 +582,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->iovcc)) { ret = PTR_ERR(ctx->iovcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request iovcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request iovcc regulator: %d\n", ret); return ret; } @@ -621,7 +606,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret); + dev_err(dev, "mipi_dsi_attach failed: %d\n", ret); drm_panel_remove(&ctx->panel); return ret; } @@ -636,13 +621,11 @@ static void ltk050h3146w_shutdown(struct mipi_dsi_device *dsi) ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); ret = drm_panel_disable(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } static int ltk050h3146w_remove(struct mipi_dsi_device *dsi) @@ -654,8 +637,7 @@ static int ltk050h3146w_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", - ret); + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c index 0f6a248c47a51..3c00e4f8f8037 100644 --- a/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c +++ b/drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c @@ -20,7 +20,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct ltk500hd1829 { struct device *dev; @@ -278,13 +277,11 @@ static int ltk500hd1829_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - ret); + dev_err(panel->dev, "failed to set display off: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", ret); } /* 120ms to enter sleep mode */ @@ -310,14 +307,12 @@ static int ltk500hd1829_prepare(struct drm_panel *panel) ret = regulator_enable(ctx->vcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable vci supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); return ret; } ret = regulator_enable(ctx->iovcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable iovcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); goto disable_vcc; } @@ -333,16 +328,14 @@ static int ltk500hd1829_prepare(struct drm_panel *panel) ret = mipi_dsi_generic_write(dsi, &init_code[i], sizeof(struct ltk500hd1829_cmd)); if (ret < 0) { - DRM_DEV_ERROR(panel->dev, - "failed to write init cmds: %d\n", ret); + dev_err(panel->dev, "failed to write init cmds: %d\n", ret); goto disable_iovcc; } } ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", - ret); + dev_err(panel->dev, "failed to exit sleep mode: %d\n", ret); goto disable_iovcc; } @@ -351,8 +344,7 @@ static int ltk500hd1829_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", - ret); + dev_err(panel->dev, "failed to set display on: %d\n", ret); goto disable_iovcc; } @@ -389,9 +381,9 @@ static int ltk500hd1829_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(ctx->dev, "failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(ctx->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -423,7 +415,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); + dev_err(dev, "cannot get reset gpio\n"); return PTR_ERR(ctx->reset_gpio); } @@ -431,9 +423,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vcc)) { ret = PTR_ERR(ctx->vcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request vcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request vcc regulator: %d\n", ret); return ret; } @@ -441,9 +431,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->iovcc)) { ret = PTR_ERR(ctx->iovcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request iovcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request iovcc regulator: %d\n", ret); return ret; } @@ -467,7 +455,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret); + dev_err(dev, "mipi_dsi_attach failed: %d\n", ret); drm_panel_remove(&ctx->panel); return ret; } @@ -482,13 +470,11 @@ static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi) ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); ret = drm_panel_disable(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } static int ltk500hd1829_remove(struct mipi_dsi_device *dsi) @@ -500,8 +486,7 @@ static int ltk500hd1829_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", - ret); + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); -- GitLab From c8cf6990f98688ae382770b55cab9ceec5a2fc8f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sat, 15 Aug 2020 14:54:04 +0200 Subject: [PATCH 0534/1494] drm/panel: raydium: Use dev_ based logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on the dev_ based logging and drop the include of drm_print.h. Fix a few cases where "x@" was used when printing the mode. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Guido Günther <agx@sigxcpu.org> Cc: Robert Chiras <robert.chiras@nxp.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Guido Günther <agx@sigxcpu.org> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200815125406.1153224-4-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-raydium-rm67191.c | 33 +++++++++---------- drivers/gpu/drm/panel/panel-raydium-rm68200.c | 18 +++++----- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c index 2ef3225821339..23b62081e951d 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -19,7 +19,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> /* Panel specific color-format bits */ #define COL_FMT_16BPP 0x55 @@ -329,7 +328,7 @@ static int rad_panel_enable(struct drm_panel *panel) ret = rad_panel_push_cmd_list(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to send MCS (%d)\n", ret); + dev_err(dev, "Failed to send MCS (%d)\n", ret); goto fail; } @@ -341,7 +340,7 @@ static int rad_panel_enable(struct drm_panel *panel) /* Software reset */ ret = mipi_dsi_dcs_soft_reset(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to do Software Reset (%d)\n", ret); + dev_err(dev, "Failed to do Software Reset (%d)\n", ret); goto fail; } @@ -350,33 +349,32 @@ static int rad_panel_enable(struct drm_panel *panel) /* Set DSI mode */ ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set DSI mode (%d)\n", ret); + dev_err(dev, "Failed to set DSI mode (%d)\n", ret); goto fail; } /* Set tear ON */ ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set tear ON (%d)\n", ret); + dev_err(dev, "Failed to set tear ON (%d)\n", ret); goto fail; } /* Set tear scanline */ ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set tear scanline (%d)\n", ret); + dev_err(dev, "Failed to set tear scanline (%d)\n", ret); goto fail; } /* Set pixel format */ ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format); - DRM_DEV_DEBUG_DRIVER(dev, "Interface color format set to 0x%x\n", - color_format); + dev_dbg(dev, "Interface color format set to 0x%x\n", color_format); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set pixel format (%d)\n", ret); + dev_err(dev, "Failed to set pixel format (%d)\n", ret); goto fail; } /* Exit sleep mode */ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to exit sleep mode (%d)\n", ret); + dev_err(dev, "Failed to exit sleep mode (%d)\n", ret); goto fail; } @@ -384,7 +382,7 @@ static int rad_panel_enable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set display ON (%d)\n", ret); + dev_err(dev, "Failed to set display ON (%d)\n", ret); goto fail; } @@ -418,7 +416,7 @@ static int rad_panel_disable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to set display OFF (%d)\n", ret); + dev_err(dev, "Failed to set display OFF (%d)\n", ret); return ret; } @@ -426,7 +424,7 @@ static int rad_panel_disable(struct drm_panel *panel) ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to enter sleep mode (%d)\n", ret); + dev_err(dev, "Failed to enter sleep mode (%d)\n", ret); return ret; } @@ -442,9 +440,9 @@ static int rad_panel_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(panel->dev, "failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -626,8 +624,7 @@ static int rad_panel_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret) - DRM_DEV_ERROR(dev, "Failed to detach from host (%d)\n", - ret); + dev_err(dev, "Failed to detach from host (%d)\n", ret); drm_panel_remove(&rad->panel); diff --git a/drivers/gpu/drm/panel/panel-raydium-rm68200.c b/drivers/gpu/drm/panel/panel-raydium-rm68200.c index 81ae8be62d15d..f908eeafb1afd 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm68200.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm68200.c @@ -17,7 +17,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> /*** Manufacturer Command Set ***/ #define MCS_CMD_MODE_SW 0xFE /* CMD Mode Switch */ @@ -110,8 +109,7 @@ static void rm68200_dcs_write_buf(struct rm68200 *ctx, const void *data, err = mipi_dsi_dcs_write_buffer(dsi, data, len); if (err < 0) - DRM_ERROR_RATELIMITED("MIPI DSI DCS write buffer failed: %d\n", - err); + dev_err_ratelimited(ctx->dev, "MIPI DSI DCS write buffer failed: %d\n", err); } static void rm68200_dcs_write_cmd(struct rm68200 *ctx, u8 cmd, u8 value) @@ -121,7 +119,7 @@ static void rm68200_dcs_write_cmd(struct rm68200 *ctx, u8 cmd, u8 value) err = mipi_dsi_dcs_write(dsi, cmd, &value, 1); if (err < 0) - DRM_ERROR_RATELIMITED("MIPI DSI DCS write failed: %d\n", err); + dev_err_ratelimited(ctx->dev, "MIPI DSI DCS write failed: %d\n", err); } #define dcs_write_seq(ctx, seq...) \ @@ -256,11 +254,11 @@ static int rm68200_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret) - DRM_WARN("failed to set display off: %d\n", ret); + dev_warn(panel->dev, "failed to set display off: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret) - DRM_WARN("failed to enter sleep mode: %d\n", ret); + dev_warn(panel->dev, "failed to enter sleep mode: %d\n", ret); msleep(120); @@ -287,7 +285,7 @@ static int rm68200_prepare(struct drm_panel *panel) ret = regulator_enable(ctx->supply); if (ret < 0) { - DRM_ERROR("failed to enable supply: %d\n", ret); + dev_err(ctx->dev, "failed to enable supply: %d\n", ret); return ret; } @@ -336,9 +334,9 @@ static int rm68200_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_ERROR("failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } -- GitLab From 65d5c86fc55f42392428a36fb0b32dc51b2c5848 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sat, 15 Aug 2020 14:54:05 +0200 Subject: [PATCH 0535/1494] drm/panel: sitronix: Use dev_ based logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on the dev_ based logging and drop the include of drm_print.h. Fix a few cases where "x@" was used when printing the mode. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Guido Günther <agx@sigxcpu.org> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Guido Günther <agx@sigxcpu.org> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200815125406.1153224-5-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-sitronix-st7701.c | 10 ++- drivers/gpu/drm/panel/panel-sitronix-st7703.c | 61 +++++++------------ 2 files changed, 27 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c index 12462114a52d8..4d2a149b202cb 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c @@ -7,7 +7,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <linux/gpio/consumer.h> #include <linux/delay.h> @@ -269,10 +268,9 @@ static int st7701_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, desc_mode); if (!mode) { - DRM_DEV_ERROR(&st7701->dsi->dev, - "failed to add mode %ux%ux@%u\n", - desc_mode->hdisplay, desc_mode->vdisplay, - drm_mode_vrefresh(desc_mode)); + dev_err(&st7701->dsi->dev, "failed to add mode %ux%u@%u\n", + desc_mode->hdisplay, desc_mode->vdisplay, + drm_mode_vrefresh(desc_mode)); return -ENOMEM; } @@ -358,7 +356,7 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) st7701->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(st7701->reset)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our reset GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); return PTR_ERR(st7701->reset); } diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7703.c b/drivers/gpu/drm/panel/panel-sitronix-st7703.c index 8996ced2b721a..c22e7c49e0778 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7703.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7703.c @@ -22,7 +22,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define DRV_NAME "panel-sitronix-st7703" @@ -364,8 +363,7 @@ static int st7703_enable(struct drm_panel *panel) ret = ctx->desc->init_sequence(ctx); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", - ret); + dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); return ret; } @@ -373,7 +371,7 @@ static int st7703_enable(struct drm_panel *panel) ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to exit sleep mode: %d\n", ret); + dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); return ret; } @@ -384,7 +382,7 @@ static int st7703_enable(struct drm_panel *panel) if (ret) return ret; - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Panel init sequence done\n"); + dev_dbg(ctx->dev, "Panel init sequence done\n"); return 0; } @@ -397,13 +395,11 @@ static int st7703_disable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, - "Failed to turn off the display: %d\n", ret); + dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, - "Failed to enter sleep mode: %d\n", ret); + dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret); return 0; } @@ -431,17 +427,15 @@ static int st7703_prepare(struct drm_panel *panel) if (ctx->prepared) return 0; - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); + dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable vcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret); return ret; } ret = regulator_enable(ctx->iovcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable iovcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); goto disable_vcc; } @@ -467,9 +461,9 @@ static int st7703_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, ctx->desc->mode); if (!mode) { - DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n", - ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, - drm_mode_vrefresh(ctx->desc->mode)); + dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", + ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, + drm_mode_vrefresh(ctx->desc->mode)); return -ENOMEM; } @@ -496,7 +490,7 @@ static int allpixelson_set(void *data, u64 val) struct st7703 *ctx = data; struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Setting all pixels on\n"); + dev_dbg(ctx->dev, "Setting all pixels on\n"); dsi_generic_write_seq(dsi, ST7703_CMD_ALL_PIXEL_ON); msleep(val * 1000); /* Reset the panel to get video back */ @@ -537,7 +531,7 @@ static int st7703_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); + dev_err(dev, "cannot get reset gpio\n"); return PTR_ERR(ctx->reset_gpio); } @@ -554,18 +548,14 @@ static int st7703_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vcc)) { ret = PTR_ERR(ctx->vcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request vcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request vcc regulator: %d\n", ret); return ret; } ctx->iovcc = devm_regulator_get(dev, "iovcc"); if (IS_ERR(ctx->iovcc)) { ret = PTR_ERR(ctx->iovcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request iovcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request iovcc regulator: %d\n", ret); return ret; } @@ -580,17 +570,15 @@ static int st7703_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, - "mipi_dsi_attach failed (%d). Is host ready?\n", - ret); + dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret); drm_panel_remove(&ctx->panel); return ret; } - DRM_DEV_INFO(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", - ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, - drm_mode_vrefresh(ctx->desc->mode), - mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); + dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n", + ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, + drm_mode_vrefresh(ctx->desc->mode), + mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes); st7703_debugfs_init(ctx); return 0; @@ -603,13 +591,11 @@ static void st7703_shutdown(struct mipi_dsi_device *dsi) ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); ret = drm_panel_disable(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } static int st7703_remove(struct mipi_dsi_device *dsi) @@ -621,8 +607,7 @@ static int st7703_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", - ret); + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); -- GitLab From a25b6b273f7039da72e41f78dc6e9d64b4592e68 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg <sam@ravnborg.org> Date: Sat, 15 Aug 2020 14:54:06 +0200 Subject: [PATCH 0536/1494] drm/panel: Use dev_ based logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on the dev_ based logging and drop the include of drm_print.h. Fix a few cases where "x@" was used when printing the mode. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Guido Günther <agx@sigxcpu.org> Cc: Jerry Han <hanxu5@huaqin.corp-partner.google.com> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Icenowy Zheng <icenowy@aosc.io> Cc: Jagan Teki <jagan@amarulasolutions.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Guido Günther <agx@sigxcpu.org> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200815125406.1153224-6-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-boe-himax8279d.c | 44 ++++------ drivers/gpu/drm/panel/panel-elida-kd35t133.c | 51 +++++------- .../gpu/drm/panel/panel-feixin-k101-im2ba02.c | 19 ++--- .../drm/panel/panel-feiyang-fy07024di26a30d.c | 21 +++-- drivers/gpu/drm/panel/panel-ilitek-ili9322.c | 3 +- drivers/gpu/drm/panel/panel-innolux-p079zca.c | 31 +++---- .../drm/panel/panel-kingdisplay-kd097d04.c | 33 +++----- drivers/gpu/drm/panel/panel-novatek-nt35510.c | 40 ++++----- .../gpu/drm/panel/panel-orisetech-otm8009a.c | 13 ++- drivers/gpu/drm/panel/panel-ronbo-rb070d30.c | 16 ++-- drivers/gpu/drm/panel/panel-sony-acx424akp.c | 81 +++++++------------ drivers/gpu/drm/panel/panel-tpo-tpg110.c | 38 ++++----- drivers/gpu/drm/panel/panel-truly-nt35597.c | 63 +++++---------- .../gpu/drm/panel/panel-visionox-rm69299.c | 41 +++------- .../gpu/drm/panel/panel-xinpeng-xpp055c272.c | 51 +++++------- 15 files changed, 200 insertions(+), 345 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index d676b4c2a8fa4..42854bd37fd5b 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -19,7 +19,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <video/mipi_display.h> @@ -93,8 +92,7 @@ static int boe_panel_disable(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - err); + dev_err(panel->dev, "failed to set display off: %d\n", err); return err; } @@ -113,13 +111,11 @@ static int boe_panel_unprepare(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_off(pinfo->link); if (err < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - err); + dev_err(panel->dev, "failed to set display off: %d\n", err); err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link); if (err < 0) - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); /* sleep_mode_delay: 1ms - 2ms */ usleep_range(1000, 2000); @@ -163,15 +159,13 @@ static int boe_panel_prepare(struct drm_panel *panel) /* send init code */ err = send_mipi_cmds(panel, pinfo->desc->on_cmds); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to send DCS Init Code: %d\n", - err); + dev_err(panel->dev, "failed to send DCS Init Code: %d\n", err); goto poweroff; } err = mipi_dsi_dcs_exit_sleep_mode(pinfo->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to exit sleep mode: %d\n", err); goto poweroff; } @@ -180,8 +174,7 @@ static int boe_panel_prepare(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_on(pinfo->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", - err); + dev_err(panel->dev, "failed to set display on: %d\n", err); goto poweroff; } @@ -209,8 +202,7 @@ static int boe_panel_enable(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(pinfo->link); if (ret < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", - ret); + dev_err(panel->dev, "failed to set display on: %d\n", ret); return ret; } @@ -228,8 +220,8 @@ static int boe_panel_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, m); if (!mode) { - DRM_DEV_ERROR(pinfo->base.dev, "failed to add mode %ux%u@%u\n", - m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); + dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n", + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); return -ENOMEM; } @@ -865,8 +857,7 @@ static int panel_add(struct panel_info *pinfo) if (IS_ERR(pinfo->pp18_gpio)) { ret = PTR_ERR(pinfo->pp18_gpio); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get pp18 gpio: %d\n", - ret); + dev_err(dev, "failed to get pp18 gpio: %d\n", ret); return ret; } @@ -874,8 +865,7 @@ static int panel_add(struct panel_info *pinfo) if (IS_ERR(pinfo->pp33_gpio)) { ret = PTR_ERR(pinfo->pp33_gpio); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get pp33 gpio: %d\n", - ret); + dev_err(dev, "failed to get pp33 gpio: %d\n", ret); return ret; } @@ -883,8 +873,7 @@ static int panel_add(struct panel_info *pinfo) if (IS_ERR(pinfo->enable_gpio)) { ret = PTR_ERR(pinfo->enable_gpio); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get enable gpio: %d\n", - ret); + dev_err(dev, "failed to get enable gpio: %d\n", ret); return ret; } @@ -937,18 +926,15 @@ static int panel_remove(struct mipi_dsi_device *dsi) err = boe_panel_disable(&pinfo->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", - err); + dev_err(&dsi->dev, "failed to disable panel: %d\n", err); err = boe_panel_unprepare(&pinfo->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n", - err); + dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); err = mipi_dsi_detach(dsi); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", - err); + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); drm_panel_remove(&pinfo->base); diff --git a/drivers/gpu/drm/panel/panel-elida-kd35t133.c b/drivers/gpu/drm/panel/panel-elida-kd35t133.c index e9675514d77b7..bc36aa3c11234 100644 --- a/drivers/gpu/drm/panel/panel-elida-kd35t133.c +++ b/drivers/gpu/drm/panel/panel-elida-kd35t133.c @@ -22,7 +22,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> /* Manufacturer specific Commands send via DSI */ #define KD35T133_CMD_INTERFACEMODECTRL 0xb0 @@ -89,7 +88,7 @@ static int kd35t133_init_sequence(struct kd35t133 *ctx) 0xa9, 0x51, 0x2c, 0x82); mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_INVERT_MODE, NULL, 0); - DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n"); + dev_dbg(dev, "Panel init sequence done\n"); return 0; } @@ -104,13 +103,11 @@ static int kd35t133_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, "failed to set display off: %d\n", - ret); + dev_err(ctx->dev, "failed to set display off: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret); return ret; } @@ -131,18 +128,16 @@ static int kd35t133_prepare(struct drm_panel *panel) if (ctx->prepared) return 0; - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); + dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vdd); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable vdd supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable vdd supply: %d\n", ret); return ret; } ret = regulator_enable(ctx->iovcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable iovcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); goto disable_vdd; } @@ -156,7 +151,7 @@ static int kd35t133_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to exit sleep mode: %d\n", ret); + dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); goto disable_iovcc; } @@ -164,14 +159,13 @@ static int kd35t133_prepare(struct drm_panel *panel) ret = kd35t133_init_sequence(ctx); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", - ret); + dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); goto disable_iovcc; } ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to set display on: %d\n", ret); + dev_err(ctx->dev, "Failed to set display on: %d\n", ret); goto disable_iovcc; } @@ -210,9 +204,9 @@ static int kd35t133_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -244,7 +238,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); + dev_err(dev, "cannot get reset gpio\n"); return PTR_ERR(ctx->reset_gpio); } @@ -252,9 +246,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vdd)) { ret = PTR_ERR(ctx->vdd); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request vdd regulator: %d\n", - ret); + dev_err(dev, "Failed to request vdd regulator: %d\n", ret); return ret; } @@ -262,9 +254,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->iovcc)) { ret = PTR_ERR(ctx->iovcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request iovcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request iovcc regulator: %d\n", ret); return ret; } @@ -288,7 +278,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret); + dev_err(dev, "mipi_dsi_attach failed: %d\n", ret); drm_panel_remove(&ctx->panel); return ret; } @@ -303,13 +293,11 @@ static void kd35t133_shutdown(struct mipi_dsi_device *dsi) ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); ret = drm_panel_disable(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } static int kd35t133_remove(struct mipi_dsi_device *dsi) @@ -321,8 +309,7 @@ static int kd35t133_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", - ret); + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); diff --git a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c index 0b7e82e5ba4e3..2a602aee61c30 100644 --- a/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c +++ b/drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c @@ -13,7 +13,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define K101_IM2BA02_INIT_CMD_LEN 2 @@ -374,13 +373,11 @@ static int k101_im2ba02_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(ctx->dsi); if (ret < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - ret); + dev_err(panel->dev, "failed to set display off: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi); if (ret < 0) - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", ret); msleep(200); @@ -416,10 +413,10 @@ static int k101_im2ba02_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &k101_im2ba02_default_mode); if (!mode) { - DRM_DEV_ERROR(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n", - k101_im2ba02_default_mode.hdisplay, - k101_im2ba02_default_mode.vdisplay, - drm_mode_vrefresh(&k101_im2ba02_default_mode)); + dev_err(&ctx->dsi->dev, "failed to add mode %ux%u@%u\n", + k101_im2ba02_default_mode.hdisplay, + k101_im2ba02_default_mode.vdisplay, + drm_mode_vrefresh(&k101_im2ba02_default_mode)); return -ENOMEM; } @@ -460,13 +457,13 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi) ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(ctx->supplies), ctx->supplies); if (ret < 0) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get regulators\n"); + dev_err(&dsi->dev, "Couldn't get regulators\n"); return ret; } ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our reset GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); return PTR_ERR(ctx->reset); } diff --git a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c index f9edee69fea40..581661b506f81 100644 --- a/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c +++ b/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c @@ -7,7 +7,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <linux/gpio/consumer.h> #include <linux/delay.h> @@ -118,13 +117,11 @@ static int feiyang_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(ctx->dsi); if (ret < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - ret); + dev_err(panel->dev, "failed to set display off: %d\n", ret); ret = mipi_dsi_dcs_enter_sleep_mode(ctx->dsi); if (ret < 0) - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", ret); /* T13 (backlight fall + video & logic signal fall) T13 >= 200ms */ msleep(200); @@ -165,10 +162,10 @@ static int feiyang_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &feiyang_default_mode); if (!mode) { - DRM_DEV_ERROR(&ctx->dsi->dev, "failed to add mode %ux%ux@%u\n", - feiyang_default_mode.hdisplay, - feiyang_default_mode.vdisplay, - drm_mode_vrefresh(&feiyang_default_mode)); + dev_err(&ctx->dsi->dev, "failed to add mode %ux%u@%u\n", + feiyang_default_mode.hdisplay, + feiyang_default_mode.vdisplay, + drm_mode_vrefresh(&feiyang_default_mode)); return -ENOMEM; } @@ -204,19 +201,19 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi) ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd"); if (IS_ERR(ctx->dvdd)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get dvdd regulator\n"); + dev_err(&dsi->dev, "Couldn't get dvdd regulator\n"); return PTR_ERR(ctx->dvdd); } ctx->avdd = devm_regulator_get(&dsi->dev, "avdd"); if (IS_ERR(ctx->avdd)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get avdd regulator\n"); + dev_err(&dsi->dev, "Couldn't get avdd regulator\n"); return PTR_ERR(ctx->avdd); } ctx->reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our reset GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); return PTR_ERR(ctx->reset); } diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 9688458947257..074e18559b9f6 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -33,7 +33,6 @@ #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define ILI9322_CHIP_ID 0x00 #define ILI9322_CHIP_ID_MAGIC 0x96 @@ -683,7 +682,7 @@ static int ili9322_get_modes(struct drm_panel *panel, break; } if (!mode) { - DRM_ERROR("bad mode or failed to add mode\n"); + dev_err(panel->dev, "bad mode or failed to add mode\n"); return -EINVAL; } drm_mode_set_name(mode); diff --git a/drivers/gpu/drm/panel/panel-innolux-p079zca.c b/drivers/gpu/drm/panel/panel-innolux-p079zca.c index 1a8e69c641253..aea3162253914 100644 --- a/drivers/gpu/drm/panel/panel-innolux-p079zca.c +++ b/drivers/gpu/drm/panel/panel-innolux-p079zca.c @@ -17,7 +17,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct panel_init_cmd { size_t len; @@ -85,13 +84,11 @@ static int innolux_panel_unprepare(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_off(innolux->link); if (err < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - err); + dev_err(panel->dev, "failed to set display off: %d\n", err); err = mipi_dsi_dcs_enter_sleep_mode(innolux->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); return err; } @@ -147,8 +144,7 @@ static int innolux_panel_prepare(struct drm_panel *panel) err = mipi_dsi_generic_write(innolux->link, cmd->data, cmd->len); if (err < 0) { - dev_err(panel->dev, - "failed to write command %u\n", i); + dev_err(panel->dev, "failed to write command %u\n", i); goto poweroff; } @@ -159,8 +155,7 @@ static int innolux_panel_prepare(struct drm_panel *panel) */ err = mipi_dsi_dcs_nop(innolux->link); if (err < 0) { - dev_err(panel->dev, - "failed to send DCS nop: %d\n", err); + dev_err(panel->dev, "failed to send DCS nop: %d\n", err); goto poweroff; } } @@ -168,8 +163,7 @@ static int innolux_panel_prepare(struct drm_panel *panel) err = mipi_dsi_dcs_exit_sleep_mode(innolux->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to exit sleep mode: %d\n", err); goto poweroff; } @@ -178,8 +172,7 @@ static int innolux_panel_prepare(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_on(innolux->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", - err); + dev_err(panel->dev, "failed to set display on: %d\n", err); goto poweroff; } @@ -398,8 +391,8 @@ static int innolux_panel_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, m); if (!mode) { - DRM_DEV_ERROR(panel->dev, "failed to add mode %ux%ux@%u\n", - m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); return -ENOMEM; } @@ -512,17 +505,15 @@ static int innolux_panel_remove(struct mipi_dsi_device *dsi) err = drm_panel_unprepare(&innolux->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n", - err); + dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); err = drm_panel_disable(&innolux->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err); + dev_err(&dsi->dev, "failed to disable panel: %d\n", err); err = mipi_dsi_detach(dsi); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", - err); + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); innolux_panel_del(innolux); diff --git a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c index f42dc2ceeb079..86e4213e8bb13 100644 --- a/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c +++ b/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c @@ -16,7 +16,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct kingdisplay_panel { struct drm_panel base; @@ -191,8 +190,7 @@ static int kingdisplay_panel_disable(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_off(kingdisplay->link); if (err < 0) - DRM_DEV_ERROR(panel->dev, "failed to set display off: %d\n", - err); + dev_err(panel->dev, "failed to set display off: %d\n", err); kingdisplay->enabled = false; @@ -209,8 +207,7 @@ static int kingdisplay_panel_unprepare(struct drm_panel *panel) err = mipi_dsi_dcs_enter_sleep_mode(kingdisplay->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to enter sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to enter sleep mode: %d\n", err); return err; } @@ -255,16 +252,14 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel) err = mipi_dsi_generic_write(kingdisplay->link, &init_code[i], sizeof(struct kingdisplay_panel_cmd)); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed write init cmds: %d\n", - err); + dev_err(panel->dev, "failed write init cmds: %d\n", err); goto poweroff; } } err = mipi_dsi_dcs_exit_sleep_mode(kingdisplay->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to exit sleep mode: %d\n", - err); + dev_err(panel->dev, "failed to exit sleep mode: %d\n", err); goto poweroff; } @@ -273,8 +268,7 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel) err = mipi_dsi_dcs_set_display_on(kingdisplay->link); if (err < 0) { - DRM_DEV_ERROR(panel->dev, "failed to set display on: %d\n", - err); + dev_err(panel->dev, "failed to set display on: %d\n", err); goto poweroff; } @@ -290,8 +284,7 @@ static int kingdisplay_panel_prepare(struct drm_panel *panel) regulator_err = regulator_disable(kingdisplay->supply); if (regulator_err) - DRM_DEV_ERROR(panel->dev, "failed to disable regulator: %d\n", - regulator_err); + dev_err(panel->dev, "failed to disable regulator: %d\n", regulator_err); return err; } @@ -327,9 +320,9 @@ static int kingdisplay_panel_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(panel->dev, "failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -423,17 +416,15 @@ static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi) err = drm_panel_unprepare(&kingdisplay->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to unprepare panel: %d\n", - err); + dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err); err = drm_panel_disable(&kingdisplay->base); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to disable panel: %d\n", err); + dev_err(&dsi->dev, "failed to disable panel: %d\n", err); err = mipi_dsi_detach(dsi); if (err < 0) - DRM_DEV_ERROR(&dsi->dev, "failed to detach from DSI host: %d\n", - err); + dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err); kingdisplay_panel_del(kingdisplay); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35510.c b/drivers/gpu/drm/panel/panel-novatek-nt35510.c index 64c8cf2bae7ca..b9a0e56f33e24 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt35510.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt35510.c @@ -35,7 +35,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define MCS_CMD_MAUCCTR 0xF0 /* Manufacturer command enable */ #define MCS_CMD_READ_ID1 0xDA @@ -404,9 +403,7 @@ static int nt35510_send_long(struct nt35510 *nt, struct mipi_dsi_device *dsi, chunk = 15; ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk); if (ret < 0) { - DRM_DEV_ERROR(nt->dev, - "error sending DCS command seq cmd %02x\n", - cmd); + dev_err(nt->dev, "error sending DCS command seq cmd %02x\n", cmd); return ret; } cmdwritten += chunk; @@ -418,16 +415,13 @@ static int nt35510_send_long(struct nt35510 *nt, struct mipi_dsi_device *dsi, chunk = 15; ret = mipi_dsi_generic_write(dsi, seqp, chunk); if (ret < 0) { - DRM_DEV_ERROR(nt->dev, - "error sending generic write seq %02x\n", - cmd); + dev_err(nt->dev, "error sending generic write seq %02x\n", cmd); return ret; } cmdwritten += chunk; seqp += chunk; } - DRM_DEV_DEBUG(nt->dev, "sent command %02x %02x bytes\n", - cmd, cmdlen); + dev_dbg(nt->dev, "sent command %02x %02x bytes\n", cmd, cmdlen); return 0; } @@ -439,17 +433,17 @@ static int nt35510_read_id(struct nt35510 *nt) ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID1, &id1, 1); if (ret < 0) { - DRM_DEV_ERROR(nt->dev, "could not read MTP ID1\n"); + dev_err(nt->dev, "could not read MTP ID1\n"); return ret; } ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID2, &id2, 1); if (ret < 0) { - DRM_DEV_ERROR(nt->dev, "could not read MTP ID2\n"); + dev_err(nt->dev, "could not read MTP ID2\n"); return ret; } ret = mipi_dsi_dcs_read(dsi, MCS_CMD_READ_ID3, &id3, 1); if (ret < 0) { - DRM_DEV_ERROR(nt->dev, "could not read MTP ID3\n"); + dev_err(nt->dev, "could not read MTP ID3\n"); return ret; } @@ -458,9 +452,7 @@ static int nt35510_read_id(struct nt35510 *nt) * ID (e.g. Hydis 0x55), driver ID (e.g. NT35510 0xc0) and * version. */ - DRM_DEV_INFO(nt->dev, - "MTP ID manufacturer: %02x version: %02x driver: %02x\n", - id1, id2, id3); + dev_info(nt->dev, "MTP ID manufacturer: %02x version: %02x driver: %02x\n", id1, id2, id3); return 0; } @@ -661,7 +653,7 @@ static int nt35510_set_brightness(struct backlight_device *bl) u8 brightness = bl->props.brightness; int ret; - DRM_DEV_DEBUG(nt->dev, "set brightness %d\n", brightness); + dev_dbg(nt->dev, "set brightness %d\n", brightness); ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, &brightness, sizeof(brightness)); @@ -796,8 +788,7 @@ static int nt35510_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret) { - DRM_DEV_ERROR(nt->dev, "failed to turn display off (%d)\n", - ret); + dev_err(nt->dev, "failed to turn display off (%d)\n", ret); return ret; } usleep_range(10000, 20000); @@ -805,8 +796,7 @@ static int nt35510_unprepare(struct drm_panel *panel) /* Enter sleep mode */ ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(nt->dev, "failed to enter sleep mode (%d)\n", - ret); + dev_err(nt->dev, "failed to enter sleep mode (%d)\n", ret); return ret; } @@ -833,8 +823,7 @@ static int nt35510_prepare(struct drm_panel *panel) /* Exit sleep mode */ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(nt->dev, "failed to exit sleep mode (%d)\n", - ret); + dev_err(nt->dev, "failed to exit sleep mode (%d)\n", ret); return ret; } /* Up to 120 ms */ @@ -842,8 +831,7 @@ static int nt35510_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret) { - DRM_DEV_ERROR(nt->dev, "failed to turn display on (%d)\n", - ret); + dev_err(nt->dev, "failed to turn display on (%d)\n", ret); return ret; } /* Some 10 ms */ @@ -864,7 +852,7 @@ static int nt35510_get_modes(struct drm_panel *panel, info->height_mm = nt->conf->height_mm; mode = drm_mode_duplicate(connector->dev, &nt->conf->mode); if (!mode) { - DRM_ERROR("bad mode or failed to add mode\n"); + dev_err(panel->dev, "bad mode or failed to add mode\n"); return -EINVAL; } drm_mode_set_name(mode); @@ -963,7 +951,7 @@ static int nt35510_probe(struct mipi_dsi_device *dsi) bl = devm_backlight_device_register(dev, "nt35510", dev, nt, &nt35510_bl_ops, NULL); if (IS_ERR(bl)) { - DRM_DEV_ERROR(dev, "failed to register backlight device\n"); + dev_err(dev, "failed to register backlight device\n"); return PTR_ERR(bl); } bl->props.max_brightness = 255; diff --git a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c index d956522f32ee0..b6e377aa1131b 100644 --- a/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c +++ b/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c @@ -17,7 +17,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define OTM8009A_BACKLIGHT_DEFAULT 240 #define OTM8009A_BACKLIGHT_MAX 255 @@ -97,7 +96,7 @@ static void otm8009a_dcs_write_buf(struct otm8009a *ctx, const void *data, struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); if (mipi_dsi_dcs_write_buffer(dsi, data, len) < 0) - DRM_WARN("mipi dsi dcs write buffer failed\n"); + dev_warn(ctx->dev, "mipi dsi dcs write buffer failed\n"); } static void otm8009a_dcs_write_buf_hs(struct otm8009a *ctx, const void *data, @@ -313,7 +312,7 @@ static int otm8009a_prepare(struct drm_panel *panel) ret = regulator_enable(ctx->supply); if (ret < 0) { - DRM_ERROR("failed to enable supply: %d\n", ret); + dev_err(panel->dev, "failed to enable supply: %d\n", ret); return ret; } @@ -355,9 +354,9 @@ static int otm8009a_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_ERROR("failed to add mode %ux%ux@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(panel->dev, "failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -390,7 +389,7 @@ static int otm8009a_backlight_update_status(struct backlight_device *bd) u8 data[2]; if (!ctx->prepared) { - DRM_DEBUG("lcd not ready yet for setting its backlight!\n"); + dev_dbg(&bd->dev, "lcd not ready yet for setting its backlight!\n"); return -ENXIO; } diff --git a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c index ea74958d7544d..535c8d1cca21c 100644 --- a/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c +++ b/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c @@ -23,7 +23,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct rb070d30_panel { struct drm_panel panel; @@ -50,7 +49,7 @@ static int rb070d30_panel_prepare(struct drm_panel *panel) ret = regulator_enable(ctx->supply); if (ret < 0) { - DRM_DEV_ERROR(&ctx->dsi->dev, "Failed to enable supply: %d\n", ret); + dev_err(&ctx->dsi->dev, "Failed to enable supply: %d\n", ret); return ret; } @@ -117,9 +116,8 @@ static int rb070d30_panel_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(&ctx->dsi->dev, - "Failed to add mode " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&default_mode)); + dev_err(&ctx->dsi->dev, "Failed to add mode " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&default_mode)); return -EINVAL; } @@ -166,13 +164,13 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) ctx->gpios.reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->gpios.reset)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our reset GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our reset GPIO\n"); return PTR_ERR(ctx->gpios.reset); } ctx->gpios.power = devm_gpiod_get(&dsi->dev, "power", GPIOD_OUT_LOW); if (IS_ERR(ctx->gpios.power)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our power GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our power GPIO\n"); return PTR_ERR(ctx->gpios.power); } @@ -182,7 +180,7 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) */ ctx->gpios.updn = devm_gpiod_get(&dsi->dev, "updn", GPIOD_OUT_LOW); if (IS_ERR(ctx->gpios.updn)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our updn GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our updn GPIO\n"); return PTR_ERR(ctx->gpios.updn); } @@ -192,7 +190,7 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi) */ ctx->gpios.shlr = devm_gpiod_get(&dsi->dev, "shlr", GPIOD_OUT_LOW); if (IS_ERR(ctx->gpios.shlr)) { - DRM_DEV_ERROR(&dsi->dev, "Couldn't get our shlr GPIO\n"); + dev_err(&dsi->dev, "Couldn't get our shlr GPIO\n"); return PTR_ERR(ctx->gpios.shlr); } diff --git a/drivers/gpu/drm/panel/panel-sony-acx424akp.c b/drivers/gpu/drm/panel/panel-sony-acx424akp.c index 57575c40f2aa6..065efae213f5b 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx424akp.c +++ b/drivers/gpu/drm/panel/panel-sony-acx424akp.c @@ -20,7 +20,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #define ACX424_DCS_READ_ID1 0xDA #define ACX424_DCS_READ_ID2 0xDB @@ -110,13 +109,11 @@ static int acx424akp_set_brightness(struct backlight_device *bl) SCALE_FACTOR_NS_DIV_MHZ); /* Set up PWM dutycycle ONE byte (differs from the standard) */ - DRM_DEV_DEBUG(acx->dev, "calculated duty cycle %02x\n", pwm_ratio); + dev_dbg(acx->dev, "calculated duty cycle %02x\n", pwm_ratio); ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, &pwm_ratio, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to set display PWM ratio (%d)\n", - ret); + dev_err(acx->dev, "failed to set display PWM ratio (%d)\n", ret); return ret; } @@ -132,40 +129,30 @@ static int acx424akp_set_brightness(struct backlight_device *bl) par = 0xaa; ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to unlock CMD 2 (%d)\n", - ret); + dev_err(acx->dev, "failed to unlock CMD 2 (%d)\n", ret); return ret; } par = 0x01; ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to enter page 1 (%d)\n", - ret); + dev_err(acx->dev, "failed to enter page 1 (%d)\n", ret); return ret; } par = 0x01; ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to disable MTP reload (%d)\n", - ret); + dev_err(acx->dev, "failed to disable MTP reload (%d)\n", ret); return ret; } ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to set PWM divisor (%d)\n", - ret); + dev_err(acx->dev, "failed to set PWM divisor (%d)\n", ret); return ret; } par = 0xaa; ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to lock CMD 2 (%d)\n", - ret); + dev_err(acx->dev, "failed to lock CMD 2 (%d)\n", ret); return ret; } @@ -174,9 +161,7 @@ static int acx424akp_set_brightness(struct backlight_device *bl) ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, &par, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, - "failed to enable display backlight (%d)\n", - ret); + dev_err(acx->dev, "failed to enable display backlight (%d)\n", ret); return ret; } @@ -196,22 +181,22 @@ static int acx424akp_read_id(struct acx424akp *acx) ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID1, &vendor, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, "could not vendor ID byte\n"); + dev_err(acx->dev, "could not vendor ID byte\n"); return ret; } ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID2, &version, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, "could not read device version byte\n"); + dev_err(acx->dev, "could not read device version byte\n"); return ret; } ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID3, &panel, 1); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, "could not read panel ID byte\n"); + dev_err(acx->dev, "could not read panel ID byte\n"); return ret; } if (vendor == 0x00) { - DRM_DEV_ERROR(acx->dev, "device vendor ID is zero\n"); + dev_err(acx->dev, "device vendor ID is zero\n"); return -ENODEV; } @@ -220,14 +205,12 @@ static int acx424akp_read_id(struct acx424akp *acx) case DISPLAY_SONY_ACX424AKP_ID1: case DISPLAY_SONY_ACX424AKP_ID2: case DISPLAY_SONY_ACX424AKP_ID3: - DRM_DEV_INFO(acx->dev, - "MTP vendor: %02x, version: %02x, panel: %02x\n", - vendor, version, panel); + dev_info(acx->dev, "MTP vendor: %02x, version: %02x, panel: %02x\n", + vendor, version, panel); break; default: - DRM_DEV_INFO(acx->dev, - "unknown vendor: %02x, version: %02x, panel: %02x\n", - vendor, version, panel); + dev_info(acx->dev, "unknown vendor: %02x, version: %02x, panel: %02x\n", + vendor, version, panel); break; } @@ -240,7 +223,7 @@ static int acx424akp_power_on(struct acx424akp *acx) ret = regulator_enable(acx->supply); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to enable supply (%d)\n", ret); + dev_err(acx->dev, "failed to enable supply (%d)\n", ret); return ret; } @@ -276,7 +259,7 @@ static int acx424akp_prepare(struct drm_panel *panel) ret = acx424akp_read_id(acx); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to read panel ID (%d)\n", ret); + dev_err(acx->dev, "failed to read panel ID (%d)\n", ret); goto err_power_off; } @@ -284,8 +267,7 @@ static int acx424akp_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to enable vblank TE (%d)\n", - ret); + dev_err(acx->dev, "failed to enable vblank TE (%d)\n", ret); goto err_power_off; } @@ -302,23 +284,21 @@ static int acx424akp_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_write(dsi, ACX424_DCS_SET_MDDI, &mddi, sizeof(mddi)); if (ret < 0) { - DRM_DEV_ERROR(acx->dev, "failed to set MDDI (%d)\n", ret); + dev_err(acx->dev, "failed to set MDDI (%d)\n", ret); goto err_power_off; } /* Exit sleep mode */ ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to exit sleep mode (%d)\n", - ret); + dev_err(acx->dev, "failed to exit sleep mode (%d)\n", ret); goto err_power_off; } msleep(140); ret = mipi_dsi_dcs_set_display_on(dsi); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to turn display on (%d)\n", - ret); + dev_err(acx->dev, "failed to turn display on (%d)\n", ret); goto err_power_off; } if (acx->video_mode) { @@ -351,24 +331,20 @@ static int acx424akp_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, &par, 1); if (ret) { - DRM_DEV_ERROR(acx->dev, - "failed to disable display backlight (%d)\n", - ret); + dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret); return ret; } ret = mipi_dsi_dcs_set_display_off(dsi); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to turn display off (%d)\n", - ret); + dev_err(acx->dev, "failed to turn display off (%d)\n", ret); return ret; } /* Enter sleep mode */ ret = mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret) { - DRM_DEV_ERROR(acx->dev, "failed to enter sleep mode (%d)\n", - ret); + dev_err(acx->dev, "failed to enter sleep mode (%d)\n", ret); return ret; } msleep(85); @@ -418,7 +394,7 @@ static int acx424akp_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &sony_acx424akp_cmd_mode); if (!mode) { - DRM_ERROR("bad mode or failed to add mode\n"); + dev_err(panel->dev, "bad mode or failed to add mode\n"); return -EINVAL; } drm_mode_set_name(mode); @@ -486,8 +462,7 @@ static int acx424akp_probe(struct mipi_dsi_device *dsi) if (IS_ERR(acx->reset_gpio)) { ret = PTR_ERR(acx->reset_gpio); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n", - ret); + dev_err(dev, "failed to request GPIO (%d)\n", ret); return ret; } @@ -497,7 +472,7 @@ static int acx424akp_probe(struct mipi_dsi_device *dsi) acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx, &acx424akp_bl_ops, NULL); if (IS_ERR(acx->bl)) { - DRM_DEV_ERROR(dev, "failed to register backlight device\n"); + dev_err(dev, "failed to register backlight device\n"); return PTR_ERR(acx->bl); } acx->bl->props.max_brightness = 1023; diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c index cd00cfa6ba149..d57ed75a977c3 100644 --- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c +++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c @@ -12,7 +12,6 @@ */ #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -238,7 +237,7 @@ static u8 tpg110_readwrite_reg(struct tpg110 *tpg, bool write, spi_message_add_tail(&t[1], &m); ret = spi_sync(tpg->spi, &m); if (ret) { - DRM_DEV_ERROR(tpg->dev, "SPI message error %d\n", ret); + dev_err(tpg->dev, "SPI message error %d\n", ret); return ret; } if (write) @@ -265,18 +264,18 @@ static int tpg110_startup(struct tpg110 *tpg) /* De-assert the reset signal */ gpiod_set_value_cansleep(tpg->grestb, 0); usleep_range(1000, 2000); - DRM_DEV_DEBUG(tpg->dev, "de-asserted GRESTB\n"); + dev_dbg(tpg->dev, "de-asserted GRESTB\n"); /* Test display communication */ tpg110_write_reg(tpg, TPG110_TEST, 0x55); val = tpg110_read_reg(tpg, TPG110_TEST); if (val != 0x55) { - DRM_DEV_ERROR(tpg->dev, "failed communication test\n"); + dev_err(tpg->dev, "failed communication test\n"); return -ENODEV; } val = tpg110_read_reg(tpg, TPG110_CHIPID); - DRM_DEV_INFO(tpg->dev, "TPG110 chip ID: %d version: %d\n", + dev_info(tpg->dev, "TPG110 chip ID: %d version: %d\n", val >> 4, val & 0x0f); /* Show display resolution */ @@ -284,27 +283,25 @@ static int tpg110_startup(struct tpg110 *tpg) val &= TPG110_RES_MASK; switch (val) { case TPG110_RES_400X240_D: - DRM_DEV_INFO(tpg->dev, - "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)\n"); + dev_info(tpg->dev, "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)\n"); break; case TPG110_RES_480X272_D: - DRM_DEV_INFO(tpg->dev, - "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)\n"); + dev_info(tpg->dev, "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)\n"); break; case TPG110_RES_480X640: - DRM_DEV_INFO(tpg->dev, "480x640 RGB\n"); + dev_info(tpg->dev, "480x640 RGB\n"); break; case TPG110_RES_480X272: - DRM_DEV_INFO(tpg->dev, "480x272 RGB\n"); + dev_info(tpg->dev, "480x272 RGB\n"); break; case TPG110_RES_640X480: - DRM_DEV_INFO(tpg->dev, "640x480 RGB\n"); + dev_info(tpg->dev, "640x480 RGB\n"); break; case TPG110_RES_800X480: - DRM_DEV_INFO(tpg->dev, "800x480 RGB\n"); + dev_info(tpg->dev, "800x480 RGB\n"); break; default: - DRM_DEV_ERROR(tpg->dev, "ILLEGAL RESOLUTION 0x%02x\n", val); + dev_err(tpg->dev, "ILLEGAL RESOLUTION 0x%02x\n", val); break; } @@ -322,13 +319,12 @@ static int tpg110_startup(struct tpg110 *tpg) } } if (i == ARRAY_SIZE(tpg110_modes)) { - DRM_DEV_ERROR(tpg->dev, "unsupported mode (%02x) detected\n", - val); + dev_err(tpg->dev, "unsupported mode (%02x) detected\n", val); return -ENODEV; } val = tpg110_read_reg(tpg, TPG110_CTRL2); - DRM_DEV_INFO(tpg->dev, "resolution and standby is controlled by %s\n", + dev_info(tpg->dev, "resolution and standby is controlled by %s\n", (val & TPG110_CTRL2_RES_PM_CTRL) ? "software" : "hardware"); /* Take control over resolution and standby */ val |= TPG110_CTRL2_RES_PM_CTRL; @@ -414,15 +410,15 @@ static int tpg110_probe(struct spi_device *spi) /* We get the physical display dimensions from the DT */ ret = of_property_read_u32(np, "width-mm", &tpg->width); if (ret) - DRM_DEV_ERROR(dev, "no panel width specified\n"); + dev_err(dev, "no panel width specified\n"); ret = of_property_read_u32(np, "height-mm", &tpg->height); if (ret) - DRM_DEV_ERROR(dev, "no panel height specified\n"); + dev_err(dev, "no panel height specified\n"); /* This asserts the GRESTB signal, putting the display into reset */ tpg->grestb = devm_gpiod_get(dev, "grestb", GPIOD_OUT_HIGH); if (IS_ERR(tpg->grestb)) { - DRM_DEV_ERROR(dev, "no GRESTB GPIO\n"); + dev_err(dev, "no GRESTB GPIO\n"); return -ENODEV; } @@ -430,7 +426,7 @@ static int tpg110_probe(struct spi_device *spi) spi->mode |= SPI_3WIRE_HIZ; ret = spi_setup(spi); if (ret < 0) { - DRM_DEV_ERROR(dev, "spi setup failed.\n"); + dev_err(dev, "spi setup failed.\n"); return ret; } tpg->spi = spi; diff --git a/drivers/gpu/drm/panel/panel-truly-nt35597.c b/drivers/gpu/drm/panel/panel-truly-nt35597.c index 9b9c167b8dc8f..b24b92d93ea56 100644 --- a/drivers/gpu/drm/panel/panel-truly-nt35597.c +++ b/drivers/gpu/drm/panel/panel-truly-nt35597.c @@ -17,7 +17,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> static const char * const regulator_names[] = { "vdda", @@ -231,9 +230,7 @@ static int truly_dcs_write(struct drm_panel *panel, u32 command) for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { ret = mipi_dsi_dcs_write(ctx->dsi[i], command, NULL, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "cmd 0x%x failed for dsi = %d\n", - command, i); + dev_err(ctx->dev, "cmd 0x%x failed for dsi = %d\n", command, i); } } @@ -250,8 +247,7 @@ static int truly_dcs_write_buf(struct drm_panel *panel, for (i = 0; i < ARRAY_SIZE(ctx->dsi); i++) { ret = mipi_dsi_dcs_write_buffer(ctx->dsi[i], buf, size); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "failed to tx cmd [%d], err: %d\n", i, ret); + dev_err(ctx->dev, "failed to tx cmd [%d], err: %d\n", i, ret); return ret; } } @@ -300,16 +296,14 @@ static int truly_nt35597_power_off(struct truly_nt35597 *ctx) ret = regulator_set_load(ctx->supplies[i].consumer, regulator_disable_loads[i]); if (ret) { - DRM_DEV_ERROR(ctx->dev, - "regulator_set_load failed %d\n", ret); + dev_err(ctx->dev, "regulator_set_load failed %d\n", ret); return ret; } } ret = regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); if (ret) { - DRM_DEV_ERROR(ctx->dev, - "regulator_bulk_disable failed %d\n", ret); + dev_err(ctx->dev, "regulator_bulk_disable failed %d\n", ret); } return ret; } @@ -325,8 +319,7 @@ static int truly_nt35597_disable(struct drm_panel *panel) if (ctx->backlight) { ret = backlight_disable(ctx->backlight); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, "backlight disable failed %d\n", - ret); + dev_err(ctx->dev, "backlight disable failed %d\n", ret); } ctx->enabled = false; @@ -346,9 +339,7 @@ static int truly_nt35597_unprepare(struct drm_panel *panel) ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_OFF); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "set_display_off cmd failed ret = %d\n", - ret); + dev_err(ctx->dev, "set_display_off cmd failed ret = %d\n", ret); } /* 120ms delay required here as per DCS spec */ @@ -356,13 +347,12 @@ static int truly_nt35597_unprepare(struct drm_panel *panel) ret = truly_dcs_write(panel, MIPI_DCS_ENTER_SLEEP_MODE); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "enter_sleep cmd failed ret = %d\n", ret); + dev_err(ctx->dev, "enter_sleep cmd failed ret = %d\n", ret); } ret = truly_nt35597_power_off(ctx); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, "power_off failed ret = %d\n", ret); + dev_err(ctx->dev, "power_off failed ret = %d\n", ret); ctx->prepared = false; return ret; @@ -396,18 +386,14 @@ static int truly_nt35597_prepare(struct drm_panel *panel) panel_on_cmds[i].size, panel_on_cmds[i].commands); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "cmd set tx failed i = %d ret = %d\n", - i, ret); + dev_err(ctx->dev, "cmd set tx failed i = %d ret = %d\n", i, ret); goto power_off; } } ret = truly_dcs_write(panel, MIPI_DCS_EXIT_SLEEP_MODE); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "exit_sleep_mode cmd failed ret = %d\n", - ret); + dev_err(ctx->dev, "exit_sleep_mode cmd failed ret = %d\n", ret); goto power_off; } @@ -416,8 +402,7 @@ static int truly_nt35597_prepare(struct drm_panel *panel) ret = truly_dcs_write(panel, MIPI_DCS_SET_DISPLAY_ON); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "set_display_on cmd failed ret = %d\n", ret); + dev_err(ctx->dev, "set_display_on cmd failed ret = %d\n", ret); goto power_off; } @@ -430,7 +415,7 @@ static int truly_nt35597_prepare(struct drm_panel *panel) power_off: if (truly_nt35597_power_off(ctx)) - DRM_DEV_ERROR(ctx->dev, "power_off failed\n"); + dev_err(ctx->dev, "power_off failed\n"); return ret; } @@ -445,8 +430,7 @@ static int truly_nt35597_enable(struct drm_panel *panel) if (ctx->backlight) { ret = backlight_enable(ctx->backlight); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, "backlight enable failed %d\n", - ret); + dev_err(ctx->dev, "backlight enable failed %d\n", ret); } ctx->enabled = true; @@ -464,8 +448,7 @@ static int truly_nt35597_get_modes(struct drm_panel *panel, config = ctx->config; mode = drm_mode_create(connector->dev); if (!mode) { - DRM_DEV_ERROR(ctx->dev, - "failed to create a new display mode\n"); + dev_err(ctx->dev, "failed to create a new display mode\n"); return 0; } @@ -501,15 +484,13 @@ static int truly_nt35597_panel_add(struct truly_nt35597 *ctx) ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n", - PTR_ERR(ctx->reset_gpio)); + dev_err(dev, "cannot get reset gpio %ld\n", PTR_ERR(ctx->reset_gpio)); return PTR_ERR(ctx->reset_gpio); } ctx->mode_gpio = devm_gpiod_get(dev, "mode", GPIOD_OUT_LOW); if (IS_ERR(ctx->mode_gpio)) { - DRM_DEV_ERROR(dev, "cannot get mode gpio %ld\n", - PTR_ERR(ctx->mode_gpio)); + dev_err(dev, "cannot get mode gpio %ld\n", PTR_ERR(ctx->mode_gpio)); return PTR_ERR(ctx->mode_gpio); } @@ -584,22 +565,21 @@ static int truly_nt35597_probe(struct mipi_dsi_device *dsi) dsi1 = of_graph_get_remote_node(dsi->dev.of_node, 1, -1); if (!dsi1) { - DRM_DEV_ERROR(dev, - "failed to get remote node for dsi1_device\n"); + dev_err(dev, "failed to get remote node for dsi1_device\n"); return -ENODEV; } dsi1_host = of_find_mipi_dsi_host_by_node(dsi1); of_node_put(dsi1); if (!dsi1_host) { - DRM_DEV_ERROR(dev, "failed to find dsi host\n"); + dev_err(dev, "failed to find dsi host\n"); return -EPROBE_DEFER; } /* register the second DSI device */ dsi1_device = mipi_dsi_device_register_full(dsi1_host, &info); if (IS_ERR(dsi1_device)) { - DRM_DEV_ERROR(dev, "failed to create dsi device\n"); + dev_err(dev, "failed to create dsi device\n"); return PTR_ERR(dsi1_device); } @@ -611,7 +591,7 @@ static int truly_nt35597_probe(struct mipi_dsi_device *dsi) ret = truly_nt35597_panel_add(ctx); if (ret) { - DRM_DEV_ERROR(dev, "failed to add panel\n"); + dev_err(dev, "failed to add panel\n"); goto err_panel_add; } @@ -623,8 +603,7 @@ static int truly_nt35597_probe(struct mipi_dsi_device *dsi) MIPI_DSI_CLOCK_NON_CONTINUOUS; ret = mipi_dsi_attach(dsi_dev); if (ret < 0) { - DRM_DEV_ERROR(dev, - "dsi attach failed i = %d\n", i); + dev_err(dev, "dsi attach failed i = %d\n", i); goto err_dsi_attach; } } diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c index a12976b497ce7..eb43503ec97b3 100644 --- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c +++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c @@ -14,7 +14,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> struct visionox_rm69299 { struct drm_panel panel; @@ -69,16 +68,14 @@ static int visionox_rm69299_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0); if (ret < 0) - DRM_DEV_ERROR(ctx->panel.dev, - "set_display_off cmd failed ret = %d\n", ret); + dev_err(ctx->panel.dev, "set_display_off cmd failed ret = %d\n", ret); /* 120ms delay required here as per DCS spec */ msleep(120); ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "enter_sleep cmd failed ret = %d\n", ret); + dev_err(ctx->panel.dev, "enter_sleep cmd failed ret = %d\n", ret); } ret = visionox_rm69299_power_off(ctx); @@ -103,36 +100,31 @@ static int visionox_rm69299_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xfe, 0x00 }, 2); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "cmd set tx 0 failed, ret = %d\n", ret); + dev_err(ctx->panel.dev, "cmd set tx 0 failed, ret = %d\n", ret); goto power_off; } ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0xc2, 0x08 }, 2); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "cmd set tx 1 failed, ret = %d\n", ret); + dev_err(ctx->panel.dev, "cmd set tx 1 failed, ret = %d\n", ret); goto power_off; } ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x35, 0x00 }, 2); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "cmd set tx 2 failed, ret = %d\n", ret); + dev_err(ctx->panel.dev, "cmd set tx 2 failed, ret = %d\n", ret); goto power_off; } ret = mipi_dsi_dcs_write_buffer(ctx->dsi, (u8[]) { 0x51, 0xff }, 2); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "cmd set tx 3 failed, ret = %d\n", ret); + dev_err(ctx->panel.dev, "cmd set tx 3 failed, ret = %d\n", ret); goto power_off; } ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "exit_sleep_mode cmd failed ret = %d\n", ret); + dev_err(ctx->panel.dev, "exit_sleep_mode cmd failed ret = %d\n", ret); goto power_off; } @@ -141,8 +133,7 @@ static int visionox_rm69299_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_write(ctx->dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); if (ret < 0) { - DRM_DEV_ERROR(ctx->panel.dev, - "set_display_on cmd failed ret = %d\n", ret); + dev_err(ctx->panel.dev, "set_display_on cmd failed ret = %d\n", ret); goto power_off; } @@ -179,8 +170,7 @@ static int visionox_rm69299_get_modes(struct drm_panel *panel, mode = drm_mode_create(connector->dev); if (!mode) { - DRM_DEV_ERROR(ctx->panel.dev, - "failed to create a new display mode\n"); + dev_err(ctx->panel.dev, "failed to create a new display mode\n"); return 0; } @@ -225,8 +215,7 @@ static int visionox_rm69299_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get(ctx->panel.dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio %ld\n", - PTR_ERR(ctx->reset_gpio)); + dev_err(dev, "cannot get reset gpio %ld\n", PTR_ERR(ctx->reset_gpio)); return PTR_ERR(ctx->reset_gpio); } @@ -242,23 +231,19 @@ static int visionox_rm69299_probe(struct mipi_dsi_device *dsi) MIPI_DSI_CLOCK_NON_CONTINUOUS; ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "dsi attach failed ret = %d\n", ret); + dev_err(dev, "dsi attach failed ret = %d\n", ret); goto err_dsi_attach; } ret = regulator_set_load(ctx->supplies[0].consumer, 32000); if (ret) { - DRM_DEV_ERROR(dev, - "regulator set load failed for vdda supply ret = %d\n", - ret); + dev_err(dev, "regulator set load failed for vdda supply ret = %d\n", ret); goto err_set_load; } ret = regulator_set_load(ctx->supplies[1].consumer, 13200); if (ret) { - DRM_DEV_ERROR(dev, - "regulator set load failed for vdd3p3 supply ret = %d\n", - ret); + dev_err(dev, "regulator set load failed for vdd3p3 supply ret = %d\n", ret); goto err_set_load; } diff --git a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c index 06341deb60ca7..55172d63a922e 100644 --- a/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c +++ b/drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c @@ -12,7 +12,6 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_modes.h> #include <drm/drm_panel.h> -#include <drm/drm_print.h> #include <video/display_timing.h> #include <video/mipi_display.h> @@ -135,7 +134,7 @@ static int xpp055c272_init_sequence(struct xpp055c272 *ctx) msleep(60); - DRM_DEV_DEBUG_DRIVER(dev, "Panel init sequence done\n"); + dev_dbg(dev, "Panel init sequence done\n"); return 0; } @@ -150,13 +149,11 @@ static int xpp055c272_unprepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_off(dsi); if (ret < 0) - DRM_DEV_ERROR(ctx->dev, "failed to set display off: %d\n", - ret); + dev_err(ctx->dev, "failed to set display off: %d\n", ret); mipi_dsi_dcs_enter_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "failed to enter sleep mode: %d\n", - ret); + dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret); return ret; } @@ -177,17 +174,15 @@ static int xpp055c272_prepare(struct drm_panel *panel) if (ctx->prepared) return 0; - DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); + dev_dbg(ctx->dev, "Resetting the panel\n"); ret = regulator_enable(ctx->vci); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable vci supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable vci supply: %d\n", ret); return ret; } ret = regulator_enable(ctx->iovcc); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, - "Failed to enable iovcc supply: %d\n", ret); + dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret); goto disable_vci; } @@ -201,14 +196,13 @@ static int xpp055c272_prepare(struct drm_panel *panel) ret = xpp055c272_init_sequence(ctx); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", - ret); + dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret); goto disable_iovcc; } ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to exit sleep mode: %d\n", ret); + dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret); goto disable_iovcc; } @@ -217,7 +211,7 @@ static int xpp055c272_prepare(struct drm_panel *panel) ret = mipi_dsi_dcs_set_display_on(dsi); if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Failed to set display on: %d\n", ret); + dev_err(ctx->dev, "Failed to set display on: %d\n", ret); goto disable_iovcc; } @@ -256,9 +250,9 @@ static int xpp055c272_get_modes(struct drm_panel *panel, mode = drm_mode_duplicate(connector->dev, &default_mode); if (!mode) { - DRM_DEV_ERROR(ctx->dev, "Failed to add mode %ux%u@%u\n", - default_mode.hdisplay, default_mode.vdisplay, - drm_mode_vrefresh(&default_mode)); + dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + drm_mode_vrefresh(&default_mode)); return -ENOMEM; } @@ -290,7 +284,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi) ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(ctx->reset_gpio)) { - DRM_DEV_ERROR(dev, "cannot get reset gpio\n"); + dev_err(dev, "cannot get reset gpio\n"); return PTR_ERR(ctx->reset_gpio); } @@ -298,9 +292,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->vci)) { ret = PTR_ERR(ctx->vci); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request vci regulator: %d\n", - ret); + dev_err(dev, "Failed to request vci regulator: %d\n", ret); return ret; } @@ -308,9 +300,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->iovcc)) { ret = PTR_ERR(ctx->iovcc); if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, - "Failed to request iovcc regulator: %d\n", - ret); + dev_err(dev, "Failed to request iovcc regulator: %d\n", ret); return ret; } @@ -334,7 +324,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "mipi_dsi_attach failed: %d\n", ret); + dev_err(dev, "mipi_dsi_attach failed: %d\n", ret); drm_panel_remove(&ctx->panel); return ret; } @@ -349,13 +339,11 @@ static void xpp055c272_shutdown(struct mipi_dsi_device *dsi) ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); ret = drm_panel_disable(&ctx->panel); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", - ret); + dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); } static int xpp055c272_remove(struct mipi_dsi_device *dsi) @@ -367,8 +355,7 @@ static int xpp055c272_remove(struct mipi_dsi_device *dsi) ret = mipi_dsi_detach(dsi); if (ret < 0) - DRM_DEV_ERROR(&dsi->dev, "Failed to detach from DSI host: %d\n", - ret); + dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret); drm_panel_remove(&ctx->panel); -- GitLab From 5960e02290357504b18f79fdda6de2f4d4812926 Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Mon, 17 Aug 2020 13:46:56 -0400 Subject: [PATCH 0537/1494] drm/amdkfd: Initialize SDMA activity counter to 0 To prevent reporting erroneous SDMA usage, initialize SDMA activity counter to 0 before using. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 40695d52e9a8d..ddd192e3197ce 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -270,6 +270,7 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, kfd_sdma_activity_worker); sdma_activity_work_handler.pdd = pdd; + sdma_activity_work_handler.sdma_activity_counter = 0; schedule_work(&sdma_activity_work_handler.sdma_activity_work); -- GitLab From c80e966b54096e50264af62a350c621708a4fcd2 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Mon, 17 Aug 2020 15:26:41 -0400 Subject: [PATCH 0538/1494] drm/amd/display: Add dsc_to_stream_resource for dcn3 Without this, enabling dsc will cause a nullptr Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 1ee9087eec761..957fc37b971ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2424,6 +2424,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = { .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, .set_mcif_arb_params = dcn30_set_mcif_arb_params, -- GitLab From e2d732fdb7a9e421720a644580cd6a9400f97f60 Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Tue, 11 Aug 2020 19:59:58 -0400 Subject: [PATCH 0539/1494] drm/scheduler: Scheduler priority fixes (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove DRM_SCHED_PRIORITY_LOW, as it was used in only one place. Rename and separate by a line DRM_SCHED_PRIORITY_MAX to DRM_SCHED_PRIORITY_COUNT as it represents a (total) count of said priorities and it is used as such in loops throughout the code. (0-based indexing is the the count number.) Remove redundant word HIGH in priority names, and rename *KERNEL* to *HIGH*, as it really means that, high. v2: Add back KERNEL and remove SW and HW, in lieu of a single HIGH between NORMAL and KERNEL. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/scheduler/sched_main.c | 4 ++-- include/drm/gpu_scheduler.h | 12 +++++++----- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 8842c55d4490b..fc695126b6e75 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -46,7 +46,7 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = { static int amdgpu_ctx_priority_permit(struct drm_file *filp, enum drm_sched_priority priority) { - if (priority < 0 || priority >= DRM_SCHED_PRIORITY_MAX) + if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT) return -EINVAL; /* NORMAL and below are accessible by everyone */ @@ -65,7 +65,7 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp, static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio) { switch (prio) { - case DRM_SCHED_PRIORITY_HIGH_HW: + case DRM_SCHED_PRIORITY_HIGH: case DRM_SCHED_PRIORITY_KERNEL: return AMDGPU_GFX_PIPE_PRIO_HIGH; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 937029ad5271a..dcfe8a3b03ffb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -251,7 +251,7 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched) int i; /* Signal all jobs not yet scheduled */ - for (i = DRM_SCHED_PRIORITY_MAX - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { struct drm_sched_rq *rq = &sched->sched_rq[i]; if (!rq) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 13ea8ebc421c6..6d4fc79bf84aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -267,7 +267,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, &ring->sched; } - for (i = 0; i < DRM_SCHED_PRIORITY_MAX; ++i) + for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_COUNT; ++i) atomic_set(&ring->num_jobs[i], 0); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index da871d84b7424..7112137689db0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -243,7 +243,7 @@ struct amdgpu_ring { bool has_compute_vm_bug; bool no_scheduler; - atomic_t num_jobs[DRM_SCHED_PRIORITY_MAX]; + atomic_t num_jobs[DRM_SCHED_PRIORITY_COUNT]; struct mutex priority_mutex; /* protected by priority_mutex */ int priority; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index c799691dfa848..17661ede94885 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -36,14 +36,14 @@ enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority) { switch (amdgpu_priority) { case AMDGPU_CTX_PRIORITY_VERY_HIGH: - return DRM_SCHED_PRIORITY_HIGH_HW; + return DRM_SCHED_PRIORITY_HIGH; case AMDGPU_CTX_PRIORITY_HIGH: - return DRM_SCHED_PRIORITY_HIGH_SW; + return DRM_SCHED_PRIORITY_HIGH; case AMDGPU_CTX_PRIORITY_NORMAL: return DRM_SCHED_PRIORITY_NORMAL; case AMDGPU_CTX_PRIORITY_LOW: case AMDGPU_CTX_PRIORITY_VERY_LOW: - return DRM_SCHED_PRIORITY_LOW; + return DRM_SCHED_PRIORITY_MIN; case AMDGPU_CTX_PRIORITY_UNSET: return DRM_SCHED_PRIORITY_UNSET; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 2d502e98fad0f..3d2712a4cf4d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2109,7 +2109,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) ring = adev->mman.buffer_funcs_ring; sched = &ring->sched; r = drm_sched_entity_init(&adev->mman.entity, - DRM_SCHED_PRIORITY_KERNEL, &sched, + DRM_SCHED_PRIORITY_KERNEL, &sched, 1, NULL); if (r) { DRM_ERROR("Failed setting up TTM BO move entity (%d)\n", diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 2f319102ae9f7..19f381e5e6618 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -623,7 +623,7 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched) return NULL; /* Kernel run queue has higher priority than normal run queue*/ - for (i = DRM_SCHED_PRIORITY_MAX - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { entity = drm_sched_rq_select_entity(&sched->sched_rq[i]); if (entity) break; @@ -851,7 +851,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, sched->name = name; sched->timeout = timeout; sched->hang_limit = hang_limit; - for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_MAX; i++) + for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_COUNT; i++) drm_sched_rq_init(sched, &sched->sched_rq[i]); init_waitqueue_head(&sched->wake_up_worker); diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index a21b3b92135a6..b30026ccd564b 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -33,14 +33,16 @@ struct drm_gpu_scheduler; struct drm_sched_rq; +/* These are often used as an (initial) index + * to an array, and as such should start at 0. + */ enum drm_sched_priority { DRM_SCHED_PRIORITY_MIN, - DRM_SCHED_PRIORITY_LOW = DRM_SCHED_PRIORITY_MIN, DRM_SCHED_PRIORITY_NORMAL, - DRM_SCHED_PRIORITY_HIGH_SW, - DRM_SCHED_PRIORITY_HIGH_HW, + DRM_SCHED_PRIORITY_HIGH, DRM_SCHED_PRIORITY_KERNEL, - DRM_SCHED_PRIORITY_MAX, + + DRM_SCHED_PRIORITY_COUNT, DRM_SCHED_PRIORITY_INVALID = -1, DRM_SCHED_PRIORITY_UNSET = -2 }; @@ -274,7 +276,7 @@ struct drm_gpu_scheduler { uint32_t hw_submission_limit; long timeout; const char *name; - struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_MAX]; + struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_COUNT]; wait_queue_head_t wake_up_worker; wait_queue_head_t job_scheduled; atomic_t hw_rq_count; -- GitLab From 9af5e21dace795891544042abda877ada39abacc Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Tue, 11 Aug 2020 20:56:58 -0400 Subject: [PATCH 0540/1494] drm/scheduler: Remove priority macro INVALID (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove DRM_SCHED_PRIORITY_INVALID. We no longer carry around an invalid priority and cut it off at the source. Backwards compatibility behaviour of AMDGPU CTX IOCTL passing in garbage for context priority from user space and then mapping that to DRM_SCHED_PRIORITY_NORMAL is preserved. v2: Revert "res" --> "r" and "prio" --> "priority". Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 5 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 40 +++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h | 3 +- include/drm/gpu_scheduler.h | 1 - 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index fc695126b6e75..ba243cc8f5850 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -388,13 +388,12 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_fpriv *fpriv = filp->driver_priv; - r = 0; id = args->in.ctx_id; - priority = amdgpu_to_sched_priority(args->in.priority); + r = amdgpu_to_sched_priority(args->in.priority, &priority); /* For backwards compatibility reasons, we need to accept * ioctls with garbage in the priority field */ - if (priority == DRM_SCHED_PRIORITY_INVALID) + if (r == -EINVAL) priority = DRM_SCHED_PRIORITY_NORMAL; switch (args->in.op) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index 17661ede94885..9581283a4c785 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -32,24 +32,32 @@ #include "amdgpu_vm.h" -enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority) +int amdgpu_to_sched_priority(int amdgpu_priority, + enum drm_sched_priority *prio) { switch (amdgpu_priority) { case AMDGPU_CTX_PRIORITY_VERY_HIGH: - return DRM_SCHED_PRIORITY_HIGH; + *prio = DRM_SCHED_PRIORITY_HIGH; + break; case AMDGPU_CTX_PRIORITY_HIGH: - return DRM_SCHED_PRIORITY_HIGH; + *prio = DRM_SCHED_PRIORITY_HIGH; + break; case AMDGPU_CTX_PRIORITY_NORMAL: - return DRM_SCHED_PRIORITY_NORMAL; + *prio = DRM_SCHED_PRIORITY_NORMAL; + break; case AMDGPU_CTX_PRIORITY_LOW: case AMDGPU_CTX_PRIORITY_VERY_LOW: - return DRM_SCHED_PRIORITY_MIN; + *prio = DRM_SCHED_PRIORITY_MIN; + break; case AMDGPU_CTX_PRIORITY_UNSET: - return DRM_SCHED_PRIORITY_UNSET; + *prio = DRM_SCHED_PRIORITY_UNSET; + break; default: WARN(1, "Invalid context priority %d\n", amdgpu_priority); - return DRM_SCHED_PRIORITY_INVALID; + return -EINVAL; } + + return 0; } static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev, @@ -119,9 +127,20 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, enum drm_sched_priority priority; int r; - priority = amdgpu_to_sched_priority(args->in.priority); - if (priority == DRM_SCHED_PRIORITY_INVALID) + /* First check the op, then the op's argument. + */ + switch (args->in.op) { + case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: + case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE: + break; + default: + DRM_ERROR("Invalid sched op specified: %d\n", args->in.op); return -EINVAL; + } + + r = amdgpu_to_sched_priority(args->in.priority, &priority); + if (r) + return r; switch (args->in.op) { case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: @@ -136,7 +155,8 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, priority); break; default: - DRM_ERROR("Invalid sched op specified: %d\n", args->in.op); + /* Impossible. + */ r = -EINVAL; break; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h index 12299fd95691c..67e5b2472f6a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h @@ -30,7 +30,8 @@ enum drm_sched_priority; struct drm_device; struct drm_file; -enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority); +int amdgpu_to_sched_priority(int amdgpu_priority, + enum drm_sched_priority *prio); int amdgpu_sched_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index b30026ccd564b..a33590e621086 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -43,7 +43,6 @@ enum drm_sched_priority { DRM_SCHED_PRIORITY_KERNEL, DRM_SCHED_PRIORITY_COUNT, - DRM_SCHED_PRIORITY_INVALID = -1, DRM_SCHED_PRIORITY_UNSET = -2 }; -- GitLab From 332d790365dbf33a5babc2f31a33957f7633361b Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Mon, 17 Aug 2020 22:38:38 +0800 Subject: [PATCH 0541/1494] Revert "drm/amdgpu: disable gfxoff for navy_flounder" This reverts commit ba4e049e63b607ac2e0c070b1406826390d5047e. Newly released sdma fw (51.52) provides a fix for the issue. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index e87d43537013a..e527be22a3d54 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3610,9 +3610,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; - case CHIP_NAVY_FLOUNDER: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - break; default: break; } -- GitLab From b109f61e7fe13109a2355f8cf087da0a448ee5de Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Tue, 18 Aug 2020 10:54:06 +0800 Subject: [PATCH 0542/1494] drm/amd/pm: update driver if version for navy_flounder It's in accordance with pmfw 65.7.0 for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 65363d56e3ccd..77d0996f4ec2a 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -31,7 +31,7 @@ #define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 -#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x4 /* MP Apertures */ #define MP0_Public 0x03800000 -- GitLab From 588a4d5c6a9275ad3d2b74780c93c6e5a41fdf41 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 17 Aug 2020 14:52:06 +0800 Subject: [PATCH 0543/1494] drm/amd/pm: disable/enable gfx ulv on UMD pstate enter/exit Add gfx ulv disablement/enablement on UMD pstate entering/exiting. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index bbe4a343e9f1e..7cc707ec21c33 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -596,6 +596,7 @@ struct pptable_funcs { int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); int (*enable_mgpu_fan_boost)(struct smu_context *smu); + int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7d17c4f1b4893..221b5c923ce15 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1440,6 +1440,7 @@ static int smu_enable_umd_pstate(void *handle, amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_UNGATE); + smu_gfx_ulv_control(smu, false); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1447,6 +1448,7 @@ static int smu_enable_umd_pstate(void *handle, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; smu_dpm_ctx->enable_umd_pstate = false; + smu_gfx_ulv_control(smu, true); amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 264073d4e2635..2fe29c6a00ceb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -92,6 +92,7 @@ #define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) +#define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) #endif #endif -- GitLab From e988026fcf2694893c5f81aa0aa241c3c7891063 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 17 Aug 2020 15:08:16 +0800 Subject: [PATCH 0544/1494] drm/amd/pm: add SMU11 common gfx ulv control interface Considering the same logic can be applied to Arcturus, Navi1X and Sienna Cichlid. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 + .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 11 +++++++++++ 5 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 77d0996f4ec2a..c4743f8d0d230 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -274,5 +274,8 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); +int smu_v11_0_gfx_ulv_control(struct smu_context *smu, + bool enablement); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 81f43fea4d528..aab83b9572464 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2391,6 +2391,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = arcturus_get_gpu_metrics, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 4b4d461899df4..c968f05533d9c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2660,6 +2660,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = navi10_get_gpu_metrics, .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 407a11c2826b2..45b9defebd07a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2796,6 +2796,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index ff574ebc179ee..3c98060e04b8b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1985,3 +1985,14 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); } + +int smu_v11_0_gfx_ulv_control(struct smu_context *smu, + bool enablement) +{ + int ret = 0; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_GFX_ULV_BIT)) + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_GFX_ULV_BIT, enablement); + + return ret; +} -- GitLab From f0d51d20d918b116571a243ef8c102b914fd5ad8 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 17 Aug 2020 15:52:42 +0800 Subject: [PATCH 0545/1494] drm/amd/pm: disable/enable deep sleep features on UMD pstate enter/exit Add deep sleep disablement/enablement on UMD pstate entering/exiting. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 7cc707ec21c33..4c5c041af4ee5 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -597,6 +597,7 @@ struct pptable_funcs { ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); int (*enable_mgpu_fan_boost)(struct smu_context *smu); int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); + int (*deep_sleep_control)(struct smu_context *smu, bool enablement); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 221b5c923ce15..8eb5b92903cd0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1441,6 +1441,7 @@ static int smu_enable_umd_pstate(void *handle, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_UNGATE); smu_gfx_ulv_control(smu, false); + smu_deep_sleep_control(smu, false); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1448,6 +1449,7 @@ static int smu_enable_umd_pstate(void *handle, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; smu_dpm_ctx->enable_umd_pstate = false; + smu_deep_sleep_control(smu, true); smu_gfx_ulv_control(smu, true); amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 2fe29c6a00ceb..c88f8fab1bae9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -93,6 +93,7 @@ #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) +#define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement) #endif #endif -- GitLab From 5ce99853a6fd94c729d4b50188f43300d6568898 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 17 Aug 2020 16:05:10 +0800 Subject: [PATCH 0546/1494] drm/amd/pm: add SMU11 common deep sleep control interface Considering the same logic can be applied to Arcturus, Navi1X and Sienna Cichlid. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 ++ .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 + .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 + .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 33 +++++++++++++++++++ 5 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index c4743f8d0d230..2a3f1ee4a50b0 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -277,5 +277,8 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); int smu_v11_0_gfx_ulv_control(struct smu_context *smu, bool enablement); +int smu_v11_0_deep_sleep_control(struct smu_context *smu, + bool enablement); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index aab83b9572464..8347b1f2509fb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2392,6 +2392,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = arcturus_get_gpu_metrics, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index c968f05533d9c..72f3d68691d8d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2661,6 +2661,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_gpu_metrics = navi10_get_gpu_metrics, .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 45b9defebd07a..8ffa8b71b75fe 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2797,6 +2797,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 3c98060e04b8b..ec20e839f555c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1996,3 +1996,36 @@ int smu_v11_0_gfx_ulv_control(struct smu_context *smu, return ret; } + +int smu_v11_0_deep_sleep_control(struct smu_context *smu, + bool enablement) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_GFXCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_GFXCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s GFXCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s SOCCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_LCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_LCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s LCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + return ret; +} -- GitLab From 9a1cddd6374fb1eb166f40f10d5411e3699066d4 Mon Sep 17 00:00:00 2001 From: jqdeng <Emily.Deng@amd.com> Date: Fri, 7 Aug 2020 17:31:19 +0800 Subject: [PATCH 0547/1494] drm/amdgpu: Fix repeatly flr issue Only for no job running test case need to do recover in flr notification. For having job in mirror list, then let guest driver to hit job timeout, and then do recover. Signed-off-by: jqdeng <Emily.Deng@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 2 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 3 ++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 08f80ca3b296c..54666eea18639 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1133,6 +1133,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); /* Common functions */ +bool amdgpu_device_has_job_running(struct amdgpu_device *adev); bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); int amdgpu_device_gpu_recover(struct amdgpu_device *adev, struct amdgpu_job* job); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 415e1a32b98c2..6573e11124624 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3922,6 +3922,34 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, return r; } +/** + * amdgpu_device_has_job_running - check if there is any job in mirror list + * + * @adev: amdgpu device pointer + * + * check if there is any job in mirror list + */ +bool amdgpu_device_has_job_running(struct amdgpu_device *adev) +{ + int i; + struct drm_sched_job *job; + + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->sched.thread) + continue; + + spin_lock(&ring->sched.job_list_lock); + job = list_first_entry_or_null(&ring->sched.ring_mirror_list, + struct drm_sched_job, node); + spin_unlock(&ring->sched.job_list_lock); + if (job) + return true; + } + return false; +} + /** * amdgpu_device_should_recover_gpu - check if we should try GPU recovery * diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 5fd67e1cc2a04..475ff5df8c873 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -268,7 +268,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT) + && (amdgpu_device_has_job_running(adev) || adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT)) amdgpu_device_gpu_recover(adev, NULL); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index ce2bf1fb79ed1..9cf695c05db39 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -289,7 +289,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && (adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || + && (amdgpu_device_has_job_running(adev) || + adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || adev->gfx_timeout == MAX_SCHEDULE_TIMEOUT || adev->compute_timeout == MAX_SCHEDULE_TIMEOUT || adev->video_timeout == MAX_SCHEDULE_TIMEOUT)) -- GitLab From 8e1d88f948f33f2e34dbf13c3e9fc4228f1331af Mon Sep 17 00:00:00 2001 From: jqdeng <Emily.Deng@amd.com> Date: Thu, 30 Jul 2020 14:48:40 +0800 Subject: [PATCH 0548/1494] drm/amdgpu: Limit the error info print rate Use function printk_ratelimit to limit the print rate. Signed-off-by: jqdeng <Emily.Deng@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 10c0779aba731..e84a6e0bc7844 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1305,7 +1305,8 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) r = amdgpu_cs_parser_init(&parser, data); if (r) { - DRM_ERROR("Failed to initialize parser %d!\n", r); + if (printk_ratelimit()) + DRM_ERROR("Failed to initialize parser %d!\n", r); goto out; } -- GitLab From cdab4211f66ec961a481e3b9d088e253b358cd1e Mon Sep 17 00:00:00 2001 From: Leo Liu <leo.liu@amd.com> Date: Fri, 14 Aug 2020 11:08:59 -0400 Subject: [PATCH 0549/1494] drm/amdgpu/jpeg: remove redundant check when it returns Fix warning from kernel test robot v2: remove the local variable as well Signed-off-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index c41e5590a7019..3a0dff53654df 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -460,15 +460,10 @@ static bool jpeg_v3_0_is_idle(void *handle) static int jpeg_v3_0_wait_for_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - int ret; - ret = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, + return SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, UVD_JRBC_STATUS__RB_JOB_DONE_MASK, UVD_JRBC_STATUS__RB_JOB_DONE_MASK); - if (ret) - return ret; - - return ret; } static int jpeg_v3_0_set_clockgating_state(void *handle, -- GitLab From d0eb1b5ceb2049dee32c469e4242ee7400504b48 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 17 Aug 2020 15:04:44 -0400 Subject: [PATCH 0550/1494] drm/amdgpu/pm: remove duplicate check FAMILY_KV is APUs and we already check for APUs. Reviewed-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 5fc6a9a13096f..f2e70655e8d9a 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3311,8 +3311,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, } if (((adev->flags & AMD_IS_APU) || - adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ - adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ + adev->family == AMDGPU_FAMILY_SI) && /* not implemented yet */ (attr == &sensor_dev_attr_power1_average.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| -- GitLab From 61426114f246219e065b553d0d613f3b081a2683 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 17 Aug 2020 15:37:54 -0400 Subject: [PATCH 0551/1494] drm/amdgpu/swsmu: implement voltage metrics for RENOIR Grab the data from the SMU metrics table. Reviewed-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 186929c31e9e9..ac81f2f605a23 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -616,6 +616,27 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, return 0; } +static int renoir_get_vddc(struct smu_context *smu, uint32_t *value, + unsigned int index) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (index >= 2) + return -EINVAL; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + *value = metrics.Voltage[index]; + + return 0; +} + /** * This interface get dpm clock table for dc */ @@ -952,6 +973,14 @@ static int renoir_read_sensor(struct smu_context *smu, *(uint32_t *)data *= 100; *size = 4; break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = renoir_get_vddc(smu, (uint32_t *)data, 0); + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDNB: + ret = renoir_get_vddc(smu, (uint32_t *)data, 1); + *size = 4; + break; default: ret = -EOPNOTSUPP; break; -- GitLab From b49dc928f5a61d6a6dc8b73644bacfaf21b4ae64 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 17 Aug 2020 15:47:31 -0400 Subject: [PATCH 0552/1494] drm/amdgpu/swsmu: implement power metrics for RENOIR Grab the data from the SMU metrics table. Reviewed-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index ac81f2f605a23..3b9ac72c7571d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -637,6 +637,23 @@ static int renoir_get_vddc(struct smu_context *smu, uint32_t *value, return 0; } +static int renoir_get_power(struct smu_context *smu, uint32_t *value) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + *value = metrics.CurrentSocketPower << 8; + + return 0; +} + /** * This interface get dpm clock table for dc */ @@ -981,6 +998,10 @@ static int renoir_read_sensor(struct smu_context *smu, ret = renoir_get_vddc(smu, (uint32_t *)data, 1); *size = 4; break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = renoir_get_power(smu, (uint32_t *)data); + *size = 4; + break; default: ret = -EOPNOTSUPP; break; -- GitLab From 367deb673c2f07e2071b0cfee31a366f6f353f96 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 17 Aug 2020 15:18:01 -0400 Subject: [PATCH 0553/1494] drm/amdgpu/pm: only hide average power on SI and pre-RENOIR APUs We can get this on RENOIR and newer via the SMU metrics table. Reviewed-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index f2e70655e8d9a..a77f7347fdfc4 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3312,12 +3312,17 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, if (((adev->flags & AMD_IS_APU) || adev->family == AMDGPU_FAMILY_SI) && /* not implemented yet */ - (attr == &sensor_dev_attr_power1_average.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || + (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) return 0; + if (((adev->family == AMDGPU_FAMILY_SI) || + ((adev->flags & AMD_IS_APU) && + (adev->asic_type < CHIP_RENOIR))) && /* not implemented yet */ + (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) + return 0; + if (!is_support_sw_smu(adev)) { /* hide max/min values if we can't both query and manage the fan */ if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && -- GitLab From 1d5503331b12a76266049289747dfd94f1643fde Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Tue, 18 Aug 2020 13:09:14 +0100 Subject: [PATCH 0554/1494] drm/amd/display: fix potential integer overflow when shifting 32 bit variable bl_pwm The 32 bit unsigned integer bl_pwm is being shifted using 32 bit arithmetic and then being assigned to a 64 bit unsigned integer. There is a potential for a 32 bit overflow so cast bl_pwm to enforce a 64 bit shift operation to avoid this. Addresses-Coverity: ("unintentional integer overflow") Fixes: 3ba01817365c ("drm/amd/display: Move panel_cntl specific register from abm to panel_cntl.") Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index a6d73d30837ca..df7f826eebd86 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -76,7 +76,7 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_c else bl_pwm &= 0xFFFF; - current_backlight = bl_pwm << (1 + bl_int_count); + current_backlight = (uint64_t)bl_pwm << (1 + bl_int_count); if (bl_period == 0) bl_period = 0xFFFF; -- GitLab From 16697cf39ed8c5948b44f786bf9bf749dc67692e Mon Sep 17 00:00:00 2001 From: Tong Zhang <ztong0001@gmail.com> Date: Sun, 16 Aug 2020 03:32:12 -0400 Subject: [PATCH 0555/1494] drm/amd/display: should check error using DC_OK core_link_read_dpcd returns only DC_OK(1) and DC_ERROR_UNEXPECTED(-1), the caller should check error using DC_OK instead of checking against 0 Signed-off-by: Tong Zhang <ztong0001@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 2319299325160..d1d95d3e248a7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4413,9 +4413,9 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link, link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, dpcd_backlight_get.raw, - sizeof(union dpcd_source_backlight_get))) + sizeof(union dpcd_source_backlight_get)) != DC_OK) return false; *backlight_millinits_avg = @@ -4454,9 +4454,9 @@ bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_milli link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, (uint8_t *) backlight_millinits, - sizeof(uint32_t))) + sizeof(uint32_t)) != DC_OK) return false; return true; -- GitLab From 37d0474542850e6bb70b226487b4202d21bfe7cc Mon Sep 17 00:00:00 2001 From: Alexander Monakov <amonakov@ispras.ru> Date: Tue, 4 Aug 2020 23:13:13 +0300 Subject: [PATCH 0556/1494] drm/amd/display: use correct scale for actual_brightness Documentation for sysfs backlight level interface requires that values in both 'brightness' and 'actual_brightness' files are interpreted to be in range from 0 to the value given in the 'max_brightness' file. With amdgpu, max_brightness gives 255, and values written by the user into 'brightness' are internally rescaled to a wider range. However, reading from 'actual_brightness' gives the raw register value without inverse rescaling. This causes issues for various userspace tools such as PowerTop and systemd that expect the value to be in the correct range. Introduce a helper to retrieve internal backlight range. Use it to reimplement 'convert_brightness' as 'convert_brightness_from_user' and introduce 'convert_brightness_to_user'. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=203905 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1242 Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alexander Monakov <amonakov@ispras.ru> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 81 +++++++++---------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ad6b95d65f7b0..0a1e53fda08aa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2965,51 +2965,50 @@ static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness) return rc ? 0 : 1; } -static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps, - const uint32_t user_brightness) +static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps, + unsigned *min, unsigned *max) { - u32 min, max, conversion_pace; - u32 brightness = user_brightness; - if (!caps) - goto out; + return 0; - if (!caps->aux_support) { - max = caps->max_input_signal; - min = caps->min_input_signal; - /* - * The brightness input is in the range 0-255 - * It needs to be rescaled to be between the - * requested min and max input signal - * It also needs to be scaled up by 0x101 to - * match the DC interface which has a range of - * 0 to 0xffff - */ - conversion_pace = 0x101; - brightness = - user_brightness - * conversion_pace - * (max - min) - / AMDGPU_MAX_BL_LEVEL - + min * conversion_pace; + if (caps->aux_support) { + // Firmware limits are in nits, DC API wants millinits. + *max = 1000 * caps->aux_max_input_signal; + *min = 1000 * caps->aux_min_input_signal; } else { - /* TODO - * We are doing a linear interpolation here, which is OK but - * does not provide the optimal result. We probably want - * something close to the Perceptual Quantizer (PQ) curve. - */ - max = caps->aux_max_input_signal; - min = caps->aux_min_input_signal; - - brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min - + user_brightness * max; - // Multiple the value by 1000 since we use millinits - brightness *= 1000; - brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL); + // Firmware limits are 8-bit, PWM control is 16-bit. + *max = 0x101 * caps->max_input_signal; + *min = 0x101 * caps->min_input_signal; } + return 1; +} + +static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; -out: - return brightness; + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + // Rescale 0..255 to min..max + return min + DIV_ROUND_CLOSEST((max - min) * brightness, + AMDGPU_MAX_BL_LEVEL); +} + +static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; + + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + if (brightness < min) + return 0; + // Rescale min..max to 0..255 + return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), + max - min); } static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) @@ -3025,7 +3024,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) link = (struct dc_link *)dm->backlight_link; - brightness = convert_brightness(&caps, bd->props.brightness); + brightness = convert_brightness_from_user(&caps, bd->props.brightness); // Change brightness based on AUX property if (caps.aux_support) return set_backlight_via_aux(link, brightness); @@ -3042,7 +3041,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) if (ret == DC_ERROR_UNEXPECTED) return bd->props.brightness; - return ret; + return convert_brightness_to_user(&dm->backlight_caps, ret); } static const struct backlight_ops amdgpu_dm_backlight_ops = { -- GitLab From 9fe2f897499f129f9f0ef4c51a11512dcf2ab7d0 Mon Sep 17 00:00:00 2001 From: David Stevens <stevensd@chromium.org> Date: Wed, 19 Aug 2020 12:10:11 +0900 Subject: [PATCH 0557/1494] virtio: fix build for configs without dma-bufs Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: David Stevens <stevensd@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200819031011.310180-1-stevensd@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/Kconfig | 1 + drivers/virtio/Kconfig | 7 +++++++ drivers/virtio/Makefile | 3 ++- drivers/virtio/virtio_dma_buf.c | 3 +++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig index eff3047052d48..67624423013a1 100644 --- a/drivers/gpu/drm/virtio/Kconfig +++ b/drivers/gpu/drm/virtio/Kconfig @@ -4,6 +4,7 @@ config DRM_VIRTIO_GPU depends on DRM && VIRTIO && MMU select DRM_KMS_HELPER select DRM_GEM_SHMEM_HELPER + select VIRTIO_DMA_SHARED_BUFFER help This is the virtual GPU driver for virtio. It can be used with QEMU based VMMs (like KVM or Xen). diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 5c92e4a50882d..e76e9b9ba93ca 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -126,4 +126,11 @@ config VIRTIO_MMIO_CMDLINE_DEVICES If unsure, say 'N'. +config VIRTIO_DMA_SHARED_BUFFER + tristate + depends on DMA_SHARED_BUFFER + help + This option adds a flavor of dma buffers that are backed by + virtio resources. + endif # VIRTIO_MENU diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index 49da768ee7fde..591e6f72aa542 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o virtio_dma_buf.o +obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o @@ -8,3 +8,4 @@ obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o obj-$(CONFIG_VIRTIO_VDPA) += virtio_vdpa.o obj-$(CONFIG_VIRTIO_MEM) += virtio_mem.o +obj-$(CONFIG_VIRTIO_DMA_SHARED_BUFFER) += virtio_dma_buf.o diff --git a/drivers/virtio/virtio_dma_buf.c b/drivers/virtio/virtio_dma_buf.c index 45d6e8647dcf1..5127a2f0c986e 100644 --- a/drivers/virtio/virtio_dma_buf.c +++ b/drivers/virtio/virtio_dma_buf.c @@ -5,6 +5,7 @@ * Copyright (C) 2020 Google, Inc. */ +#include <linux/module.h> #include <linux/virtio_dma_buf.h> /** @@ -83,3 +84,5 @@ int virtio_dma_buf_get_uuid(struct dma_buf *dma_buf, return ops->get_uuid(dma_buf, uuid); } EXPORT_SYMBOL(virtio_dma_buf_get_uuid); + +MODULE_LICENSE("GPL"); -- GitLab From 9c6b876c91c067353ab30b81ad1486105bc79e08 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Tue, 18 Aug 2020 13:28:11 -0700 Subject: [PATCH 0558/1494] drm: ast: fix double __iomem sparse warning sparse complains about having 2 "__iomem" attributes on the same line where only one is needed since the first one applies to everything up to the ending ';'. However, to make it clear(er) that both of these pointers are "__iomem", use separate lines for them. ../drivers/gpu/drm/ast/ast_cursor.c:256:26: CK: warning: duplicate [noderef] ../drivers/gpu/drm/ast/ast_cursor.c:256:26: CK: error: multiple address space given: __iomem & __iomem Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: Dave Airlie <airlied@redhat.com> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/a8185578-a69a-16b0-6fdf-f4e46bc4f61f@infradead.org --- drivers/gpu/drm/ast/ast_cursor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ast/ast_cursor.c b/drivers/gpu/drm/ast/ast_cursor.c index 6c96f74cdb9e3..e0f4613918ad6 100644 --- a/drivers/gpu/drm/ast/ast_cursor.c +++ b/drivers/gpu/drm/ast/ast_cursor.c @@ -253,7 +253,8 @@ void ast_cursor_show(struct ast_private *ast, int x, int y, unsigned int offset_x, unsigned int offset_y) { u8 x_offset, y_offset; - u8 __iomem *dst, __iomem *sig; + u8 __iomem *dst; + u8 __iomem *sig; u8 jreg; dst = ast->cursor.vaddr[ast->cursor.next_index]; -- GitLab From 172c1e8572809de8313e311614ff2baf6b936339 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Fri, 3 Jul 2020 14:59:01 +0200 Subject: [PATCH 0559/1494] drm: gma500: Convert to GPIO descriptors Finalize he conversion of GMA500 to use only GPIO descriptors. The GPIO look-up-table is associated with the device directly in the GMA500 Medfield chip driver since no explicit platform type device (such as in x86/platform/intel-mid) exists: the GMA500 probes directly from the PCI device. Apparently GPIOs 128 and 34 are used on all of these so just go ahead and register those for resetting the DSI pipes. Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200703125901.513476-1-linus.walleij@linaro.org --- drivers/gpu/drm/gma500/mdfld_device.c | 20 +++++++++ drivers/gpu/drm/gma500/mdfld_dsi_dpi.c | 2 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 51 ++++++++++++----------- drivers/gpu/drm/gma500/mdfld_dsi_output.h | 2 +- drivers/gpu/drm/gma500/mdfld_output.h | 2 +- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c index b718efccdcf29..be9cf6b1e3b39 100644 --- a/drivers/gpu/drm/gma500/mdfld_device.c +++ b/drivers/gpu/drm/gma500/mdfld_device.c @@ -6,6 +6,7 @@ **************************************************************************/ #include <linux/delay.h> +#include <linux/gpio/machine.h> #include <asm/intel_scu_ipc.h> @@ -505,12 +506,31 @@ static const struct psb_offset mdfld_regmap[3] = { }, }; +/* + * The GPIO lines for resetting DSI pipe 0 and 2 are available in the + * PCI device 0000:00:0c.0 on the Medfield. + */ +static struct gpiod_lookup_table mdfld_dsi_pipe_gpio_table = { + .table = { + GPIO_LOOKUP("0000:00:0c.0", 128, "dsi-pipe0-reset", + GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("0000:00:0c.0", 34, "dsi-pipe2-reset", + GPIO_ACTIVE_HIGH), + { }, + }, +}; + static int mdfld_chip_setup(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; if (pci_enable_msi(dev->pdev)) dev_warn(dev->dev, "Enabling MSI failed!\n"); dev_priv->regmap = mdfld_regmap; + + /* Associate the GPIO lines with the DRM device */ + mdfld_dsi_pipe_gpio_table.dev_id = dev_name(dev->dev); + gpiod_add_lookup_table(&mdfld_dsi_pipe_gpio_table); + return mid_chip_setup(dev); } diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c index c976a9dd9240d..ae1223f631a7f 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c @@ -955,7 +955,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, /* panel hard-reset */ if (p_funcs->reset) { - ret = p_funcs->reset(pipe); + ret = p_funcs->reset(dev, pipe); if (ret) { DRM_ERROR("Panel %d hard-reset failed\n", pipe); return NULL; diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index 2f3486f32fedc..4aab76613bd9e 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/pm_runtime.h> +#include <linux/gpio/consumer.h> #include <asm/intel_scu_ipc.h> @@ -432,42 +433,42 @@ static int mdfld_dsi_get_default_config(struct drm_device *dev, return 0; } -int mdfld_dsi_panel_reset(int pipe) +int mdfld_dsi_panel_reset(struct drm_device *ddev, int pipe) { - unsigned gpio; - int ret = 0; - + struct device *dev = ddev->dev; + struct gpio_desc *gpiod; + + /* + * Raise the GPIO reset line for the corresponding pipe to HIGH, + * this is probably because it is active low so this takes the + * respective pipe out of reset. (We have no code to put it back + * into reset in this driver.) + */ switch (pipe) { case 0: - gpio = 128; + gpiod = gpiod_get(dev, "dsi-pipe0-reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); break; case 2: - gpio = 34; + gpiod = gpiod_get(dev, "dsi-pipe2-reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); break; default: - DRM_ERROR("Invalid output\n"); + DRM_DEV_ERROR(dev, "Invalid output pipe\n"); return -EINVAL; } + gpiod_put(gpiod); - ret = gpio_request(gpio, "gfx"); - if (ret) { - DRM_ERROR("gpio_rqueset failed\n"); - return ret; - } - - ret = gpio_direction_output(gpio, 1); - if (ret) { - DRM_ERROR("gpio_direction_output failed\n"); - goto gpio_error; - } + /* Flush posted writes on the device */ + gpiod = gpiod_get(dev, "dsi-pipe0-reset", GPIOD_ASIS); + if (IS_ERR(gpiod)) + return PTR_ERR(gpiod); + gpiod_get_value(gpiod); + gpiod_put(gpiod); - gpio_get_value(128); - -gpio_error: - if (gpio_is_valid(gpio)) - gpio_free(gpio); - - return ret; + return 0; } /* diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h index 0cccfe400a98a..5c0db3c2903ff 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h @@ -372,6 +372,6 @@ extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode, bool hs); -extern int mdfld_dsi_panel_reset(int pipe); +extern int mdfld_dsi_panel_reset(struct drm_device *dev, int pipe); #endif /*__MDFLD_DSI_OUTPUT_H__*/ diff --git a/drivers/gpu/drm/gma500/mdfld_output.h b/drivers/gpu/drm/gma500/mdfld_output.h index 17a944d70add3..37a516cc56bea 100644 --- a/drivers/gpu/drm/gma500/mdfld_output.h +++ b/drivers/gpu/drm/gma500/mdfld_output.h @@ -54,7 +54,7 @@ struct panel_funcs { const struct drm_encoder_helper_funcs *encoder_helper_funcs; struct drm_display_mode * (*get_config_mode)(struct drm_device *); int (*get_panel_info)(struct drm_device *, int, struct panel_info *); - int (*reset)(int pipe); + int (*reset)(struct drm_device *, int); void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); }; diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 3dd5718c3e315..5340225d6997b 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -13,7 +13,6 @@ #include <drm/drm_encoder.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> -#include <linux/gpio.h> #include "gma_display.h" /* -- GitLab From cdd296cdae1af2d27dae3fcfbdf12c5252ab78cf Mon Sep 17 00:00:00 2001 From: Tom Rix <trix@redhat.com> Date: Wed, 5 Aug 2020 13:59:11 -0700 Subject: [PATCH 0560/1494] drm/gma500: fix error check Reviewing this block of code in cdv_intel_dp_init() ret = cdv_intel_dp_aux_native_read(gma_encoder, DP_DPCD_REV, ... cdv_intel_edp_panel_vdd_off(gma_encoder); if (ret == 0) { /* if this fails, presume the device is a ghost */ DRM_INFO("failed to retrieve link info, disabling eDP\n"); drm_encoder_cleanup(encoder); cdv_intel_dp_destroy(connector); goto err_priv; } else { The (ret == 0) is not strict enough. cdv_intel_dp_aux_native_read() returns > 0 on success otherwise it is failure. So change to <= Fixes: d112a8163f83 ("gma500/cdv: Add eDP support") Signed-off-by: Tom Rix <trix@redhat.com> Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805205911.20927-1-trix@redhat.com --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index f41cbb753bb46..720a767118c9c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -2078,7 +2078,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev intel_dp->dpcd, sizeof(intel_dp->dpcd)); cdv_intel_edp_panel_vdd_off(gma_encoder); - if (ret == 0) { + if (ret <= 0) { /* if this fails, presume the device is a ghost */ DRM_INFO("failed to retrieve link info, disabling eDP\n"); drm_encoder_cleanup(encoder); -- GitLab From d24f1341a63cebdff22454a6464810e6f34030c6 Mon Sep 17 00:00:00 2001 From: Matt Atwood <matthew.s.atwood@intel.com> Date: Wed, 12 Aug 2020 14:07:02 -0700 Subject: [PATCH 0561/1494] drm/i915: Apply Wa_14011264657:gen11+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add minimum width to planes, variable with specific formats for gen11+ to reflect recent bspec changes. Signed-off-by: Matt Atwood <matthew.s.atwood@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200812210702.7153-1-matthew.s.atwood@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 60 ++++++++++++++++---- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2ddabf92adde1..7d50b7177d402 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3762,6 +3762,44 @@ static int glk_max_plane_width(const struct drm_framebuffer *fb, } } +static int icl_min_plane_width(const struct drm_framebuffer *fb) +{ + /* Wa_14011264657, Wa_14011050563: gen11+ */ + switch (fb->format->format) { + case DRM_FORMAT_C8: + return 18; + case DRM_FORMAT_RGB565: + return 10; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XVYU2101010: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: + return 6; + case DRM_FORMAT_NV12: + return 20; + case DRM_FORMAT_P010: + case DRM_FORMAT_P012: + case DRM_FORMAT_P016: + return 12; + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_XVYU12_16161616: + case DRM_FORMAT_XVYU16161616: + return 4; + default: + return 1; + } +} + static int icl_max_plane_width(const struct drm_framebuffer *fb, int color_plane, unsigned int rotation) @@ -3844,29 +3882,31 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) int y = plane_state->uapi.src.y1 >> 16; int w = drm_rect_width(&plane_state->uapi.src) >> 16; int h = drm_rect_height(&plane_state->uapi.src) >> 16; - int max_width; - int max_height; - u32 alignment; - u32 offset; + int max_width, min_width, max_height; + u32 alignment, offset; int aux_plane = intel_main_to_aux_plane(fb, 0); u32 aux_offset = plane_state->color_plane[aux_plane].offset; - if (INTEL_GEN(dev_priv) >= 11) + if (INTEL_GEN(dev_priv) >= 11) { max_width = icl_max_plane_width(fb, 0, rotation); - else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) + min_width = icl_min_plane_width(fb); + } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { max_width = glk_max_plane_width(fb, 0, rotation); - else + min_width = 1; + } else { max_width = skl_max_plane_width(fb, 0, rotation); + min_width = 1; + } if (INTEL_GEN(dev_priv) >= 11) max_height = icl_max_plane_height(); else max_height = skl_max_plane_height(); - if (w > max_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height) { drm_dbg_kms(&dev_priv->drm, - "requested Y/RGB source size %dx%d too big (limit %dx%d)\n", - w, h, max_width, max_height); + "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", + w, h, min_width, max_width, max_height); return -EINVAL; } -- GitLab From 0b06286579b81449b1e8f14f88d3a8db091fd443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 19 Aug 2020 15:27:48 +0200 Subject: [PATCH 0562/1494] drm/ttm: fix broken merge between drm-next and drm-misc-next MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm-next reverted the changes to ttm_tt_create() to do the NULL check inside the function, but drm-misc-next adds new users of this approach. Re-apply the NULL check change inside the function to fix this. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/386628/ --- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/ttm/ttm_tt.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 97ac662a47cb3..e3931e515906e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1180,7 +1180,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, /* * We might need to add a TTM. */ - if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { + if (bo->mem.mem_type == TTM_PL_SYSTEM) { ret = ttm_tt_create(bo, true); if (ret) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 9aa4fbe386e62..1ccf1ef050d6c 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -50,6 +50,9 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) dma_resv_assert_held(bo->base.resv); + if (bo->ttm) + return 0; + if (bdev->need_dma32) page_flags |= TTM_PAGE_FLAG_DMA32; @@ -67,7 +70,6 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) page_flags |= TTM_PAGE_FLAG_SG; break; default: - bo->ttm = NULL; pr_err("Illegal buffer object type\n"); return -EINVAL; } -- GitLab From 2f4b769e4d18c1a38dc892668971fc2f0c4e6f5b Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Thu, 20 Aug 2020 14:12:55 +0200 Subject: [PATCH 0563/1494] drm/panel: novatek,nt39016: Reorder calls in probe The drm_panel_of_backlight() function must be called after drm_panel_init(), according to the function's documentation; otherwise the backlight won't be properly initialized. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200820121256.32037-2-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index 39f7be679da53..daa583030246d 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -285,6 +285,9 @@ static int nt39016_probe(struct spi_device *spi) return PTR_ERR(panel->map); } + drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs, + DRM_MODE_CONNECTOR_DPI); + err = drm_panel_of_backlight(&panel->drm_panel); if (err) { if (err != -EPROBE_DEFER) @@ -292,9 +295,6 @@ static int nt39016_probe(struct spi_device *spi) return err; } - drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs, - DRM_MODE_CONNECTOR_DPI); - drm_panel_add(&panel->drm_panel); return 0; -- GitLab From d738005da9c59e57e5700ccf6f505c9569c93da1 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Thu, 20 Aug 2020 14:12:56 +0200 Subject: [PATCH 0564/1494] drm/panel: novatek,nt39016: Remove 'dev' field in priv struct There is already a 'struct device' pointer in the drm_panel structure, that we can access easily from our priv structure, so there's no need for a separate 'dev' field there. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200820121256.32037-3-paul@crapouillou.net --- drivers/gpu/drm/panel/panel-novatek-nt39016.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index daa583030246d..f8151fe3ac9a1 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -56,7 +56,6 @@ struct nt39016_panel_info { struct nt39016 { struct drm_panel drm_panel; - struct device *dev; struct regmap *map; struct regulator *supply; const struct nt39016_panel_info *panel_info; @@ -124,7 +123,7 @@ static int nt39016_prepare(struct drm_panel *drm_panel) err = regulator_enable(panel->supply); if (err) { - dev_err(panel->dev, "Failed to enable power supply: %d\n", err); + dev_err(drm_panel->dev, "Failed to enable power supply: %d\n", err); return err; } @@ -143,7 +142,7 @@ static int nt39016_prepare(struct drm_panel *drm_panel) err = regmap_multi_reg_write(panel->map, nt39016_panel_regs, ARRAY_SIZE(nt39016_panel_regs)); if (err) { - dev_err(panel->dev, "Failed to init registers: %d\n", err); + dev_err(drm_panel->dev, "Failed to init registers: %d\n", err); goto err_disable_regulator; } @@ -173,7 +172,7 @@ static int nt39016_enable(struct drm_panel *drm_panel) ret = regmap_write(panel->map, NT39016_REG_SYSTEM, NT39016_SYSTEM_RESET_N | NT39016_SYSTEM_STANDBY); if (ret) { - dev_err(panel->dev, "Unable to enable panel: %d\n", ret); + dev_err(drm_panel->dev, "Unable to enable panel: %d\n", ret); return ret; } @@ -193,7 +192,7 @@ static int nt39016_disable(struct drm_panel *drm_panel) err = regmap_write(panel->map, NT39016_REG_SYSTEM, NT39016_SYSTEM_RESET_N); if (err) { - dev_err(panel->dev, "Unable to disable panel: %d\n", err); + dev_err(drm_panel->dev, "Unable to disable panel: %d\n", err); return err; } @@ -252,7 +251,6 @@ static int nt39016_probe(struct spi_device *spi) if (!panel) return -ENOMEM; - panel->dev = dev; spi_set_drvdata(spi, panel); panel->panel_info = of_device_get_match_data(dev); -- GitLab From 3b4efa148da36f158cce3f662e831af2834b8e0f Mon Sep 17 00:00:00 2001 From: Mika Kuoppala <mika.kuoppala@linux.intel.com> Date: Mon, 17 Aug 2020 22:59:26 +0300 Subject: [PATCH 0565/1494] drm/i915: Fix cmd parser desc matching with masks Our variety of defined gpu commands have the actual command id field and possibly length and flags applied. We did start to apply the mask during initialization of the cmd descriptors but forgot to also apply it on comparisons. Fix comparisons in order to properly deny access with associated commands. v2: fix lri with correct mask (Chris) References: 926abff21a8f ("drm/i915/cmdparser: Ignore Length operands during command matching") Reported-by: Nicolai Stange <nstange@suse.de> Cc: stable@vger.kernel.org # v5.4+ Cc: Miroslav Benes <mbenes@suse.cz> Cc: Takashi Iwai <tiwai@suse.de> Cc: Tyler Hicks <tyhicks@canonical.com> Cc: Jon Bloomfield <jon.bloomfield@intel.com> Cc: Chris Wilson <chris.p.wilson@intel.com> Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200817195926.12671-1-mika.kuoppala@linux.intel.com --- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 372354d33f552..5ac4a999f05a6 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1204,6 +1204,12 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, return dst; } +static inline bool cmd_desc_is(const struct drm_i915_cmd_descriptor * const desc, + const u32 cmd) +{ + return desc->cmd.value == (cmd & desc->cmd.mask); +} + static bool check_cmd(const struct intel_engine_cs *engine, const struct drm_i915_cmd_descriptor *desc, const u32 *cmd, u32 length) @@ -1242,19 +1248,19 @@ static bool check_cmd(const struct intel_engine_cs *engine, * allowed mask/value pair given in the whitelist entry. */ if (reg->mask) { - if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_MEM)) { DRM_DEBUG("CMD: Rejected LRM to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_REG) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_REG)) { DRM_DEBUG("CMD: Rejected LRR to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) && + if (cmd_desc_is(desc, MI_LOAD_REGISTER_IMM(1)) && (offset + 2 > length || (cmd[offset + 1] & reg->mask) != reg->value)) { DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n", @@ -1478,7 +1484,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, break; } - if (desc->cmd.value == MI_BATCH_BUFFER_START) { + if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) { ret = check_bbstart(cmd, offset, length, batch_length, batch_addr, shadow_addr, jump_whitelist); -- GitLab From 35201cc1f8053f11bfd47032c1150cb404650a61 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sat, 27 Jun 2020 00:06:06 +0200 Subject: [PATCH 0566/1494] drm: omapdrm: Delete surplus GPIO includes The OMAP DRM driver includes <linux/gpio.h> into the two hdmi4.c and hdmi5.c files but does not use any symbols from these files. Drop the includes. Cc: Tomi Valkeinen <tomi.valkeinen@ti.com> Cc: Tony Lindgren <tony@atomide.com> Cc: Jyri Sarha <jsarha@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200626220606.340937-1-linus.walleij@linaro.org --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 1 - drivers/gpu/drm/omapdrm/dss/hdmi5.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 2578c95570f63..a14fbf06cb301 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -20,7 +20,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/clk.h> -#include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 4d4c1fabd0a1a..b738d9750686a 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -24,7 +24,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/clk.h> -#include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <linux/of.h> -- GitLab From 227c6d109ce50e318ef37bf5c1ce31d3daab1db1 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 5 Aug 2020 11:20:15 +0100 Subject: [PATCH 0567/1494] drm/omap: fix spelling mistake "propert" -> "property" There is a spelling mistake in a pr_err message. Fix it. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805102015.14891-1-colin.king@canonical.com --- drivers/gpu/drm/omapdrm/dss/venc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index e0817934ee163..0fa8f677b647c 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -781,7 +781,7 @@ static int venc_probe_of(struct venc_device *venc) venc->type = OMAP_DSS_VENC_TYPE_SVIDEO; break; default: - dev_err(&venc->pdev->dev, "bad channel propert '%d'\n", + dev_err(&venc->pdev->dev, "bad channel property '%d'\n", channels); r = -EINVAL; goto err; -- GitLab From 8b87014f23e4890fe12547530ef3008e70abf593 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen <tomi.valkeinen@ti.com> Date: Wed, 12 Aug 2020 14:26:25 +0300 Subject: [PATCH 0568/1494] drm/tidss: implement WA for AM65xx erratum i2000 This patch implements WA for AM65xx erratum i2000, which causes YUV formats to show wrong colors. An earlier patch removed a partial WA: a8d9d7da1546349f18eb2d6b6b3a04bdeb38719d ("drm/tidss: remove AM65x PG1 YUV erratum code") The patch explains the reasoning for removal. The change in plans has been that it has become clear that there are and will be users for PG1 SoCs and as such it's good to implement the WA for PG1s. This patch adds the WA back so that it is only used on SR1.0 (which is the new name for PG1). The previous WA code didn't check the SoC revision, which this patch does. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200812112625.59897-1-tomi.valkeinen@ti.com Reviewed-by: Jyri Sarha <jsarha@ti.com> --- drivers/gpu/drm/tidss/tidss_dispc.c | 32 +++++++++++++++++++++++++---- drivers/gpu/drm/tidss/tidss_dispc.h | 4 ++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index c3ece2c9d1c81..b669168ae7cb2 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/sys_soc.h> #include <drm/drm_fourcc.h> #include <drm/drm_fb_cma_helper.h> @@ -302,6 +303,8 @@ struct dispc_device { u32 num_fourccs; u32 memory_bandwidth_limit; + + struct dispc_errata errata; }; static void dispc_write(struct dispc_device *dispc, u16 reg, u32 val) @@ -2641,6 +2644,19 @@ static int dispc_init_am65x_oldi_io_ctrl(struct device *dev, return 0; } +static void dispc_init_errata(struct dispc_device *dispc) +{ + static const struct soc_device_attribute am65x_sr10_soc_devices[] = { + { .family = "AM65X", .revision = "SR1.0" }, + { /* sentinel */ } + }; + + if (soc_device_match(am65x_sr10_soc_devices)) { + dispc->errata.i2000 = true; + dev_info(dispc->dev, "WA for erratum i2000: YUV formats disabled\n"); + } +} + int dispc_init(struct tidss_device *tidss) { struct device *dev = tidss->dev; @@ -2664,19 +2680,27 @@ int dispc_init(struct tidss_device *tidss) if (!dispc) return -ENOMEM; + dispc->tidss = tidss; + dispc->dev = dev; + dispc->feat = feat; + + dispc_init_errata(dispc); + dispc->fourccs = devm_kcalloc(dev, ARRAY_SIZE(dispc_color_formats), sizeof(*dispc->fourccs), GFP_KERNEL); if (!dispc->fourccs) return -ENOMEM; num_fourccs = 0; - for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) + for (i = 0; i < ARRAY_SIZE(dispc_color_formats); ++i) { + if (dispc->errata.i2000 && + dispc_fourcc_is_yuv(dispc_color_formats[i].fourcc)) { + continue; + } dispc->fourccs[num_fourccs++] = dispc_color_formats[i].fourcc; + } dispc->num_fourccs = num_fourccs; - dispc->tidss = tidss; - dispc->dev = dev; - dispc->feat = feat; dispc_common_regmap = dispc->feat->common_regs; diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h index 5984e0de2cd9b..e49432f0abf56 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.h +++ b/drivers/gpu/drm/tidss/tidss_dispc.h @@ -46,6 +46,10 @@ struct dispc_features_scaling { u32 xinc_max; }; +struct dispc_errata { + bool i2000; /* DSS Does Not Support YUV Pixel Data Formats */ +}; + enum dispc_vp_bus_type { DISPC_VP_DPI, /* DPI output */ DISPC_VP_OLDI, /* OLDI (LVDS) output */ -- GitLab From 9517130c9b4b9e66be3b55fee74cfc7789c18f27 Mon Sep 17 00:00:00 2001 From: Douglas Anderson <dianders@chromium.org> Date: Fri, 21 Aug 2020 08:35:14 -0700 Subject: [PATCH 0569/1494] dt-bindings: display: simple: Add KD116N21-30NV-A010 compatible The KD116N21-30NV-A010 is a pretty standard eDP panel. Add it to the list of compatible strings. Signed-off-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200821083454.1.I61e6248813d797c9eeebfbb7019c713aa71c4419@changeid --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index 47247ace86acf..f2204f17a9dc1 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -161,6 +161,8 @@ properties: - innolux,n156bge-l21 # Innolux Corporation 7.0" WSVGA (1024x600) TFT LCD panel - innolux,zj070na-01p + # King & Display KD116N21-30NV-A010 eDP TFT LCD panel + - kingdisplay,kd116n21-30nv-a010 # Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel - koe,tx14d24vm1bpa # Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel -- GitLab From fc26a3758b55d930650b71b32844cd60d459eece Mon Sep 17 00:00:00 2001 From: Douglas Anderson <dianders@chromium.org> Date: Fri, 21 Aug 2020 08:35:15 -0700 Subject: [PATCH 0570/1494] drm: panel: simple: Add KD116N21-30NV-A010 Values come from the vendor and have been tested on hardware. Signed-off-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200821083454.2.Idf25356dff4b36c62704188c3e3d39a2010d6f6a@changeid --- drivers/gpu/drm/panel/panel-simple.c | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 4eabfdd3be2d7..f499de71ab3d6 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2341,6 +2341,34 @@ static const struct panel_desc ivo_m133nwf4_r0 = { .connector_type = DRM_MODE_CONNECTOR_eDP, }; +static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = { + .clock = 81000, + .hdisplay = 1366, + .hsync_start = 1366 + 40, + .hsync_end = 1366 + 40 + 32, + .htotal = 1366 + 40 + 32 + 62, + .vdisplay = 768, + .vsync_start = 768 + 5, + .vsync_end = 768 + 5 + 5, + .vtotal = 768 + 5 + 5 + 122, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc kingdisplay_kd116n21_30nv_a010 = { + .modes = &kingdisplay_kd116n21_30nv_a010_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 256, + .height = 144, + }, + .delay = { + .hpd_absent_delay = 200, + }, + .bus_format = MEDIA_BUS_FMT_RGB666_1X18, + .connector_type = DRM_MODE_CONNECTOR_eDP, +}; + static const struct display_timing koe_tx14d24vm1bpa_timing = { .pixelclock = { 5580000, 5850000, 6200000 }, .hactive = { 320, 320, 320 }, @@ -4047,6 +4075,9 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "ivo,m133nwf4-r0", .data = &ivo_m133nwf4_r0, + }, { + .compatible = "kingdisplay,kd116n21-30nv-a010", + .data = &kingdisplay_kd116n21_30nv_a010, }, { .compatible = "koe,tx14d24vm1bpa", .data = &koe_tx14d24vm1bpa, -- GitLab From 7f7fb53f62cb1602932d770b043d2aed5bd9775d Mon Sep 17 00:00:00 2001 From: Vinay Simha BN <simhavcs@gmail.com> Date: Sun, 16 Aug 2020 11:20:41 +0530 Subject: [PATCH 0571/1494] drm/bridge/tc358775: Fix for PTR_ERR passing zero to 'PTR_ERR' Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Vinay Simha BN <simhavcs@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/1597557042-5154-1-git-send-email-simhavcs@gmail.com --- drivers/gpu/drm/bridge/tc358775.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 7da15cd71f49b..d951cdc582971 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -684,7 +684,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->vdd = devm_regulator_get(dev, "vdd-supply"); if (IS_ERR(tc->vdd)) { - ret = PTR_ERR(tc->vddio); + ret = PTR_ERR(tc->vdd); dev_err(dev, "vdd-supply not found\n"); return ret; } -- GitLab From f688a345f0d7a6df4dd2aeca8e4f3c05e123a0ee Mon Sep 17 00:00:00 2001 From: Nadezda Lutovinova <lutovinova@ispras.ru> Date: Wed, 19 Aug 2020 17:37:56 +0300 Subject: [PATCH 0572/1494] drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working correctly If ge_b850v3_lvds_init() does not allocate memory for ge_b850v3_lvds_ptr, then a null pointer dereference is accessed. The patch adds checking of the return value of ge_b850v3_lvds_init(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Nadezda Lutovinova <lutovinova@ispras.ru> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200819143756.30626-1-lutovinova@ispras.ru --- .../gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 61a24f265c7ac..d2808c4a6fb1c 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -310,8 +310,12 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c, const struct i2c_device_id *id) { struct device *dev = &stdp4028_i2c->dev; + int ret; + + ret = ge_b850v3_lvds_init(dev); - ge_b850v3_lvds_init(dev); + if (ret) + return ret; ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c; i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr); @@ -372,8 +376,12 @@ static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c, const struct i2c_device_id *id) { struct device *dev = &stdp2690_i2c->dev; + int ret; + + ret = ge_b850v3_lvds_init(dev); - ge_b850v3_lvds_init(dev); + if (ret) + return ret; ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c; i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr); -- GitLab From 098754fe3ce79af2d5772c0356ba5d52e67eb64a Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 11 Aug 2020 17:46:57 +1000 Subject: [PATCH 0573/1494] drm/ttm: init mem->bus in common code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drivers all do the same thing here. Reviewed-by: Christian König <christian.koenig@amd.com> for both. Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200811074658.58309-1-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 ------ drivers/gpu/drm/drm_gem_vram_helper.c | 6 ------ drivers/gpu/drm/nouveau/nouveau_bo.c | 6 ------ drivers/gpu/drm/qxl/qxl_ttm.c | 6 ------ drivers/gpu/drm/radeon/radeon_ttm.c | 6 ------ drivers/gpu/drm/ttm/ttm_bo_util.c | 5 +++++ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 6 ------ 7 files changed, 5 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 95f144788b14c..924c19ce3f5af 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -752,12 +752,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct drm_mm_node *mm_node = mem->mm_node; - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - switch (mem->mem_type) { case TTM_PL_SYSTEM: /* system memory */ diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index b410930d94a09..545a877406f45 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1038,14 +1038,8 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, { struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev); - mem->bus.addr = NULL; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - switch (mem->mem_type) { case TTM_PL_SYSTEM: /* nothing to do */ - mem->bus.offset = 0; - mem->bus.base = 0; - mem->bus.is_iomem = false; break; case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5392e5fea5d43..9140387f30dcb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1025,12 +1025,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) struct nvkm_device *device = nvxx_device(&drm->client.device); struct nouveau_mem *mem = nouveau_mem(reg); - reg->bus.addr = NULL; - reg->bus.offset = 0; - reg->bus.size = reg->num_pages << PAGE_SHIFT; - reg->bus.base = 0; - reg->bus.is_iomem = false; - switch (reg->mem_type) { case TTM_PL_SYSTEM: /* System memory */ diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index dc31f3fea33c3..7aae0a96f043e 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -75,12 +75,6 @@ int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev, { struct qxl_device *qdev = qxl_get_qdev(bdev); - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - switch (mem->mem_type) { case TTM_PL_SYSTEM: /* system memory */ diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 31a06ecf450f1..8ca2253f6fbf2 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -363,12 +363,6 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso { struct radeon_device *rdev = radeon_get_rdev(bdev); - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - mem->bus.is_iomem = false; - switch (mem->mem_type) { case TTM_PL_SYSTEM: /* system memory */ diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 7b372ede12c24..eaed29b81d9ef 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -138,6 +138,11 @@ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, if (!bdev->driver->io_mem_reserve) return 0; + mem->bus.addr = NULL; + mem->bus.offset = 0; + mem->bus.size = mem->num_pages << PAGE_SHIFT; + mem->bus.base = 0; + mem->bus.is_iomem = false; retry: ret = bdev->driver->io_mem_reserve(bdev, mem); if (ret == -ENOSPC) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 7247347a9bca8..c7f10b2c93d22 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -715,12 +715,6 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resourc { struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev); - mem->bus.addr = NULL; - mem->bus.is_iomem = false; - mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; - mem->bus.base = 0; - switch (mem->mem_type) { case TTM_PL_SYSTEM: case VMW_PL_GMR: -- GitLab From ebb21aa1882f418b436ee23463683790c553a447 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 11 Aug 2020 17:46:58 +1000 Subject: [PATCH 0574/1494] drm/ttm: drop bus.size from bus placement. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is always calculated the same, and only used in a couple of places. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200811074658.58309-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++- drivers/gpu/drm/radeon/radeon_ttm.c | 7 ++++--- drivers/gpu/drm/ttm/ttm_bo_util.c | 7 ++++--- include/drm/ttm/ttm_resource.h | 2 -- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 924c19ce3f5af..fc5f7ac53d0ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -751,6 +751,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct drm_mm_node *mm_node = mem->mm_node; + size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; switch (mem->mem_type) { case TTM_PL_SYSTEM: @@ -761,7 +762,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; /* check if it's visible */ - if ((mem->bus.offset + mem->bus.size) > adev->gmc.visible_vram_size) + if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size) return -EINVAL; /* Only physically contiguous buffers apply. In a contiguous * buffer, size of the first mm_node would match the number of diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 8ca2253f6fbf2..3a4372ea74b9d 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -362,6 +362,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { struct radeon_device *rdev = radeon_get_rdev(bdev); + size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; switch (mem->mem_type) { case TTM_PL_SYSTEM: @@ -380,7 +381,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; /* check if it's visible */ - if ((mem->bus.offset + mem->bus.size) > rdev->mc.visible_vram_size) + if ((mem->bus.offset + bus_size) > rdev->mc.visible_vram_size) return -EINVAL; mem->bus.base = rdev->mc.aper_base; mem->bus.is_iomem = true; @@ -392,11 +393,11 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso if (mem->placement & TTM_PL_FLAG_WC) mem->bus.addr = ioremap_wc(mem->bus.base + mem->bus.offset, - mem->bus.size); + bus_size); else mem->bus.addr = ioremap(mem->bus.base + mem->bus.offset, - mem->bus.size); + bus_size); if (!mem->bus.addr) return -ENOMEM; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index eaed29b81d9ef..ee04716b2603d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -140,7 +140,6 @@ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, mem->bus.addr = NULL; mem->bus.offset = 0; - mem->bus.size = mem->num_pages << PAGE_SHIFT; mem->bus.base = 0; mem->bus.is_iomem = false; retry: @@ -214,12 +213,14 @@ static int ttm_resource_ioremap(struct ttm_bo_device *bdev, if (mem->bus.addr) { addr = mem->bus.addr; } else { + size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; + if (mem->placement & TTM_PL_FLAG_WC) addr = ioremap_wc(mem->bus.base + mem->bus.offset, - mem->bus.size); + bus_size); else addr = ioremap(mem->bus.base + mem->bus.offset, - mem->bus.size); + bus_size); if (!addr) { (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index bac22a56f6cdb..6d4226190480b 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -162,7 +162,6 @@ struct ttm_resource_manager { * @addr: mapped virtual address * @base: bus base address * @is_iomem: is this io memory ? - * @size: size in byte * @offset: offset from the base address * @io_reserved_vm: The VM system has a refcount in @io_reserved_count * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve @@ -172,7 +171,6 @@ struct ttm_resource_manager { struct ttm_bus_placement { void *addr; phys_addr_t base; - unsigned long size; unsigned long offset; bool is_iomem; bool io_reserved_vm; -- GitLab From 818b032433a345b2f5466660ae054806343263e5 Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Tue, 18 Aug 2020 14:51:41 -0400 Subject: [PATCH 0575/1494] drm/amdkfd: sparse: Fix warning in reading SDMA counters Add __user annotation to fix related sparse warning while reading SDMA counters from userland. Also, rework the read SDMA counters function by removing redundant checks. Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 28 ++----------------- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 8 +++++- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 6 ++-- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index e0e60b0d0669e..560adc57a050b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -153,30 +153,6 @@ static void decrement_queue_count(struct device_queue_manager *dqm, dqm->active_cp_queue_count--; } -int read_sdma_queue_counter(uint64_t q_rptr, uint64_t *val) -{ - int ret; - uint64_t tmp = 0; - - if (!val) - return -EINVAL; - /* - * SDMA activity counter is stored at queue's RPTR + 0x8 location. - */ - if (!access_ok((const void __user *)(q_rptr + - sizeof(uint64_t)), sizeof(uint64_t))) { - pr_err("Can't access sdma queue activity counter\n"); - return -EFAULT; - } - - ret = get_user(tmp, (uint64_t *)(q_rptr + sizeof(uint64_t))); - if (!ret) { - *val = tmp; - } - - return ret; -} - static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) { struct kfd_dev *dev = qpd->dqm->dev; @@ -552,7 +528,7 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { - retval = read_sdma_queue_counter((uint64_t)q->properties.read_ptr, + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, &sdma_val); if (retval) pr_err("Failed to read SDMA queue counter for queue: %d\n", @@ -1473,7 +1449,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { - retval = read_sdma_queue_counter((uint64_t)q->properties.read_ptr, + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, &sdma_val); if (retval) pr_err("Failed to read SDMA queue counter for queue: %d\n", diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 49d8e324c636f..16262e5d93f5c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -251,5 +251,11 @@ static inline void dqm_unlock(struct device_queue_manager *dqm) mutex_unlock(&dqm->lock_hidden); } -int read_sdma_queue_counter(uint64_t q_rptr, uint64_t *val); +static inline int read_sdma_queue_counter(uint64_t __user *q_rptr, uint64_t *val) +{ + /* + * SDMA activity counter is stored at queue's RPTR + 0x8 location. + */ + return get_user(*val, q_rptr + 1); +} #endif /* KFD_DEVICE_QUEUE_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ddd192e3197ce..a0e12a79ab7d9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -87,7 +87,7 @@ struct kfd_sdma_activity_handler_workarea { }; struct temp_sdma_queue_list { - uint64_t rptr; + uint64_t __user *rptr; uint64_t sdma_val; unsigned int queue_id; struct list_head list; @@ -159,7 +159,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work) } INIT_LIST_HEAD(&sdma_q->list); - sdma_q->rptr = (uint64_t)q->properties.read_ptr; + sdma_q->rptr = (uint64_t __user *)q->properties.read_ptr; sdma_q->queue_id = q->properties.queue_id; list_add_tail(&sdma_q->list, &sdma_q_list.list); } @@ -218,7 +218,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work) continue; list_for_each_entry_safe(sdma_q, next, &sdma_q_list.list, list) { - if (((uint64_t)q->properties.read_ptr == sdma_q->rptr) && + if (((uint64_t __user *)q->properties.read_ptr == sdma_q->rptr) && (sdma_q->queue_id == q->properties.queue_id)) { list_del(&sdma_q->list); kfree(sdma_q); -- GitLab From c9977dffcc7e0f728e82209c140991c5bd27c491 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Wed, 19 Aug 2020 13:37:54 -0400 Subject: [PATCH 0576/1494] drm/amd/display: Reject overlay plane configurations in multi-display scenarios [Why] These aren't stable on some platform configurations when driving multiple displays, especially on higher resolution. In particular the delay in asserting p-state and validating from x86 outweights any power or performance benefit from the hardware composition. Under some configurations this will manifest itself as extreme stutter or unresponsiveness especially when combined with cursor movement. [How] Disable these for now. Exposing overlays to userspace doesn't guarantee that they'll be able to use them in any and all configurations and it's part of the DRM contract to have userspace gracefully handle validation failures when they occur. Valdiation occurs as part of DC and this in particular affects RV, so disable this in dcn10_global_validation. Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 07571f84e0f87..1abd81e17f09d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1213,6 +1213,7 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont bool video_large = false; bool desktop_large = false; bool dcc_disabled = false; + bool mpo_enabled = false; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -1221,6 +1222,9 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont if (context->stream_status[i].plane_count > 2) return DC_FAIL_UNSUPPORTED_1; + if (context->stream_status[i].plane_count > 1) + mpo_enabled = true; + for (j = 0; j < context->stream_status[i].plane_count; j++) { struct dc_plane_state *plane = context->stream_status[i].plane_states[j]; @@ -1244,6 +1248,10 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont } } + /* Disable MPO in multi-display configurations. */ + if (context->stream_count > 1 && mpo_enabled) + return DC_FAIL_UNSUPPORTED_1; + /* * Workaround: On DCN10 there is UMC issue that causes underflow when * playing 4k video on 4k desktop with video downscaled and single channel -- GitLab From 53b3f8f40e6cff36ae12b11e6d6b308af3c7e53f Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Wed, 19 Aug 2020 17:23:03 +0800 Subject: [PATCH 0577/1494] drm/amdgpu: refine codes to avoid reentering GPU recovery if other threads have holden the reset lock, recovery will fail to try_lock. Therefore we introduce atomic hive->in_reset and adev->in_gpu_reset, to avoid reentering GPU recovery. v2: drop "? true : false" in the definition of amdgpu_in_reset Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 37 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 3 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 4 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 4 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 116 +++++++++--------- .../drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- 28 files changed, 127 insertions(+), 122 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 54666eea18639..72f2a9aeaf0e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,7 +949,7 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate; - bool in_gpu_reset; + atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; struct mutex lock_reset; struct amdgpu_doorbell_index doorbell_index; @@ -1267,4 +1267,8 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) return adev->gmc.tmz_enabled; } +static inline int amdgpu_in_reset(struct amdgpu_device *adev) +{ + return atomic_read(&adev->in_gpu_reset); +} #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index bf927f432506d..b0dcc800251ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -542,7 +542,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v10_compute_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; #if 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 744366c7ee85d..275f20399373f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -423,7 +423,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, unsigned long flags, end_jiffies; int retry; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index feab4cc6e8367..4997189d8b368 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -419,7 +419,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, int retry; struct vi_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index a755f63514e15..d08839d9491f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -552,7 +552,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v9_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 35fed75a43972..79b397800cbc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -127,7 +127,7 @@ static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_ poll_wait(file, &adev->autodump.gpu_hang, poll_table); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return POLLIN | POLLRDNORM | POLLWRNORM; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6573e11124624..78fd2c9a7b7d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1940,7 +1940,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) if (adev->ip_blocks[i].status.hw == true) break; - if (adev->in_gpu_reset || adev->in_suspend) { + if (amdgpu_in_reset(adev) || adev->in_suspend) { r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { DRM_ERROR("resume of IP block <%s> failed %d\n", @@ -2117,7 +2117,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev) AMDGPU_RESET_MAGIC_NUM)) return true; - if (!adev->in_gpu_reset) + if (!amdgpu_in_reset(adev)) return false; /* @@ -3053,6 +3053,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->mn_lock); mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); + atomic_set(&adev->in_gpu_reset, 0); mutex_init(&adev->lock_reset); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4200,16 +4201,14 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) { - if (trylock) { - if (!mutex_trylock(&adev->lock_reset)) - return false; - } else - mutex_lock(&adev->lock_reset); + if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) + return false; + + mutex_lock(&adev->lock_reset); atomic_inc(&adev->gpu_reset_counter); - adev->in_gpu_reset = true; switch (amdgpu_asic_reset_method(adev)) { case AMD_RESET_METHOD_MODE1: adev->mp1_state = PP_MP1_STATE_SHUTDOWN; @@ -4229,7 +4228,7 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) { amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } @@ -4340,12 +4339,14 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, true); - if (hive && !mutex_trylock(&hive->reset_lock)) { - DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", - job ? job->base.id : -1, hive->hive_id); - mutex_unlock(&hive->hive_lock); - return 0; + hive = amdgpu_get_xgmi_hive(adev, false); + if (hive) { + if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", + job ? job->base.id : -1, hive->hive_id); + return 0; + } + mutex_lock(&hive->hive_lock); } /* @@ -4367,7 +4368,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev, !hive)) { + if (!amdgpu_device_lock_adev(tmp_adev)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); mutex_unlock(&hive->hive_lock); @@ -4505,7 +4506,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, } if (hive) { - mutex_unlock(&hive->reset_lock); + atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index a819360a4b6ae..ebea3f6558268 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -719,7 +719,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); @@ -777,7 +777,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_write; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index aa1e77c60c0a6..116a89990f39e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1869,7 +1869,7 @@ static int psp_load_smu_fw(struct psp_context *psp) return 0; - if (adev->in_gpu_reset && ras && ras->supported) { + if (amdgpu_in_reset(adev) && ras && ras->supported) { ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); if (ret) { DRM_WARN("Failed to set MP1 state prepare for reload\n"); @@ -1984,7 +1984,7 @@ static int psp_load_fw(struct amdgpu_device *adev) int ret; struct psp_context *psp = &adev->psp; - if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { + if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ goto skip_memalloc; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 866373c95cae6..fa2c28ae97854 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2081,7 +2081,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, amdgpu_ras_request_reset_on_boot(adev, ras_block->block); return 0; - } else if (adev->in_suspend || adev->in_gpu_reset) { + } else if (adev->in_suspend || amdgpu_in_reset(adev)) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -2090,7 +2090,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, } /* in resume phase, no need to create ras fs node */ - if (adev->in_suspend || adev->in_gpu_reset) + if (adev->in_suspend || amdgpu_in_reset(adev)) return 0; if (ih_info->cb) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3d2712a4cf4d2..97449ab24c20f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2098,7 +2098,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) uint64_t size; int r; - if (!adev->mman.initialized || adev->in_gpu_reset || + if (!adev->mman.initialized || amdgpu_in_reset(adev) || adev->mman.buffer_funcs_enabled == enable) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 183743c5fb7bf..5f851d17eef42 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -628,7 +628,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ - if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend)) + if (!amdgpu_sriov_vf(adev) && (amdgpu_in_reset(adev) || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index f826945989c72..b2046c3a404de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -325,9 +325,9 @@ static inline bool is_virtual_machine(void) #define amdgpu_sriov_is_pp_one_vf(adev) \ ((adev)->virt.gim_feature & AMDGIM_FEATURE_PP_ONE_VF) #define amdgpu_sriov_is_debug(adev) \ - ((!adev->in_gpu_reset) && adev->virt.tdr_debug) + ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ - ((!adev->in_gpu_reset) && (!adev->virt.tdr_debug)) + ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index cd6e6eb7d966b..7a61dc6738ebd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -372,7 +372,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo tmp->hive_id = adev->gmc.xgmi.hive_id; INIT_LIST_HEAD(&tmp->device_list); mutex_init(&tmp->hive_lock); - mutex_init(&tmp->reset_lock); + atomic_set(&tmp->in_reset, 0); task_barrier_init(&tmp->tb); if (lock) @@ -594,7 +594,6 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) if(!(--hive->number_devices)){ amdgpu_xgmi_sysfs_destroy(adev, hive); mutex_destroy(&hive->hive_lock); - mutex_destroy(&hive->reset_lock); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 6999eab16a720..453336ca96757 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -30,10 +30,11 @@ struct amdgpu_hive_info { uint64_t hive_id; struct list_head device_list; int number_devices; - struct mutex hive_lock, reset_lock; + struct mutex hive_lock; struct kobject *kobj; struct device_attribute dev_attr; struct amdgpu_device *adev; + atomic_t in_reset; int hi_req_count; struct amdgpu_device *hi_req_gpu; struct task_barrier tb; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index e527be22a3d54..d851fe80eaf4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6198,7 +6198,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) struct v10_gfx_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.gfx_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6210,7 +6210,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { + } else if (amdgpu_in_reset(adev)) { /* reset mqd with the backup copy */ if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6563,7 +6563,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v10_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6599,7 +6599,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6609,7 +6609,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 3b71272024206..d5843e8a6e17d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4633,7 +4633,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4670,7 +4670,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4682,7 +4682,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 2c5bb282cc01c..93c63ff3b35ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3686,7 +3686,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3724,7 +3724,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -3736,7 +3736,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3930,7 +3930,7 @@ static int gfx_v9_0_hw_fini(void *handle) /* Use deinitialize sequence from CAIL when unbinding device from driver, * otherwise KIQ is hanging when binding back */ - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, adev->gfx.kiq.ring.me, adev->gfx.kiq.ring.pipe, @@ -4088,7 +4088,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index ec8c0af395538..9d3b1245a339c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,7 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -312,7 +312,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready || - adev->in_gpu_reset || + amdgpu_in_reset(adev) || ring->sched.ready == false) { gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0); mutex_unlock(&adev->mman.gtt_window_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 3ce5c1d2fdf2b..80c146df338aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -434,7 +434,7 @@ static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 3e6615f9d39c1..9ab65ca7df777 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -635,7 +635,7 @@ static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6a780b674018f..86f20426c4afb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -501,7 +501,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -596,7 +596,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; if (ring->sched.ready) { diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 475ff5df8c873..f27d83f2de789 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -250,7 +250,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) */ locked = mutex_trylock(&adev->lock_reset); if (locked) - adev->in_gpu_reset = true; + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -262,7 +262,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) flr_done: if (locked) { - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 9cf695c05db39..3cb10ab943a66 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -271,7 +271,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) */ locked = mutex_trylock(&adev->lock_reset); if (locked) - adev->in_gpu_reset = true; + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -283,7 +283,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) flr_done: if (locked) { - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0a1e53fda08aa..b8f36cbcff7b6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1658,7 +1658,7 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { mutex_lock(&dm->dc_lock); dm->cached_dc_state = dc_copy_state(dm->dc->current_state); @@ -1844,7 +1844,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { dc_state = dm->cached_dc_state; r = dm_dmub_hw_init(adev); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index a77f7347fdfc4..e469de005451b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -121,7 +121,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, enum amd_pm_state_type pm; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -159,7 +159,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("battery", buf, strlen("battery")) == 0) @@ -265,7 +265,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level = 0xff; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -307,7 +307,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level current_level = 0xff; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("low", buf, strlen("low")) == 0) { @@ -411,7 +411,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -455,7 +455,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0, ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -496,7 +496,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->pp_force_state_enabled) @@ -516,7 +516,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, unsigned long idx; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strlen(buf) == 1) @@ -576,7 +576,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -620,7 +620,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -773,7 +773,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, const char delimiter[3] = {' ', '\n', '\0'}; uint32_t type; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (count > 127) @@ -867,7 +867,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -921,7 +921,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtou64(buf, 0, &featuremask); @@ -966,7 +966,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1027,7 +1027,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1095,7 +1095,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1131,7 +1131,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1163,7 +1163,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, uint32_t mask = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1199,7 +1199,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1231,7 +1231,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1269,7 +1269,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1301,7 +1301,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1339,7 +1339,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1371,7 +1371,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1409,7 +1409,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1441,7 +1441,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1479,7 +1479,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1509,7 +1509,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1552,7 +1552,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1582,7 +1582,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1645,7 +1645,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1685,7 +1685,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; tmp[0] = *(buf); @@ -1749,7 +1749,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1787,7 +1787,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1830,7 +1830,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, uint64_t count0 = 0, count1 = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->flags & AMD_IS_APU) @@ -1871,7 +1871,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->unique_id) @@ -1969,7 +1969,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, ssize_t size = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -2193,7 +2193,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, int channel = to_sensor_dev_attr(attr)->index; int r, temp = 0, size = sizeof(temp); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (channel >= PP_TEMP_MAX) @@ -2329,7 +2329,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2365,7 +2365,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err, ret; int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2419,7 +2419,7 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2473,7 +2473,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2508,7 +2508,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2542,7 +2542,7 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, u32 size = sizeof(min_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2572,7 +2572,7 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, u32 size = sizeof(max_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2601,7 +2601,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, int err; u32 rpm = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2635,7 +2635,7 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2686,7 +2686,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2723,7 +2723,7 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, int value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2768,7 +2768,7 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, u32 vddgfx; int r, size = sizeof(vddgfx); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2805,7 +2805,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, u32 vddnb; int r, size = sizeof(vddnb); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; /* only APUs have vddnb */ @@ -2847,7 +2847,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, int r, size = sizeof(u32); unsigned uw; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2888,7 +2888,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2922,7 +2922,7 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2957,7 +2957,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, int err; u32 value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (amdgpu_sriov_vf(adev)) @@ -3000,7 +3000,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, uint32_t sclk; int r, size = sizeof(sclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3037,7 +3037,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, uint32_t mclk; int r, size = sizeof(mclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3558,7 +3558,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) u32 flags = 0; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c index c7216362b68da..da84012b7fd51 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c @@ -489,7 +489,7 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; - bool use_baco = (adev->in_gpu_reset && + bool use_baco = (amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || (adev->in_runpm && amdgpu_asic_supports_baco(adev)); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8eb5b92903cd0..8462b30f4fe39 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1110,7 +1110,7 @@ static int smu_disable_dpms(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; bool use_baco = !smu->is_apu && - ((adev->in_gpu_reset && + ((amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); -- GitLab From 5049a0526988d575c777db20a52eba5efaadbd2a Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn <lukas.bulwahn@gmail.com> Date: Wed, 19 Aug 2020 10:18:08 +0200 Subject: [PATCH 0578/1494] drm/amd/display: remove unintended executable mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Besides the intended change, commit 4cc1178e166a ("drm/amdgpu: replace DRM prefix with PCI device info for gfx/mmhub") also set the source files mmhub_v1_0.c and gfx_v9_4.c to be executable, i.e., changed fromold mode 644 to new mode 755. Commit 241b2ec9317e ("drm/amd/display: Add dcn30 Headers (v2)") added the four header files {dpcs,dcn}_3_0_0_{offset,sh_mask}.h as executable, i.e., mode 755. Set to the usual modes for source and headers files and clean up those mistakes. No functional change. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 0 drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c mode change 100755 => 100644 drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h old mode 100755 new mode 100644 -- GitLab From 26902e8c58c8e147ca126c83a9ba3f3ac8c5cc7b Mon Sep 17 00:00:00 2001 From: Wang Hai <wanghai38@huawei.com> Date: Wed, 19 Aug 2020 19:34:09 +0800 Subject: [PATCH 0579/1494] drm/amd/powerplay: remove duplicate include Remove asic_reg/nbio/nbio_6_1_offset.h which is included more than once Reviewed-by: Evan Quan <evan.quan@amd.com> Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Wang Hai <wanghai38@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h index e6d9e84059e17..0d08c57d3bca4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h @@ -34,7 +34,6 @@ #include "asic_reg/gc/gc_9_2_1_offset.h" #include "asic_reg/gc/gc_9_2_1_sh_mask.h" -#include "asic_reg/nbio/nbio_6_1_offset.h" #include "asic_reg/nbio/nbio_6_1_offset.h" #include "asic_reg/nbio/nbio_6_1_sh_mask.h" -- GitLab From 4c319bbebef5491c1305d7b56e708f566f83d14a Mon Sep 17 00:00:00 2001 From: Alex Dewar <alex.dewar90@gmail.com> Date: Thu, 20 Aug 2020 18:58:06 +0100 Subject: [PATCH 0580/1494] drm/amd/pm: Remove unnecessary cast In init_powerplay_table_information() the value returned from kmalloc() is cast unnecessarily. Remove cast. Issue identified with Coccinelle. Signed-off-by: Alex Dewar <alex.dewar90@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c index 195d8539fbb43..740e2fc7a0345 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c @@ -252,7 +252,7 @@ static int init_powerplay_table_information( phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT); phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT); - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; -- GitLab From ba1bab14b61752a9b37d749735f4ce8889e3397a Mon Sep 17 00:00:00 2001 From: Furquan Shaikh <furquan@google.com> Date: Thu, 20 Aug 2020 00:52:41 -0700 Subject: [PATCH 0581/1494] drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in amdgpu_dm_update_backlight_caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In `amdgpu_dm_update_backlight_caps()`, there is a local `amdgpu_dm_backlight_caps` object that is filled in by `amdgpu_acpi_get_backlight_caps()`. However, this object is uninitialized before the call and hence the subsequent check for aux_support can fail since it is not initialized by `amdgpu_acpi_get_backlight_caps()` as well. This change initializes this local `amdgpu_dm_backlight_caps` object to 0. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Furquan Shaikh <furquan@google.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b8f36cbcff7b6..075960864e120 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2927,6 +2927,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) #if defined(CONFIG_ACPI) struct amdgpu_dm_backlight_caps caps; + memset(&caps, 0, sizeof(caps)); + if (dm->backlight_caps.caps_valid) return; -- GitLab From 66b8a9c0a747b9d05509d480f5054a65ac327515 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Fri, 21 Aug 2020 11:30:19 +0800 Subject: [PATCH 0582/1494] drm/amd/pm: enable run_btc callback for sienna_cichlid DC BTC support for sienna_cichlid is added, it provides the DC tolerance and aging measurements. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 8ffa8b71b75fe..d2320ce7ef0db 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -95,6 +95,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), @@ -1735,6 +1736,11 @@ static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, return ret; } +static int sienna_cichlid_run_btc(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); +} + static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -2792,6 +2798,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .mode1_reset = smu_v11_0_mode1_reset, .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .run_btc = sienna_cichlid_run_btc, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, -- GitLab From 6049db43d6dd9cbb9d7f897839d15b0bc600e23c Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Thu, 20 Aug 2020 10:06:32 +0800 Subject: [PATCH 0583/1494] drm/amdgpu: change reset lock from mutex to rw_semaphore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clients don't need reset-lock for synchronization when no GPU recovery. v2: change to return the return value of down_read_killable. v3: if GPU recovery begin, VF ignore FLR notification. Reviewed-by: Monk Liu <monk.liu@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 23 ++++++++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 18 ++++++---------- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 18 ++++++---------- 5 files changed, 32 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 72f2a9aeaf0e5..ba5e8635ca5fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -951,7 +951,7 @@ struct amdgpu_device { atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; - struct mutex lock_reset; + struct rw_semaphore reset_sem; struct amdgpu_doorbell_index doorbell_index; struct mutex notifier_lock; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 79b397800cbc1..cc5c7f81c5404 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -101,14 +101,18 @@ static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) file->private_data = adev; - mutex_lock(&adev->lock_reset); + ret = down_read_killable(&adev->reset_sem); + if (ret) + return ret; + if (adev->autodump.dumping.done) { reinit_completion(&adev->autodump.dumping); ret = 0; } else { ret = -EBUSY; } - mutex_unlock(&adev->lock_reset); + + up_read(&adev->reset_sem); return ret; } @@ -1242,7 +1246,9 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) } /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + r = down_read_killable(&adev->reset_sem); + if (r) + return r; /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -1269,7 +1275,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) kthread_unpark(ring->sched.thread); } - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1459,7 +1465,9 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) return -ENOMEM; /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + r = down_read_killable(&adev->reset_sem); + if (r) + goto pro_end; /* stop the scheduler */ kthread_park(ring->sched.thread); @@ -1500,13 +1508,14 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) /* restart the scheduler */ kthread_unpark(ring->sched.thread); - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); +pro_end: kfree(fences); - return 0; + return r; } static int amdgpu_debugfs_sclk_set(void *data, u64 val) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 78fd2c9a7b7d8..82242e2f56588 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3054,7 +3054,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); atomic_set(&adev->in_gpu_reset, 0); - mutex_init(&adev->lock_reset); + init_rwsem(&adev->reset_sem); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4206,7 +4206,7 @@ static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - mutex_lock(&adev->lock_reset); + down_write(&adev->reset_sem); atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4229,7 +4229,7 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); + up_write(&adev->reset_sem); } static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index f27d83f2de789..9c07014d9bd6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -238,19 +238,15 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. - * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" - * to run gpu_recover() after FLR_NOTIFICATION_CMPL received - * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - atomic_set(&adev->in_gpu_reset, 1); + if (!down_read_trylock(&adev->reset_sem)) + return; + + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -261,10 +257,8 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); - } + atomic_set(&adev->in_gpu_reset, 0); + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 3cb10ab943a66..9c23abf9b140d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -259,19 +259,15 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. - * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" - * to run gpu_recover() after FLR_NOTIFICATION_CMPL received - * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - atomic_set(&adev->in_gpu_reset, 1); + if (!down_read_trylock(&adev->reset_sem)) + return; + + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -282,10 +278,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); - } + atomic_set(&adev->in_gpu_reset, 0); + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) -- GitLab From cbfd17f7ba405d143c0db5ebcddc978cb4153762 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Thu, 20 Aug 2020 10:17:39 +0800 Subject: [PATCH 0584/1494] drm/amdgpu: fix the nullptr issue when reenter GPU recovery in single gpu system, if driver reenter gpu recovery, amdgpu_device_lock_adev will return false, but hive is nullptr now. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 82242e2f56588..81b1d9a1dca0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4371,8 +4371,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, if (!amdgpu_device_lock_adev(tmp_adev)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); - mutex_unlock(&hive->hive_lock); - return 0; + r = 0; + goto skip_recovery; } /* @@ -4505,6 +4505,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, amdgpu_device_unlock_adev(tmp_adev); } +skip_recovery: if (hive) { atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); -- GitLab From aac891685da661aeb97691e8724df231130bb452 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Thu, 20 Aug 2020 10:40:53 +0800 Subject: [PATCH 0585/1494] drm/amdgpu: refine message print for devices of hive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using dev_xxx instead of DRM_xxx/pr_xxx to indicate which device of a hive is the message for. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 32 +++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 81b1d9a1dca0b..08548e051cc01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3370,7 +3370,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) { int r; - DRM_INFO("amdgpu: finishing device.\n"); + dev_info(adev->dev, "amdgpu: finishing device.\n"); flush_delayed_work(&adev->delayed_init_work); adev->shutdown = true; @@ -3555,12 +3555,12 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) if (amdgpu_device_need_post(adev)) { r = amdgpu_atom_asic_init(adev->mode_info.atom_context); if (r) - DRM_ERROR("amdgpu asic init failed\n"); + dev_err(adev->dev, "amdgpu asic init failed\n"); } r = amdgpu_device_ip_resume(adev); if (r) { - DRM_ERROR("amdgpu_device_ip_resume failed (%d).\n", r); + dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); return r; } amdgpu_fence_driver_resume(adev); @@ -3584,7 +3584,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) if (r == 0) { r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM); if (r != 0) - DRM_ERROR("Failed to pin cursor BO (%d)\n", r); + dev_err(adev->dev, "Failed to pin cursor BO (%d)\n", r); amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj); amdgpu_bo_unreserve(aobj); } @@ -3674,7 +3674,7 @@ static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev) adev->ip_blocks[i].status.hang = adev->ip_blocks[i].version->funcs->check_soft_reset(adev); if (adev->ip_blocks[i].status.hang) { - DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name); + dev_info(adev->dev, "IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name); asic_hang = true; } } @@ -3735,7 +3735,7 @@ static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev) (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) || adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) { if (adev->ip_blocks[i].status.hang) { - DRM_INFO("Some block need full reset!\n"); + dev_info(adev->dev, "Some block need full reset!\n"); return true; } } @@ -3823,7 +3823,7 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) else tmo = msecs_to_jiffies(100); - DRM_INFO("recover vram bo from shadow start\n"); + dev_info(adev->dev, "recover vram bo from shadow start\n"); mutex_lock(&adev->shadow_list_lock); list_for_each_entry(shadow, &adev->shadow_list, shadow_list) { @@ -3859,11 +3859,11 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) dma_fence_put(fence); if (r < 0 || tmo <= 0) { - DRM_ERROR("recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo); + dev_err(adev->dev, "recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo); return -EIO; } - DRM_INFO("recover vram bo from shadow done\n"); + dev_info(adev->dev, "recover vram bo from shadow done\n"); return 0; } @@ -3962,7 +3962,7 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev) bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) { if (!amdgpu_device_ip_check_soft_reset(adev)) { - DRM_INFO("Timeout, but no hardware hang detected.\n"); + dev_info(adev->dev, "Timeout, but no hardware hang detected.\n"); return false; } @@ -4002,7 +4002,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) return true; disabled: - DRM_INFO("GPU recovery disabled.\n"); + dev_info(adev->dev, "GPU recovery disabled.\n"); return false; } @@ -4041,7 +4041,7 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, r = amdgpu_device_ip_soft_reset(adev); amdgpu_device_ip_post_soft_reset(adev); if (r || amdgpu_device_ip_check_soft_reset(adev)) { - DRM_INFO("soft reset failed, will fallback to full reset!\n"); + dev_info(adev->dev, "soft reset failed, will fallback to full reset!\n"); need_full_reset = true; } } @@ -4077,7 +4077,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, r = amdgpu_asic_reset(tmp_adev); if (r) { - DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s", + dev_err(tmp_adev->dev, "ASIC reset failed with error, %d for drm dev, %s", r, tmp_adev->ddev->unique); break; } @@ -4111,7 +4111,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, if (need_full_reset) { /* post card */ if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) - DRM_WARN("asic atom init failed!"); + dev_warn(tmp_adev->dev, "asic atom init failed!"); if (!r) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); @@ -4369,7 +4369,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (!amdgpu_device_lock_adev(tmp_adev)) { - DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", + dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; goto skip_recovery; @@ -4444,7 +4444,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, &need_full_reset); /*TODO Should we stop ?*/ if (r) { - DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", + dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ", r, tmp_adev->ddev->unique); tmp_adev->asic_reset_res = r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index ebea3f6558268..d6981425ec510 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -743,7 +743,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) failed_kiq_read: if (reg_val_offs) amdgpu_device_wb_free(adev, reg_val_offs); - pr_err("failed to read reg:%x\n", reg); + dev_err(adev->dev, "failed to read reg:%x\n", reg); return ~0; } @@ -796,5 +796,5 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_write: - pr_err("failed to write reg:%x\n", reg); + dev_err(adev->dev, "failed to write reg:%x\n", reg); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ae720a6dc5a0a..d84649b4d51a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -93,7 +93,7 @@ void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq: - pr_err("failed to write reg %x wait reg %x\n", reg0, reg1); + dev_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 9d3b1245a339c..ad9ad622ccce7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -390,7 +390,7 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 86f20426c4afb..e1a0ae327cf5a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -633,7 +633,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); return -ETIME; } -- GitLab From d95e8e97e2d522b7ebb1d5a64c01d8de307621dc Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Tue, 18 Aug 2020 18:44:17 +0800 Subject: [PATCH 0586/1494] drm/amdgpu: refine create and release logic of hive info Change to dynamically create and release hive info object, which help driver support more hives in the future. v2: Change to save hive object pointer in adev, to avoid locking xgmi_mutex every time when calling amdgpu_get_xgmi_hive. v3: 1. Change type of hive object pointer in adev from void* to amdgpu_hive_info*. 2. remove unnecessary variable initialization. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 208 +++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 14 +- 5 files changed, 131 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ba5e8635ca5fe..486113b2bfd44 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -251,6 +251,7 @@ struct amdgpu_fpriv; struct amdgpu_bo_va_mapping; struct amdgpu_atif; struct kfd_vm_fault_info; +struct amdgpu_hive_info; enum amdgpu_cp_irq { AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0, @@ -727,7 +728,7 @@ struct amdgpu_device { #ifdef CONFIG_DRM_AMD_ACP struct amdgpu_acp acp; #endif - + struct amdgpu_hive_info *hive; /* ASIC */ enum amd_asic_type asic_type; uint32_t family; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 08548e051cc01..a4300af5797b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2857,7 +2857,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) { struct amdgpu_device *adev = container_of(__work, struct amdgpu_device, xgmi_reset_work); - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); /* It's a bug to not have a hive within this function */ if (WARN_ON(!hive)) @@ -2895,6 +2895,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) if (adev->asic_reset_res) DRM_WARN("ASIC reset failed with error, %d for drm dev, %s", adev->asic_reset_res, adev->ddev->unique); + amdgpu_put_xgmi_hive(hive); } static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) @@ -4339,11 +4340,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, false); + hive = amdgpu_get_xgmi_hive(adev); if (hive) { if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", job ? job->base.id : -1, hive->hive_id); + amdgpu_put_xgmi_hive(hive); return 0; } mutex_lock(&hive->hive_lock); @@ -4509,6 +4511,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, if (hive) { atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); + amdgpu_put_xgmi_hive(hive); } if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fa2c28ae97854..ec377a8147a21 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1554,9 +1554,10 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) struct amdgpu_device *remote_adev = NULL; struct amdgpu_device *adev = ras->adev; struct list_head device_list, *device_list_handle = NULL; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, false); if (!ras->disable_ras_err_cnt_harvest) { + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); + /* Build list of devices to query RAS related errors */ if (hive && adev->gmc.xgmi.num_physical_nodes > 1) { device_list_handle = &hive->device_list; @@ -1569,6 +1570,8 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) list_for_each_entry(remote_adev, device_list_handle, gmc.xgmi.head) amdgpu_ras_log_on_err_counter(remote_adev); + + amdgpu_put_xgmi_hive(hive); } if (amdgpu_device_should_recover_gpu(ras->adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 7a61dc6738ebd..08ed4dddfaf1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -35,11 +35,9 @@ static DEFINE_MUTEX(xgmi_mutex); -#define AMDGPU_MAX_XGMI_HIVE 8 #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 -static struct amdgpu_hive_info xgmi_hives[AMDGPU_MAX_XGMI_HIVE]; -static unsigned hive_count = 0; +static LIST_HEAD(xgmi_hive_list); static const int xgmi_pcs_err_status_reg_vg20[] = { smnXGMI0_PCS_GOPX16_PCS_ERROR_STATUS, @@ -171,59 +169,47 @@ static const struct amdgpu_pcs_ras_field wafl_pcs_ras_fields[] = { * */ +static struct attribute amdgpu_xgmi_hive_id = { + .name = "xgmi_hive_id", + .mode = S_IRUGO +}; -static ssize_t amdgpu_xgmi_show_hive_id(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct amdgpu_hive_info *hive = - container_of(attr, struct amdgpu_hive_info, dev_attr); - - return snprintf(buf, PAGE_SIZE, "%llu\n", hive->hive_id); -} +static struct attribute *amdgpu_xgmi_hive_attrs[] = { + &amdgpu_xgmi_hive_id, + NULL +}; -static int amdgpu_xgmi_sysfs_create(struct amdgpu_device *adev, - struct amdgpu_hive_info *hive) +static ssize_t amdgpu_xgmi_show_attrs(struct kobject *kobj, + struct attribute *attr, char *buf) { - int ret = 0; - - if (WARN_ON(hive->kobj)) - return -EINVAL; - - hive->kobj = kobject_create_and_add("xgmi_hive_info", &adev->dev->kobj); - if (!hive->kobj) { - dev_err(adev->dev, "XGMI: Failed to allocate sysfs entry!\n"); - return -EINVAL; - } - - hive->dev_attr = (struct device_attribute) { - .attr = { - .name = "xgmi_hive_id", - .mode = S_IRUGO, + struct amdgpu_hive_info *hive = container_of( + kobj, struct amdgpu_hive_info, kobj); - }, - .show = amdgpu_xgmi_show_hive_id, - }; - - ret = sysfs_create_file(hive->kobj, &hive->dev_attr.attr); - if (ret) { - dev_err(adev->dev, "XGMI: Failed to create device file xgmi_hive_id\n"); - kobject_del(hive->kobj); - kobject_put(hive->kobj); - hive->kobj = NULL; - } + if (attr == &amdgpu_xgmi_hive_id) + return snprintf(buf, PAGE_SIZE, "%llu\n", hive->hive_id); - return ret; + return 0; } -static void amdgpu_xgmi_sysfs_destroy(struct amdgpu_device *adev, - struct amdgpu_hive_info *hive) +static void amdgpu_xgmi_hive_release(struct kobject *kobj) { - sysfs_remove_file(hive->kobj, &hive->dev_attr.attr); - kobject_del(hive->kobj); - kobject_put(hive->kobj); - hive->kobj = NULL; + struct amdgpu_hive_info *hive = container_of( + kobj, struct amdgpu_hive_info, kobj); + + mutex_destroy(&hive->hive_lock); + kfree(hive); } +static const struct sysfs_ops amdgpu_xgmi_hive_ops = { + .show = amdgpu_xgmi_show_attrs, +}; + +struct kobj_type amdgpu_xgmi_hive_type = { + .release = amdgpu_xgmi_hive_release, + .sysfs_ops = &amdgpu_xgmi_hive_ops, + .default_attrs = amdgpu_xgmi_hive_attrs, +}; + static ssize_t amdgpu_xgmi_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) @@ -287,8 +273,8 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, /* Create sysfs link to hive info folder on the first device */ - if (adev != hive->adev) { - ret = sysfs_create_link(&adev->dev->kobj, hive->kobj, + if (hive->kobj.parent != (&adev->dev->kobj)) { + ret = sysfs_create_link(&adev->dev->kobj, &hive->kobj, "xgmi_hive_info"); if (ret) { dev_err(adev->dev, "XGMI: Failed to create link to hive info"); @@ -296,9 +282,9 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, } } - sprintf(node, "node%d", hive->number_devices); + sprintf(node, "node%d", atomic_read(&hive->number_devices)); /* Create sysfs link form the hive folder to yourself */ - ret = sysfs_create_link(hive->kobj, &adev->dev->kobj, node); + ret = sysfs_create_link(&hive->kobj, &adev->dev->kobj, node); if (ret) { dev_err(adev->dev, "XGMI: Failed to create link from hive info"); goto remove_link; @@ -326,78 +312,96 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev, device_remove_file(adev->dev, &dev_attr_xgmi_device_id); device_remove_file(adev->dev, &dev_attr_xgmi_error); - if (adev != hive->adev) + if (hive->kobj.parent != (&adev->dev->kobj)) sysfs_remove_link(&adev->dev->kobj,"xgmi_hive_info"); - sprintf(node, "node%d", hive->number_devices); - sysfs_remove_link(hive->kobj, node); + sprintf(node, "node%d", atomic_read(&hive->number_devices)); + sysfs_remove_link(&hive->kobj, node); } -struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock) +struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) { - int i; - struct amdgpu_hive_info *tmp; + struct amdgpu_hive_info *hive = NULL, *tmp = NULL; + int ret; if (!adev->gmc.xgmi.hive_id) return NULL; + if (adev->hive) { + kobject_get(&adev->hive->kobj); + return adev->hive; + } + mutex_lock(&xgmi_mutex); - for (i = 0 ; i < hive_count; ++i) { - tmp = &xgmi_hives[i]; - if (tmp->hive_id == adev->gmc.xgmi.hive_id) { - if (lock) - mutex_lock(&tmp->hive_lock); - mutex_unlock(&xgmi_mutex); - return tmp; + if (!list_empty(&xgmi_hive_list)) { + list_for_each_entry_safe(hive, tmp, &xgmi_hive_list, node) { + if (hive->hive_id == adev->gmc.xgmi.hive_id) + goto pro_end; } } - if (i >= AMDGPU_MAX_XGMI_HIVE) { - mutex_unlock(&xgmi_mutex); - return NULL; + + hive = kzalloc(sizeof(*hive), GFP_KERNEL); + if (!hive) { + dev_err(adev->dev, "XGMI: allocation failed\n"); + hive = NULL; + goto pro_end; } /* initialize new hive if not exist */ - tmp = &xgmi_hives[hive_count++]; - - if (amdgpu_xgmi_sysfs_create(adev, tmp)) { - mutex_unlock(&xgmi_mutex); - return NULL; + ret = kobject_init_and_add(&hive->kobj, + &amdgpu_xgmi_hive_type, + &adev->dev->kobj, + "%s", "xgmi_hive_info"); + if (ret) { + dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n"); + kfree(hive); + hive = NULL; + goto pro_end; } - tmp->adev = adev; - tmp->hive_id = adev->gmc.xgmi.hive_id; - INIT_LIST_HEAD(&tmp->device_list); - mutex_init(&tmp->hive_lock); - atomic_set(&tmp->in_reset, 0); - task_barrier_init(&tmp->tb); - - if (lock) - mutex_lock(&tmp->hive_lock); - tmp->pstate = AMDGPU_XGMI_PSTATE_UNKNOWN; - tmp->hi_req_gpu = NULL; + hive->hive_id = adev->gmc.xgmi.hive_id; + INIT_LIST_HEAD(&hive->device_list); + INIT_LIST_HEAD(&hive->node); + mutex_init(&hive->hive_lock); + atomic_set(&hive->in_reset, 0); + atomic_set(&hive->number_devices, 0); + task_barrier_init(&hive->tb); + hive->pstate = AMDGPU_XGMI_PSTATE_UNKNOWN; + hive->hi_req_gpu = NULL; /* * hive pstate on boot is high in vega20 so we have to go to low * pstate on after boot. */ - tmp->hi_req_count = AMDGPU_MAX_XGMI_DEVICE_PER_HIVE; + hive->hi_req_count = AMDGPU_MAX_XGMI_DEVICE_PER_HIVE; + list_add_tail(&hive->node, &xgmi_hive_list); + +pro_end: + if (hive) + kobject_get(&hive->kobj); mutex_unlock(&xgmi_mutex); + return hive; +} - return tmp; +void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive) +{ + if (hive) + kobject_put(&hive->kobj); } int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) { int ret = 0; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); struct amdgpu_device *request_adev = hive->hi_req_gpu ? hive->hi_req_gpu : adev; bool is_hi_req = pstate == AMDGPU_XGMI_PSTATE_MAX_VEGA20; bool init_low = hive->pstate == AMDGPU_XGMI_PSTATE_UNKNOWN; + amdgpu_put_xgmi_hive(hive); /* fw bug so temporarily disable pstate switching */ return 0; @@ -449,7 +453,7 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev /* Each psp need to set the latest topology */ ret = psp_xgmi_set_topology_info(&adev->psp, - hive->number_devices, + atomic_read(&hive->number_devices), &adev->psp.xgmi_context.top_info); if (ret) dev_err(adev->dev, @@ -511,7 +515,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) adev->gmc.xgmi.node_id = adev->gmc.xgmi.physical_node_id + 16; } - hive = amdgpu_get_xgmi_hive(adev, 1); + hive = amdgpu_get_xgmi_hive(adev); if (!hive) { ret = -EINVAL; dev_err(adev->dev, @@ -519,6 +523,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id); goto exit; } + mutex_lock(&hive->hive_lock); top_info = &adev->psp.xgmi_context.top_info; @@ -526,7 +531,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) list_for_each_entry(entry, &hive->device_list, head) top_info->nodes[count++].node_id = entry->node_id; top_info->num_nodes = count; - hive->number_devices = count; + atomic_set(&hive->number_devices, count); task_barrier_add_task(&hive->tb); @@ -565,35 +570,48 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) exit_unlock: mutex_unlock(&hive->hive_lock); exit: - if (!ret) + if (!ret) { + adev->hive = hive; dev_info(adev->dev, "XGMI: Add node %d, hive 0x%llx.\n", adev->gmc.xgmi.physical_node_id, adev->gmc.xgmi.hive_id); - else + } else { + amdgpu_put_xgmi_hive(hive); dev_err(adev->dev, "XGMI: Failed to add node %d, hive 0x%llx ret: %d\n", adev->gmc.xgmi.physical_node_id, adev->gmc.xgmi.hive_id, ret); + } return ret; } int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) { - struct amdgpu_hive_info *hive; + struct amdgpu_hive_info *hive = adev->hive; if (!adev->gmc.xgmi.supported) return -EINVAL; - hive = amdgpu_get_xgmi_hive(adev, 1); if (!hive) return -EINVAL; + mutex_lock(&hive->hive_lock); task_barrier_rem_task(&hive->tb); amdgpu_xgmi_sysfs_rem_dev_info(adev, hive); + if (hive->hi_req_gpu == adev) + hive->hi_req_gpu = NULL; + list_del(&adev->gmc.xgmi.head); mutex_unlock(&hive->hive_lock); - if(!(--hive->number_devices)){ - amdgpu_xgmi_sysfs_destroy(adev, hive); - mutex_destroy(&hive->hive_lock); + amdgpu_put_xgmi_hive(hive); + adev->hive = NULL; + + if (atomic_dec_return(&hive->number_devices) == 0) { + /* Remove the hive from global hive list */ + mutex_lock(&xgmi_mutex); + list_del(&hive->node); + mutex_unlock(&xgmi_mutex); + + amdgpu_put_xgmi_hive(hive); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 453336ca96757..148560d635543 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -27,13 +27,12 @@ struct amdgpu_hive_info { - uint64_t hive_id; - struct list_head device_list; - int number_devices; + struct kobject kobj; + uint64_t hive_id; + struct list_head device_list; + struct list_head node; + atomic_t number_devices; struct mutex hive_lock; - struct kobject *kobj; - struct device_attribute dev_attr; - struct amdgpu_device *adev; atomic_t in_reset; int hi_req_count; struct amdgpu_device *hi_req_gpu; @@ -51,7 +50,8 @@ struct amdgpu_pcs_ras_field { uint32_t pcs_err_shift; }; -struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock); +struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); +void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive); int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); int amdgpu_xgmi_add_device(struct amdgpu_device *adev); int amdgpu_xgmi_remove_device(struct amdgpu_device *adev); -- GitLab From 08ebb485f0ee8ba1c9ca3f83c9cdbda32b357869 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Thu, 6 Aug 2020 14:48:15 +0800 Subject: [PATCH 0587/1494] drm/amdgpu: annotate a false positive recursive locking Re-apply commit 72e14ebf9fc09e33b28b70f00a2ed9821c198633 [ 584.110304] ============================================ [ 584.110590] WARNING: possible recursive locking detected [ 584.110876] 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 Tainted: G OE [ 584.111164] -------------------------------------------- [ 584.111456] kworker/38:1/553 is trying to acquire lock: [ 584.111721] ffff9b15ff0a47a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.112112] but task is already holding lock: [ 584.112673] ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.113068] other info that might help us debug this: [ 584.113689] Possible unsafe locking scenario: [ 584.114350] CPU0 [ 584.114685] ---- [ 584.115014] lock(&adev->reset_sem); [ 584.115349] lock(&adev->reset_sem); [ 584.115678] *** DEADLOCK *** [ 584.116624] May be due to missing lock nesting notation [ 584.117284] 4 locks held by kworker/38:1/553: [ 584.117616] #0: ffff9ad635c1d348 ((wq_completion)events){+.+.}, at: process_one_work+0x21f/0x630 [ 584.117967] #1: ffffac708e1c3e58 ((work_completion)(&con->recovery_work)){+.+.}, at: process_one_work+0x21f/0x630 [ 584.118358] #2: ffffffffc1c2a5d0 (&tmp->hive_lock){+.+.}, at: amdgpu_device_gpu_recover+0xae/0x1030 [amdgpu] [ 584.118786] #3: ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.119222] stack backtrace: [ 584.119990] CPU: 38 PID: 553 Comm: kworker/38:1 Kdump: loaded Tainted: G OE 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 [ 584.120782] Hardware name: Supermicro SYS-7049GP-TRT/X11DPG-QT, BIOS 3.1 05/23/2019 [ 584.121223] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 584.121638] Call Trace: [ 584.122050] dump_stack+0x98/0xd5 [ 584.122499] __lock_acquire+0x1139/0x16e0 [ 584.122931] ? trace_hardirqs_on+0x3b/0xf0 [ 584.123358] ? cancel_delayed_work+0xa6/0xc0 [ 584.123771] lock_acquire+0xb8/0x1c0 [ 584.124197] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.124599] down_write+0x49/0x120 [ 584.125032] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125472] amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125910] ? amdgpu_ras_error_query+0x1b8/0x2a0 [amdgpu] [ 584.126367] amdgpu_ras_do_recovery+0x159/0x190 [amdgpu] [ 584.126789] process_one_work+0x29e/0x630 [ 584.127208] worker_thread+0x3c/0x3f0 [ 584.127621] ? __kthread_parkme+0x61/0x90 [ 584.128014] kthread+0x12f/0x150 [ 584.128402] ? process_one_work+0x630/0x630 [ 584.128790] ? kthread_park+0x90/0x90 [ 584.129174] ret_from_fork+0x3a/0x50 Each adev has owned lock_class_key to avoid false positive recursive locking. v2: 1. register adev->lock_key into lockdep, otherwise lockdep will report the below warning [ 1216.705820] BUG: key ffff890183b647d0 has not been registered! [ 1216.705924] ------------[ cut here ]------------ [ 1216.705972] DEBUG_LOCKS_WARN_ON(1) [ 1216.705997] WARNING: CPU: 20 PID: 541 at kernel/locking/lockdep.c:3743 lockdep_init_map+0x150/0x210 v3: change to use down_write_nest_lock to annotate the false dead-lock warning. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index a4300af5797b9..172dc47b7f39a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4202,12 +4202,17 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, + struct amdgpu_hive_info *hive) { if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - down_write(&adev->reset_sem); + if (hive) { + down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); + } else { + down_write(&adev->reset_sem); + } atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4370,7 +4375,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev)) { + if (!amdgpu_device_lock_adev(tmp_adev, hive)) { dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; -- GitLab From 6ec46653eb80d4d97b18298d81a80cf2ca81066c Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Fri, 21 Aug 2020 16:20:47 +0800 Subject: [PATCH 0588/1494] drm/amd/pm: set VCN pg per instances When deciding whether to set pg for vcn1, instances number is more generic than chip name. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index d2320ce7ef0db..66d655958a789 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -783,7 +783,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0x10000, NULL); if (ret) @@ -795,7 +795,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0x10000, NULL); if (ret) -- GitLab From d844812b28421c3409215a128a48ecfdaa82b91e Mon Sep 17 00:00:00 2001 From: "Prike.Liang" <Prike.Liang@amd.com> Date: Mon, 1 Jun 2020 14:07:13 +0800 Subject: [PATCH 0589/1494] drm/amdgpu: enable ATHUB clock gatting Enable ATHUB clock gatting set in Renoir series. Signed-off-by: Prike.Liang <Prike.Liang@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/athub_v1_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c index 847ca9b3ce4ea..3ea5578643200 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c @@ -73,6 +73,7 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev, case CHIP_VEGA12: case CHIP_VEGA20: case CHIP_RAVEN: + case CHIP_RENOIR: athub_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); athub_update_medium_grain_light_sleep(adev, -- GitLab From 50166d1ce59e8f78660102ac07fea515ed695234 Mon Sep 17 00:00:00 2001 From: "Prike.Liang" <Prike.Liang@amd.com> Date: Mon, 1 Jun 2020 14:10:54 +0800 Subject: [PATCH 0590/1494] drm/amdgpu: enable HDP clock gatting Enabe HDP SD/DS clock gatting in Renoir series. Signed-off-by: Prike.Liang <Prike.Liang@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/soc15.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3cd98c144bc65..3c3a7adad0249 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1452,7 +1452,8 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable uint32_t def, data; if (adev->asic_type == CHIP_VEGA20 || - adev->asic_type == CHIP_ARCTURUS) { + adev->asic_type == CHIP_ARCTURUS || + adev->asic_type == CHIP_RENOIR) { def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) -- GitLab From 1348969ab68cb864034ec4fe48a86c157cc4e10d Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Mon, 24 Aug 2020 12:27:47 -0400 Subject: [PATCH 0591/1494] drm/amdgpu: drm_device to amdgpu_device by inline-f (v2) Get the amdgpu_device from the DRM device by use of an inline function, drm_to_adev(). The inline function resolves a pointer to struct drm_device to a pointer to struct amdgpu_device. v2: Use a typed visible static inline function instead of an invisible macro. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 18 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 12 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 12 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 16 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 4 +- drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 22 ++--- drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 6 +- .../gpu/drm/amd/amdgpu/atombios_encoders.c | 34 ++++---- drivers/gpu/drm/amd/amdgpu/atombios_i2c.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 48 +++++------ drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 50 ++++++------ drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 58 +++++++------- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 48 +++++------ drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 4 +- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 2 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 61 +++++++------- .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 3 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 80 +++++++++---------- 44 files changed, 303 insertions(+), 300 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 486113b2bfd44..f33a1f372681a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -986,6 +986,11 @@ struct amdgpu_device { struct ratelimit_state throttling_logging_rs; }; +static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) +{ + return ddev->dev_private; +} + static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) { return container_of(bdev, struct amdgpu_device, mman.bdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0effc1d468241..b74846fc39338 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -483,7 +483,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, /* Can't handle buffers from different drivers */ goto out_put; - adev = obj->dev->dev_private; + adev = drm_to_adev(obj->dev); bo = gem_to_amdgpu_bo(obj); if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT))) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 62cb510e2cc47..517eb00b836ae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1674,7 +1674,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, return -EINVAL; obj = dma_buf->priv; - if (obj->dev->dev_private != adev) + if (drm_to_adev(obj->dev) != adev) /* Can't handle buffers from other devices */ return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index e33f63712b46f..662cc414ceec7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1882,7 +1882,7 @@ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) */ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); WREG32(reg, val); } @@ -1898,7 +1898,7 @@ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) */ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); uint32_t r; r = RREG32(reg); @@ -1916,7 +1916,7 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) */ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); WREG32_IO(reg, val); } @@ -1932,7 +1932,7 @@ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) */ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); uint32_t r; r = RREG32_IO(reg); @@ -1944,7 +1944,7 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct atom_context *ctx = adev->mode_info.atom_context; return snprintf(buf, PAGE_SIZE, "%s\n", ctx->vbios_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 4053597b3af2b..15c45b2a39835 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -265,7 +265,7 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; union drm_amdgpu_bo_list *args = data; uint32_t handle = args->in.list_handle; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index a1aec205435de..3bce625189ce4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -41,7 +41,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); /* bail if the connector does not have hpd pin, e.g., @@ -279,7 +279,7 @@ amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev) static void amdgpu_connector_get_edid(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); if (amdgpu_connector->edid) @@ -463,7 +463,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector, uint64_t val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; @@ -834,7 +834,7 @@ static enum drm_mode_status amdgpu_connector_vga_mode_valid(struct drm_connector struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* XXX check mode bandwidth */ @@ -941,7 +941,7 @@ static bool amdgpu_connector_check_hpd_status_unchanged(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); enum drm_connector_status status; @@ -972,7 +972,7 @@ static enum drm_connector_status amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); const struct drm_encoder_helper_funcs *encoder_funcs; int r; @@ -1159,7 +1159,7 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); /* XXX check mode bandwidth */ @@ -1311,7 +1311,7 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector) bool amdgpu_connector_is_dp12_capable(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if ((adev->clock.default_dispclk >= 53900) && amdgpu_connector_encoder_is_hbr2(connector)) { @@ -1325,7 +1325,7 @@ static enum drm_connector_status amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index e84a6e0bc7844..690648785b3c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1288,7 +1288,7 @@ static void trace_amdgpu_cs_ibs(struct amdgpu_cs_parser *parser) int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser parser = {}; bool reserved_buffers = false; @@ -1432,7 +1432,7 @@ static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev, int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_fence_to_handle *info = data; struct dma_fence *fence; struct drm_syncobj *syncobj; @@ -1608,7 +1608,7 @@ static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev, int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_wait_fences *wait = data; uint32_t fence_count = wait->in.fence_count; struct drm_amdgpu_fence *fences_user; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index ba243cc8f5850..59032c26fc823 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -385,7 +385,7 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, enum drm_sched_priority priority; union drm_amdgpu_ctx *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; id = args->in.ctx_id; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index cc5c7f81c5404..37eb8e77d61ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1236,7 +1236,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r = 0, i; r = pm_runtime_get_sync(dev->dev); @@ -1287,7 +1287,7 @@ static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); seq_write(m, adev->bios, adev->bios_size); return 0; @@ -1297,7 +1297,7 @@ static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); @@ -1318,7 +1318,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 172dc47b7f39a..06aa0a98f4a51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -132,7 +132,7 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t cnt = amdgpu_asic_get_pcie_replay_count(adev); return snprintf(buf, PAGE_SIZE, "%llu\n", cnt); @@ -157,7 +157,7 @@ static ssize_t amdgpu_device_get_product_name(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_name); } @@ -179,7 +179,7 @@ static ssize_t amdgpu_device_get_product_number(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_number); } @@ -201,7 +201,7 @@ static ssize_t amdgpu_device_get_serial_number(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->serial); } @@ -219,7 +219,7 @@ static DEVICE_ATTR(serial_number, S_IRUGO, */ bool amdgpu_device_supports_boco(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (adev->flags & AMD_IS_PX) return true; @@ -236,7 +236,7 @@ bool amdgpu_device_supports_boco(struct drm_device *dev) */ bool amdgpu_device_supports_baco(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_asic_supports_baco(adev); } @@ -3457,7 +3457,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) return -ENODEV; } - adev = dev->dev_private; + adev = drm_to_adev(dev); if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; @@ -3545,7 +3545,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) { struct drm_connector *connector; struct drm_connector_list_iter iter; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_crtc *crtc; int r = 0; @@ -4662,7 +4662,7 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) int amdgpu_device_baco_enter(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); if (!amdgpu_device_supports_baco(adev->ddev)) @@ -4676,7 +4676,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev) int amdgpu_device_baco_exit(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); int ret = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index d761729651998..e7ebc7bb70de8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -152,7 +152,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_gem_object *obj; struct amdgpu_flip_work *work; @@ -292,7 +292,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set, pm_runtime_mark_last_busy(dev->dev); - adev = dev->dev_private; + adev = drm_to_adev(dev); /* if we have active crtcs and we don't have a power ref, take the current one */ if (active && !adev->have_disp_power_ref) { @@ -813,7 +813,7 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, int vbl_start, vbl_end, vtotal, ret = 0; bool in_vbl = true; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index b3a62d5ba4e21..9c297300291f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -455,7 +455,7 @@ static struct drm_gem_object * amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf) { struct dma_resv *resv = dma_buf->resv; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_bo *bo; struct amdgpu_bo_param bp; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 92d0368217a2c..651b51ab14cb6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1167,7 +1167,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, } else if (ret) goto err_pci; - adev = dev->dev_private; + adev = drm_to_adev(dev); ret = amdgpu_debugfs_init(adev); if (ret) DRM_ERROR("Creating debugfs files failed (%d).\n", ret); @@ -1201,7 +1201,7 @@ static void amdgpu_pci_shutdown(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (amdgpu_ras_intr_triggered()) return; @@ -1234,7 +1234,7 @@ static int amdgpu_pmops_resume(struct device *dev) static int amdgpu_pmops_freeze(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int r; adev->in_hibernate = true; @@ -1270,7 +1270,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int ret, i; if (!adev->runpm) { @@ -1321,7 +1321,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int ret; if (!adev->runpm) @@ -1357,7 +1357,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) static int amdgpu_pmops_runtime_idle(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ int ret = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c index 61fcf247a6389..af4ef84e27a77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c @@ -35,7 +35,7 @@ void amdgpu_link_encoder_connector(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_connector *connector; struct drm_connector_list_iter iter; struct amdgpu_connector *amdgpu_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 58d4c219178a2..cfccd3d33341b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -700,7 +700,7 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int i; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { @@ -749,7 +749,7 @@ static int amdgpu_debugfs_gpu_recover(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7f9e50247413d..8371a87240873 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -217,7 +217,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; union drm_amdgpu_gem_create *args = data; @@ -298,7 +298,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct ttm_operation_ctx ctx = { true, false }; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_gem_userptr *args = data; struct drm_gem_object *gobj; struct amdgpu_bo *bo; @@ -587,7 +587,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, struct drm_amdgpu_gem_va *args = data; struct drm_gem_object *gobj; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_bo *abo; struct amdgpu_bo_va *bo_va; @@ -711,7 +711,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_gem_op *args = data; struct drm_gem_object *gobj; struct amdgpu_vm_bo_base *base; @@ -788,7 +788,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_gem_object *gobj; uint32_t handle; u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index bc01a06546aaf..ba3027c1d7a7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -47,7 +47,7 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", (adev->mman.bdev.man[TTM_PL_TT].size) * PAGE_SIZE); @@ -65,7 +65,7 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT])); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index 70dbe343f51df..411c84194f97c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c @@ -40,7 +40,7 @@ static int amdgpu_i2c_pre_xfer(struct i2c_adapter *i2c_adap) { struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; @@ -82,7 +82,7 @@ static int amdgpu_i2c_pre_xfer(struct i2c_adapter *i2c_adap) static void amdgpu_i2c_post_xfer(struct i2c_adapter *i2c_adap) { struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; @@ -101,7 +101,7 @@ static void amdgpu_i2c_post_xfer(struct i2c_adapter *i2c_adap) static int amdgpu_i2c_get_clock(void *i2c_priv) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -116,7 +116,7 @@ static int amdgpu_i2c_get_clock(void *i2c_priv) static int amdgpu_i2c_get_data(void *i2c_priv) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -130,7 +130,7 @@ static int amdgpu_i2c_get_data(void *i2c_priv) static void amdgpu_i2c_set_clock(void *i2c_priv, int clock) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -143,7 +143,7 @@ static void amdgpu_i2c_set_clock(void *i2c_priv, int clock) static void amdgpu_i2c_set_data(void *i2c_priv, int data) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index dcd4921705987..2f53fa0ae9a62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -445,7 +445,7 @@ static int amdgpu_debugfs_sa_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); seq_printf(m, "--------------------- DELAYED --------------------- \n"); amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED], diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 0cc4c67f95f72..508cb34a91428 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -151,7 +151,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev) irqreturn_t amdgpu_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); irqreturn_t ret; ret = amdgpu_ih_process(adev, &adev->irq.ih); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 7619f1c3084df..c2a697d3f830f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -78,7 +78,7 @@ void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev) */ void amdgpu_driver_unload_kms(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (adev == NULL) return; @@ -479,7 +479,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev, */ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_info *info = data; struct amdgpu_mode_info *minfo = &adev->mode_info; void __user *out = (void __user *)(uintptr_t)info->return_pointer; @@ -992,7 +992,7 @@ void amdgpu_driver_lastclose_kms(struct drm_device *dev) */ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv; int r, pasid; @@ -1077,7 +1077,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) void amdgpu_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_bo_list *list; struct amdgpu_bo *pd; @@ -1142,7 +1142,7 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int vpos, hpos, stat; u32 count; @@ -1210,7 +1210,7 @@ int amdgpu_enable_vblank_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe); return amdgpu_irq_get(adev, &adev->crtc_irq, idx); @@ -1227,7 +1227,7 @@ void amdgpu_disable_vblank_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe); amdgpu_irq_put(adev, &adev->crtc_irq, idx); @@ -1263,7 +1263,7 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_info_firmware fw_info; struct drm_amdgpu_query_fw query_fw; struct atom_context *ctx = adev->mode_info.atom_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 116a89990f39e..c22fb0194df78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -2604,7 +2604,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t fw_ver; int ret; @@ -2631,7 +2631,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); void *cpu_addr; dma_addr_t dma_addr; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index 9581283a4c785..0da0a0d986720 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -123,7 +123,7 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { union drm_amdgpu_sched *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); enum drm_sched_priority priority; int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 97449ab24c20f..245d9352ef511 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2134,7 +2134,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = file_priv->minor->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); if (adev == NULL) return -EINVAL; @@ -2315,7 +2315,7 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *)m->private; unsigned ttm_pl = (uintptr_t)node->info_ent->data; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct ttm_mem_type_manager *man = &adev->mman.bdev.man[ttm_pl]; struct drm_printer p = drm_seq_file_printer(m); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5f851d17eef42..55fe19a2f3322 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -408,7 +408,7 @@ static ssize_t show_##name(struct device *dev, \ char *buf) \ { \ struct drm_device *ddev = dev_get_drvdata(dev); \ - struct amdgpu_device *adev = ddev->dev_private; \ + struct amdgpu_device *adev = drm_to_adev(ddev); \ \ return snprintf(buf, PAGE_SIZE, "0x%08x\n", adev->field); \ } \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 771c27478bb12..620472a70460a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -3222,7 +3222,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { union drm_amdgpu_vm *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; long timeout = msecs_to_jiffies(2000); int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index be6a7ec22de48..543f3d28be171 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -47,7 +47,7 @@ static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size); } @@ -64,7 +64,7 @@ static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size); } @@ -81,7 +81,7 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); @@ -99,7 +99,7 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); @@ -110,7 +110,7 @@ static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); switch (adev->gmc.vram_vendor) { case SAMSUNG: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 08ed4dddfaf1c..bda3f709a8e17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -215,7 +215,7 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.xgmi.node_id); @@ -227,7 +227,7 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t ficaa_pie_ctl_in, ficaa_pie_status_in; uint64_t fica_out; unsigned int error_count = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index 213e62a28ba03..159a2a4385a1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -41,7 +41,7 @@ void amdgpu_atombios_crtc_overscan_setup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); SET_CRTC_OVERSCAN_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); @@ -84,7 +84,7 @@ void amdgpu_atombios_crtc_overscan_setup(struct drm_crtc *crtc, void amdgpu_atombios_crtc_scaler_setup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); ENABLE_SCALER_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); @@ -114,7 +114,7 @@ void amdgpu_atombios_crtc_lock(struct drm_crtc *crtc, int lock) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); ENABLE_CRTC_PS_ALLOCATION args; @@ -131,7 +131,7 @@ void amdgpu_atombios_crtc_enable(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); ENABLE_CRTC_PS_ALLOCATION args; @@ -147,7 +147,7 @@ void amdgpu_atombios_crtc_blank(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); BLANK_CRTC_PS_ALLOCATION args; @@ -163,7 +163,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); ENABLE_DISP_POWER_GATING_PS_ALLOCATION args; @@ -192,7 +192,7 @@ void amdgpu_atombios_crtc_set_dtd_timing(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); SET_CRTC_USING_DTD_TIMING_PARAMETERS args; int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); u16 misc = 0; @@ -307,7 +307,7 @@ static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_encoder *encoder = amdgpu_crtc->encoder; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -588,7 +588,7 @@ void amdgpu_atombios_crtc_program_pll(struct drm_crtc *crtc, struct amdgpu_atom_ss *ss) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u8 frev, crev; int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); union set_pixel_clock args; @@ -749,7 +749,7 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder); @@ -818,7 +818,7 @@ void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); u32 pll_clock = mode->clock; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 9b74cfdba7b8c..cc2494671f9d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -60,7 +60,7 @@ static int amdgpu_atombios_dp_process_aux_ch(struct amdgpu_i2c_chan *chan, u8 delay, u8 *ack) { struct drm_device *dev = chan->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union aux_channel_transaction args; int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); unsigned char *base; @@ -305,7 +305,7 @@ static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev, u8 amdgpu_atombios_dp_get_sinktype(struct amdgpu_connector *amdgpu_connector) { struct drm_device *dev = amdgpu_connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_atombios_dp_encoder_service(adev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, amdgpu_connector->ddc_bus->rec.i2c_id, 0); @@ -702,7 +702,7 @@ void amdgpu_atombios_dp_link_train(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector; struct amdgpu_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 1e94a9b652f70..a7466f3562bc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -70,7 +70,7 @@ u8 amdgpu_atombios_encoder_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) return 0; @@ -84,7 +84,7 @@ amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encode { struct drm_encoder *encoder = &amdgpu_encoder->base; struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder_atom_dig *dig; if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) @@ -152,7 +152,7 @@ amdgpu_atombios_encoder_get_backlight_brightness(struct backlight_device *bd) struct amdgpu_backlight_privdata *pdata = bl_get_data(bd); struct amdgpu_encoder *amdgpu_encoder = pdata->encoder; struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); } @@ -166,7 +166,7 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode struct drm_connector *drm_connector) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct backlight_device *bd; struct backlight_properties props; struct amdgpu_backlight_privdata *pdata; @@ -229,7 +229,7 @@ void amdgpu_atombios_encoder_fini_backlight(struct amdgpu_encoder *amdgpu_encoder) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct backlight_device *bd = NULL; struct amdgpu_encoder_atom_dig *dig; @@ -319,7 +319,7 @@ static void amdgpu_atombios_encoder_setup_dac(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); DAC_ENCODER_CONTROL_PS_ALLOCATION args; int index = 0; @@ -382,7 +382,7 @@ static void amdgpu_atombios_encoder_setup_dvo(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); union dvo_encoder_control args; int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); @@ -573,7 +573,7 @@ amdgpu_atombios_encoder_setup_dig_encoder(struct drm_encoder *encoder, int action, int panel_mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -762,7 +762,7 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a uint8_t lane_num, uint8_t lane_set) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1178,7 +1178,7 @@ amdgpu_atombios_encoder_set_edp_panel_power(struct drm_connector *connector, { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_device *dev = amdgpu_connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union dig_transmitter_control args; int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); uint8_t frev, crev; @@ -1225,7 +1225,7 @@ amdgpu_atombios_encoder_setup_external_encoder(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder *ext_amdgpu_encoder = to_amdgpu_encoder(ext_encoder); union external_encoder_control args; @@ -1466,7 +1466,7 @@ void amdgpu_atombios_encoder_set_crtc_source(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); union crtc_source_param args; @@ -1701,7 +1701,7 @@ amdgpu_atombios_encoder_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -1751,7 +1751,7 @@ amdgpu_atombios_encoder_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); uint32_t bios_0_scratch; @@ -1790,7 +1790,7 @@ amdgpu_atombios_encoder_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *ext_encoder = amdgpu_get_external_encoder(encoder); @@ -1848,7 +1848,7 @@ amdgpu_atombios_encoder_set_bios_scratch_regs(struct drm_connector *connector, bool connected) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -1999,7 +1999,7 @@ struct amdgpu_encoder_atom_dig * amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) { struct drm_device *dev = encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_mode_info *mode_info = &adev->mode_info; int index = GetIndexIntoMasterTable(DATA, LVDS_Info); uint16_t data_offset, misc; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c index b4cc7c55fa16f..09a538465ffdc 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c @@ -40,7 +40,7 @@ static int amdgpu_atombios_i2c_process_i2c_ch(struct amdgpu_i2c_chan *chan, u8 *buf, u8 num) { struct drm_device *dev = chan->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); unsigned char *base; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 84b45a019a36d..65301a56344b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -504,7 +504,7 @@ void dce_v10_0_disable_dce(struct amdgpu_device *adev) static void dce_v10_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1209,7 +1209,7 @@ static struct amdgpu_audio_pin *dce_v10_0_audio_get_pin(struct amdgpu_device *ad static void dce_v10_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1226,7 +1226,7 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1272,7 +1272,7 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1328,7 +1328,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1483,7 +1483,7 @@ static void dce_v10_0_audio_fini(struct amdgpu_device *adev) static void dce_v10_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1519,7 +1519,7 @@ static void dce_v10_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint8_t *frame = buffer + 3; @@ -1538,7 +1538,7 @@ static void dce_v10_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v10_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1569,7 +1569,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1749,7 +1749,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v10_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1822,7 +1822,7 @@ static void dce_v10_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1836,7 +1836,7 @@ static void dce_v10_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1850,7 +1850,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2095,7 +2095,7 @@ static void dce_v10_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); u32 tmp; @@ -2111,7 +2111,7 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; u32 tmp; @@ -2250,7 +2250,7 @@ static u32 dce_v10_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2285,7 +2285,7 @@ static u32 dce_v10_0_pick_pll(struct drm_crtc *crtc) static void dce_v10_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2300,7 +2300,7 @@ static void dce_v10_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v10_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; tmp = RREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset); @@ -2311,7 +2311,7 @@ static void dce_v10_0_hide_cursor(struct drm_crtc *crtc) static void dce_v10_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, @@ -2329,7 +2329,7 @@ static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2503,7 +2503,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = { static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2557,7 +2557,7 @@ static void dce_v10_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3345,7 +3345,7 @@ dce_v10_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v10_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3385,7 +3385,7 @@ static void dce_v10_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v10_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 01ce52266966a..0847fb6485de7 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -530,7 +530,7 @@ void dce_v11_0_disable_dce(struct amdgpu_device *adev) static void dce_v11_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1235,7 +1235,7 @@ static struct amdgpu_audio_pin *dce_v11_0_audio_get_pin(struct amdgpu_device *ad static void dce_v11_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1252,7 +1252,7 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1298,7 +1298,7 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1354,7 +1354,7 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1525,7 +1525,7 @@ static void dce_v11_0_audio_fini(struct amdgpu_device *adev) static void dce_v11_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1561,7 +1561,7 @@ static void dce_v11_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint8_t *frame = buffer + 3; @@ -1580,7 +1580,7 @@ static void dce_v11_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v11_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1611,7 +1611,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1791,7 +1791,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v11_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1864,7 +1864,7 @@ static void dce_v11_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1878,7 +1878,7 @@ static void dce_v11_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1892,7 +1892,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2137,7 +2137,7 @@ static void dce_v11_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); u32 tmp; @@ -2153,7 +2153,7 @@ static void dce_v11_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; u32 tmp; @@ -2283,7 +2283,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2364,7 +2364,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc) static void dce_v11_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2379,7 +2379,7 @@ static void dce_v11_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v11_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; tmp = RREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset); @@ -2390,7 +2390,7 @@ static void dce_v11_0_hide_cursor(struct drm_crtc *crtc) static void dce_v11_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, @@ -2408,7 +2408,7 @@ static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2582,7 +2582,7 @@ static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = { static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2636,7 +2636,7 @@ static void dce_v11_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -2706,7 +2706,7 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (!amdgpu_crtc->adjusted_clock) return -EINVAL; @@ -3471,7 +3471,7 @@ dce_v11_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v11_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3511,7 +3511,7 @@ static void dce_v11_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v11_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index cbddead3dafb1..e234d6fb49ab5 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -401,7 +401,7 @@ static void dce_v6_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1114,7 +1114,7 @@ static struct amdgpu_audio_pin *dce_v6_0_audio_get_pin(struct amdgpu_device *ade static void dce_v6_0_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1130,7 +1130,7 @@ static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1174,7 +1174,7 @@ static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1235,7 +1235,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1392,7 +1392,7 @@ static void dce_v6_0_audio_fini(struct amdgpu_device *adev) static void dce_v6_0_audio_set_vbi_packet(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1408,7 +1408,7 @@ static void dce_v6_0_audio_set_acr(struct drm_encoder *encoder, uint32_t clock, int bpc) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1446,7 +1446,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1488,7 +1488,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); int em = amdgpu_atombios_encoder_get_encoder_mode(encoder); u32 tmp; @@ -1522,7 +1522,7 @@ static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1566,7 +1566,7 @@ static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool mute) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1579,7 +1579,7 @@ static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool mute) static void dce_v6_0_audio_hdmi_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1616,7 +1616,7 @@ static void dce_v6_0_audio_hdmi_enable(struct drm_encoder *encoder, bool enable) static void dce_v6_0_audio_dp_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1645,7 +1645,7 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1714,7 +1714,7 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v6_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1788,7 +1788,7 @@ static void dce_v6_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1799,7 +1799,7 @@ static void dce_v6_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0); } @@ -1810,7 +1810,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2033,7 +2033,7 @@ static void dce_v6_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2048,7 +2048,7 @@ static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; @@ -2148,7 +2148,7 @@ static u32 dce_v6_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2177,7 +2177,7 @@ static u32 dce_v6_0_pick_pll(struct drm_crtc *crtc) static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2192,7 +2192,7 @@ static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v6_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) | @@ -2204,7 +2204,7 @@ static void dce_v6_0_hide_cursor(struct drm_crtc *crtc) static void dce_v6_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, upper_32_bits(amdgpu_crtc->cursor_addr)); @@ -2222,7 +2222,7 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; int w = amdgpu_crtc->cursor_width; @@ -2397,7 +2397,7 @@ static const struct drm_crtc_funcs dce_v6_0_crtc_funcs = { static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2447,7 +2447,7 @@ static void dce_v6_0_crtc_disable(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3146,7 +3146,7 @@ dce_v6_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v6_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3187,7 +3187,7 @@ static void dce_v6_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index fa0ad50b628c3..7cc8f7c4bc1ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -444,7 +444,7 @@ void dce_v8_0_disable_dce(struct amdgpu_device *adev) static void dce_v8_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1146,7 +1146,7 @@ static struct amdgpu_audio_pin *dce_v8_0_audio_get_pin(struct amdgpu_device *ade static void dce_v8_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 offset; @@ -1164,7 +1164,7 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1225,7 +1225,7 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1278,7 +1278,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder) static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 offset; @@ -1446,7 +1446,7 @@ static void dce_v8_0_audio_fini(struct amdgpu_device *adev) static void dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1469,7 +1469,7 @@ static void dce_v8_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint32_t offset = dig->afmt->offset; @@ -1489,7 +1489,7 @@ static void dce_v8_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v8_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1516,7 +1516,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1678,7 +1678,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v8_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1751,7 +1751,7 @@ static void dce_v8_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1765,7 +1765,7 @@ static void dce_v8_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1779,7 +1779,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2004,7 +2004,7 @@ static void dce_v8_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2018,7 +2018,7 @@ static void dce_v8_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; @@ -2140,7 +2140,7 @@ static u32 dce_v8_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2188,7 +2188,7 @@ static u32 dce_v8_0_pick_pll(struct drm_crtc *crtc) static void dce_v8_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2203,7 +2203,7 @@ static void dce_v8_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v8_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) | @@ -2213,7 +2213,7 @@ static void dce_v8_0_hide_cursor(struct drm_crtc *crtc) static void dce_v8_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, upper_32_bits(amdgpu_crtc->cursor_addr)); @@ -2230,7 +2230,7 @@ static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2404,7 +2404,7 @@ static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = { static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2458,7 +2458,7 @@ static void dce_v8_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3233,7 +3233,7 @@ dce_v8_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v8_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3273,7 +3273,7 @@ static void dce_v8_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v8_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index d5ff7b6331ff9..5bc784531e650 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -132,7 +132,7 @@ static const struct drm_crtc_funcs dce_virtual_crtc_funcs = { static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -697,7 +697,7 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, struct amdgpu_crtc, vblank_timer); struct drm_device *ddev = amdgpu_crtc->base.dev; - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 0aa1ac1accd6e..2eab808fffeb5 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -251,7 +251,7 @@ static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev, int i, count; ddev = dev_get_drvdata(dev); - adev = ddev->dev_private; + adev = drm_to_adev(ddev); count = 0; for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 075960864e120..a81c74f322093 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -544,7 +544,7 @@ static int dm_early_init(void* handle); static void amdgpu_dm_fbc_init(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_comressor_info *compressor = &adev->dm.compressor; struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector); struct drm_display_mode *mode; @@ -586,7 +586,7 @@ static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port, unsigned char *buf, int max_bytes) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_connector *connector; struct drm_connector_list_iter conn_iter; struct amdgpu_dm_connector *aconnector; @@ -625,7 +625,7 @@ static int amdgpu_dm_audio_component_bind(struct device *kdev, struct device *hda_kdev, void *data) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_audio_component *acomp = data; acomp->ops = &amdgpu_dm_audio_component_ops; @@ -639,7 +639,7 @@ static void amdgpu_dm_audio_component_unbind(struct device *kdev, struct device *hda_kdev, void *data) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_audio_component *acomp = data; acomp->ops = NULL; @@ -2050,7 +2050,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) return; conn_base = &aconnector->base; - adev = conn_base->dev->dev_private; + adev = drm_to_adev(conn_base->dev); dm = &adev->dm; caps = &dm->backlight_caps; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; @@ -2239,7 +2239,7 @@ static void handle_hpd_irq(void *param) struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; #ifdef CONFIG_DRM_AMD_DC_HDCP - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); #endif /* @@ -2372,7 +2372,7 @@ static void handle_hpd_rx_irq(void *param) enum dc_connection_type new_connection_type = dc_connection_none; #ifdef CONFIG_DRM_AMD_DC_HDCP union hpd_irq_data hpd_irq_data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); memset(&hpd_irq_data, 0, sizeof(hpd_irq_data)); #endif @@ -2793,7 +2793,7 @@ static int dm_atomic_get_state(struct drm_atomic_state *state, struct dm_atomic_state **dm_state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct drm_private_state *priv_state; @@ -2813,7 +2813,7 @@ static struct dm_atomic_state * dm_atomic_get_new_state(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct drm_private_obj *obj; struct drm_private_state *new_obj_state; @@ -3388,7 +3388,7 @@ static ssize_t s3_debug_store(struct device *device, int ret; int s3_state; struct drm_device *drm_dev = dev_get_drvdata(device); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); ret = kstrtoint(buf, 0, &s3_state); @@ -4785,7 +4785,7 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable) { enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int rc; irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst; @@ -4801,7 +4801,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) { enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); int rc = 0; @@ -4878,7 +4878,7 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, uint64_t val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_connector_state *dm_old_state = to_dm_connector_state(connector->state); struct dm_connector_state *dm_new_state = @@ -4933,7 +4933,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, uint64_t *val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_connector_state *dm_state = to_dm_connector_state(state); int ret = -EINVAL; @@ -4983,7 +4983,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; - struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ @@ -5168,7 +5168,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct dc_stream_state *old_stream) { struct drm_connector *connector = &aconnector->base; - struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct dc_stream_state *stream; const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8; @@ -5445,7 +5445,7 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc, static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dc *dc = adev->dm.dc; struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); int ret = -EINVAL; @@ -5817,7 +5817,7 @@ static int dm_plane_helper_check_state(struct drm_plane_state *state, static int dm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - struct amdgpu_device *adev = plane->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(plane->dev); struct dc *dc = adev->dm.dc; struct dm_plane_state *dm_plane_state; struct dc_scaling_info scaling_info; @@ -6292,7 +6292,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, struct dc_link *link, int link_index) { - struct amdgpu_device *adev = dm->ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dm->ddev); /* * Some of the properties below require access to state, like bpc. @@ -6543,7 +6543,7 @@ static int amdgpu_dm_encoder_init(struct drm_device *dev, struct amdgpu_encoder *aencoder, uint32_t link_index) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int res = drm_encoder_init(dev, &aencoder->base, @@ -6728,7 +6728,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, static void handle_cursor_update(struct drm_plane *plane, struct drm_plane_state *old_plane_state) { - struct amdgpu_device *adev = plane->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(plane->dev); struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; @@ -7265,9 +7265,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * on some ASICs). */ if (dm_old_crtc_state->active_planes != acrtc_state->active_planes) - dm_update_pflip_irq_state( - (struct amdgpu_device *)dev->dev_private, - acrtc_attach); + dm_update_pflip_irq_state(drm_to_adev(dev), + acrtc_attach); if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && @@ -7297,7 +7296,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, static void amdgpu_dm_commit_audio(struct drm_device *dev, struct drm_atomic_state *state) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; @@ -7389,7 +7388,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int i; /* @@ -7436,7 +7435,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct dm_atomic_state *dm_state; struct dc_state *dc_state = NULL, *dc_state_temp = NULL; @@ -8410,7 +8409,7 @@ static int dm_update_plane_state(struct dc *dc, plane->base.id, new_plane_crtc->base.id); ret = fill_dc_plane_attributes( - new_plane_crtc->dev->dev_private, + drm_to_adev(new_plane_crtc->dev), dc_new_plane_state, new_plane_state, new_crtc_state); @@ -8508,7 +8507,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_atomic_state *dm_state = NULL; struct dc *dc = adev->dm.dc; struct drm_connector *connector; @@ -8861,7 +8860,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct dm_connector_state *dm_con_state = NULL; struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); bool freesync_capable = false; if (!connector->state) { @@ -9075,7 +9074,7 @@ static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dc *dc = adev->dm.dc; int i; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index b321ff654df42..5df05f0d18bc9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -308,8 +308,7 @@ static int __set_input_tf(struct dc_transfer_func *func, int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) { struct dc_stream_state *stream = crtc->stream; - struct amdgpu_device *adev = - (struct amdgpu_device *)crtc->base.state->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev); bool has_rom = adev->asic_type <= CHIP_RAVEN; struct drm_color_ctm *ctm = NULL; const struct drm_color_lut *degamma_lut, *regamma_lut; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index eaad9099bc0b4..d0699e98db929 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -101,7 +101,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, struct dm_crtc_state *dm_crtc_state, enum amdgpu_dm_pipe_crc_source source) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dc_stream_state *stream_state = dm_crtc_state->stream; bool enable = amdgpu_dm_is_valid_crc_source(source); int ret = 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index ae6b1313403e9..5703a68d8302d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2127,7 +2127,7 @@ static int current_backlight_read(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; unsigned int backlight = dc_link_get_backlight_level(dm->backlight_link); @@ -2145,7 +2145,7 @@ static int target_backlight_read(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; unsigned int backlight = dc_link_get_target_backlight_pwm(dm->backlight_link); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index a222335133e0e..8aba40345b54e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -241,7 +241,7 @@ dm_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *connector_state) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); return &adev->dm.mst_encoders[acrtc->crtc_id].base; @@ -337,7 +337,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; int i; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index e469de005451b..ea00c4b0e74b1 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -117,7 +117,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type pm; int ret; @@ -155,7 +155,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state; int ret; @@ -261,7 +261,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level = 0xff; int ret; @@ -302,7 +302,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level = 0xff; int ret = 0; @@ -407,7 +407,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct pp_states_info data; int i, buf_len, ret; @@ -449,7 +449,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct pp_states_info data; struct smu_context *smu = &adev->smu; enum amd_pm_state_type pm = 0; @@ -494,7 +494,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); if (amdgpu_in_reset(adev)) return -EPERM; @@ -511,7 +511,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state = 0; unsigned long idx; int ret; @@ -572,7 +572,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); char *table = NULL; int size, ret; @@ -617,7 +617,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret = 0; if (amdgpu_in_reset(adev)) @@ -763,7 +763,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t parameter_size = 0; long parameter[64]; @@ -863,7 +863,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -917,7 +917,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t featuremask; int ret; @@ -962,7 +962,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1023,7 +1023,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1091,7 +1091,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1127,7 +1127,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1159,7 +1159,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t mask = 0; int ret; @@ -1195,7 +1195,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1227,7 +1227,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1265,7 +1265,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1297,7 +1297,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1335,7 +1335,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1367,7 +1367,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1405,7 +1405,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1437,7 +1437,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1475,7 +1475,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t value = 0; int ret; @@ -1505,7 +1505,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; long int value; @@ -1548,7 +1548,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t value = 0; int ret; @@ -1578,7 +1578,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; long int value; @@ -1641,7 +1641,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1675,7 +1675,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, { int ret; struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t parameter_size = 0; long parameter[64]; char *sub_str, buf_cpy[128]; @@ -1746,7 +1746,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int r, value, size = sizeof(value); if (amdgpu_in_reset(adev)) @@ -1784,7 +1784,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int r, value, size = sizeof(value); if (amdgpu_in_reset(adev)) @@ -1826,7 +1826,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t count0 = 0, count1 = 0; int ret; @@ -1869,7 +1869,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); if (amdgpu_in_reset(adev)) return -EPERM; @@ -1900,7 +1900,7 @@ static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", adev->ddev->unique, @@ -1914,7 +1914,7 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); long throttling_logging_interval; unsigned long flags; int ret = 0; @@ -1964,7 +1964,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); void *gpu_metrics; ssize_t size = 0; int ret; @@ -3554,7 +3554,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 flags = 0; int r; -- GitLab From 4a580877bdcb837e7a3754ae20798dcfccb44e80 Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Mon, 24 Aug 2020 12:29:45 -0400 Subject: [PATCH 0592/1494] drm/amdgpu: Get DRM dev from adev by inline-f Add a static inline adev_to_drm() to obtain the DRM device pointer from an amdgpu_device pointer. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 6 +- .../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 178 ++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 30 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 20 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 18 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 2 +- .../gpu/drm/amd/amdgpu/atombios_encoders.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 36 ++-- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 84 ++++---- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 6 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 194 +++++++++--------- 33 files changed, 428 insertions(+), 423 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index f33a1f372681a..9d93b3170cd62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -991,6 +991,11 @@ static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) return ddev->dev_private; } +static inline struct drm_device *adev_to_drm(struct amdgpu_device *adev) +{ + return adev->ddev; +} + static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) { return container_of(bdev, struct amdgpu_device, mman.bdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 913c8f0513bd3..4a93b880c6bfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -463,11 +463,11 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev, if (req.pending & ATIF_DGPU_DISPLAY_EVENT) { if (adev->flags & AMD_IS_PX) { - pm_runtime_get_sync(adev->ddev->dev); + pm_runtime_get_sync(adev_to_drm(adev)->dev); /* Just fire off a uevent and let userspace tell us what to do */ - drm_helper_hpd_irq_event(adev->ddev); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + drm_helper_hpd_irq_event(adev_to_drm(adev)); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); } } /* TODO: check other events */ @@ -817,7 +817,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) struct drm_encoder *tmp; /* Find the encoder controlling the brightness */ - list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list, + list_for_each_entry(tmp, &adev_to_drm(adev)->mode_config.encoder_list, head) { struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index b74846fc39338..d58148f455dd8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -119,7 +119,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) .gpuvm_size = min(adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT, AMDGPU_GMC_HOLE_START), - .drm_render_minor = adev->ddev->render->index, + .drm_render_minor = adev_to_drm(adev)->render->index, .sdma_doorbell_idx = adev->doorbell_index.sdma_engine, }; @@ -160,7 +160,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) adev->doorbell_index.last_non_cp; } - kgd2kfd_device_init(adev->kfd.dev, adev->ddev, &gpu_resources); + kgd2kfd_device_init(adev->kfd.dev, adev_to_drm(adev), &gpu_resources); } } @@ -479,7 +479,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, goto out_put; obj = dma_buf->priv; - if (obj->dev->driver != adev->ddev->driver) + if (obj->dev->driver != adev_to_drm(adev)->driver) /* Can't handle buffers from different drivers */ goto out_put; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 662cc414ceec7..469352e2d6ecf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -148,7 +148,7 @@ void amdgpu_atombios_i2c_init(struct amdgpu_device *adev) if (i2c.valid) { sprintf(stmp, "0x%x", i2c.i2c_id); - adev->i2c_bus[i] = amdgpu_i2c_create(adev->ddev, &i2c, stmp); + adev->i2c_bus[i] = amdgpu_i2c_create(adev_to_drm(adev), &i2c, stmp); } gpio = (ATOM_GPIO_I2C_ASSIGMENT *) ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT)); @@ -541,7 +541,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * } } - amdgpu_link_encoder_connector(adev->ddev); + amdgpu_link_encoder_connector(adev_to_drm(adev)); return true; } @@ -1995,7 +1995,7 @@ int amdgpu_atombios_init(struct amdgpu_device *adev) return -ENOMEM; adev->mode_info.atom_card_info = atom_card_info; - atom_card_info->dev = adev->ddev; + atom_card_info->dev = adev_to_drm(adev); atom_card_info->reg_read = cail_reg_read; atom_card_info->reg_write = cail_reg_write; /* needed for iio ops */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 3bce625189ce4..3d7508788eb59 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -1521,7 +1521,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, struct amdgpu_hpd *hpd, struct amdgpu_router *router) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; struct amdgpu_connector *amdgpu_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 37eb8e77d61ef..abe0c2729e1cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -69,8 +69,8 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev, adev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) drm_debugfs_create_files(files, nfiles, - adev->ddev->primary->debugfs_root, - adev->ddev->primary); + adev_to_drm(adev)->primary->debugfs_root, + adev_to_drm(adev)->primary); #endif return 0; } @@ -151,7 +151,7 @@ static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev) init_waitqueue_head(&adev->autodump.gpu_hang); debugfs_create_file("amdgpu_autodump", 0600, - adev->ddev->primary->debugfs_root, + adev_to_drm(adev)->primary->debugfs_root, adev, &autodump_debug_fops); } @@ -227,23 +227,23 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, *pos &= (1UL << 22) - 1; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } if (use_bank) { if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return -EINVAL; } @@ -292,8 +292,8 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, if (pm_pg_lock) mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -340,15 +340,15 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -358,8 +358,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, value = RREG32_PCIE(*pos >> 2); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -370,8 +370,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -399,15 +399,15 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -416,8 +416,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -430,8 +430,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -459,15 +459,15 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -477,8 +477,8 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, value = RREG32_DIDT(*pos >> 2); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -489,8 +489,8 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -518,15 +518,15 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -535,8 +535,8 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -549,8 +549,8 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -578,15 +578,15 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -596,8 +596,8 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, value = RREG32_SMC(*pos); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -608,8 +608,8 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -637,15 +637,15 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -654,8 +654,8 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -668,8 +668,8 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -796,22 +796,22 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, valuesize = sizeof(values); - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) { amdgpu_virt_disable_access_debugfs(adev); @@ -878,15 +878,15 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, wave = (*pos & GENMASK_ULL(36, 31)) >> 31; simd = (*pos & GENMASK_ULL(44, 37)) >> 37; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -901,8 +901,8 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (!x) { amdgpu_virt_disable_access_debugfs(adev); @@ -976,7 +976,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, if (!data) return -ENOMEM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) goto err; @@ -999,8 +999,8 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); while (size) { uint32_t value; @@ -1022,7 +1022,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, return result; err: - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); kfree(data); return r; } @@ -1047,9 +1047,9 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1058,8 +1058,8 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1071,8 +1071,8 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return result; } @@ -1096,7 +1096,7 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) return r; @@ -1105,15 +1105,15 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, r = amdgpu_get_gfx_off_status(adev, &value); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1123,8 +1123,8 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return result; } @@ -1216,7 +1216,7 @@ static const char *debugfs_regs_names[] = { */ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) { - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; unsigned int i; @@ -1241,7 +1241,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1302,7 +1302,7 @@ static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1323,7 +1323,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1527,9 +1527,9 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val) if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return -EINVAL; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -1542,8 +1542,8 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val) return 0; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (ret) return -EINVAL; @@ -1563,7 +1563,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) adev->debugfs_preempt = debugfs_create_file("amdgpu_preempt_ib", 0600, - adev->ddev->primary->debugfs_root, adev, + adev_to_drm(adev)->primary->debugfs_root, adev, &fops_ib_preempt); if (!(adev->debugfs_preempt)) { DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); @@ -1572,7 +1572,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) adev->smu.debugfs_sclk = debugfs_create_file("amdgpu_force_sclk", 0200, - adev->ddev->primary->debugfs_root, adev, + adev_to_drm(adev)->primary->debugfs_root, adev, &fops_sclk_set); if (!(adev->smu.debugfs_sclk)) { DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 06aa0a98f4a51..afe8cb37d5b46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1509,7 +1509,7 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) adev->enable_virtual_display = false; if (amdgpu_virtual_display) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); const char *pci_address_name = pci_name(ddev->pdev); char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname; @@ -2872,13 +2872,13 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { task_barrier_enter(&hive->tb); - adev->asic_reset_res = amdgpu_device_baco_enter(adev->ddev); + adev->asic_reset_res = amdgpu_device_baco_enter(adev_to_drm(adev)); if (adev->asic_reset_res) goto fail; task_barrier_exit(&hive->tb); - adev->asic_reset_res = amdgpu_device_baco_exit(adev->ddev); + adev->asic_reset_res = amdgpu_device_baco_exit(adev_to_drm(adev)); if (adev->asic_reset_res) goto fail; @@ -2894,7 +2894,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) fail: if (adev->asic_reset_res) DRM_WARN("ASIC reset failed with error, %d for drm dev, %s", - adev->asic_reset_res, adev->ddev->unique); + adev->asic_reset_res, adev_to_drm(adev)->unique); amdgpu_put_xgmi_hive(hive); } @@ -3243,7 +3243,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, } /* init the mode config */ - drm_mode_config_init(adev->ddev); + drm_mode_config_init(adev_to_drm(adev)); r = amdgpu_device_ip_init(adev); if (r) { @@ -3385,9 +3385,9 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_irq_disable_all(adev); if (adev->mode_info.mode_config_initialized){ if (!amdgpu_device_has_dc_support(adev)) - drm_helper_force_disable_all(adev->ddev); + drm_helper_force_disable_all(adev_to_drm(adev)); else - drm_atomic_helper_shutdown(adev->ddev); + drm_atomic_helper_shutdown(adev_to_drm(adev)); } amdgpu_fence_driver_fini(adev); if (adev->pm_sysfs_en) @@ -3411,7 +3411,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_has_atpx_dgpu_power_cntl()) && !pci_is_thunderbolt_attached(adev->pdev)) vga_switcheroo_unregister_client(adev->pdev); - if (amdgpu_device_supports_boco(adev->ddev)) + if (amdgpu_device_supports_boco(adev_to_drm(adev))) vga_switcheroo_fini_domain_pm_ops(adev->dev); vga_client_register(adev->pdev, NULL, NULL, NULL); if (adev->rio_mem) @@ -4079,7 +4079,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, if (r) { dev_err(tmp_adev->dev, "ASIC reset failed with error, %d for drm dev, %s", - r, tmp_adev->ddev->unique); + r, adev_to_drm(tmp_adev)->unique); break; } } @@ -4452,7 +4452,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /*TODO Should we stop ?*/ if (r) { dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ", - r, tmp_adev->ddev->unique); + r, adev_to_drm(tmp_adev)->unique); tmp_adev->asic_reset_res = r; } } @@ -4488,7 +4488,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, } if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { - drm_helper_resume_force_mode(tmp_adev->ddev); + drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); } tmp_adev->asic_reset_res = 0; @@ -4665,7 +4665,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev) struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - if (!amdgpu_device_supports_baco(adev->ddev)) + if (!amdgpu_device_supports_baco(adev_to_drm(adev))) return -ENOTSUPP; if (ras && ras->supported) @@ -4680,7 +4680,7 @@ int amdgpu_device_baco_exit(struct drm_device *dev) struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); int ret = 0; - if (!amdgpu_device_supports_baco(adev->ddev)) + if (!amdgpu_device_supports_baco(adev_to_drm(adev))) return -ENOTSUPP; ret = amdgpu_dpm_baco_exit(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e7ebc7bb70de8..c81206e6096f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -93,7 +93,7 @@ static void amdgpu_display_flip_work_func(struct work_struct *__work) * targeted by the flip */ if (amdgpu_crtc->enabled && - (amdgpu_display_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, + (amdgpu_display_get_crtc_scanoutpos(adev_to_drm(adev), work->crtc_id, 0, &vpos, &hpos, NULL, NULL, &crtc->hwmode) & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == @@ -619,51 +619,51 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) int sz; adev->mode_info.coherent_mode_property = - drm_property_create_range(adev->ddev, 0 , "coherent", 0, 1); + drm_property_create_range(adev_to_drm(adev), 0, "coherent", 0, 1); if (!adev->mode_info.coherent_mode_property) return -ENOMEM; adev->mode_info.load_detect_property = - drm_property_create_range(adev->ddev, 0, "load detection", 0, 1); + drm_property_create_range(adev_to_drm(adev), 0, "load detection", 0, 1); if (!adev->mode_info.load_detect_property) return -ENOMEM; - drm_mode_create_scaling_mode_property(adev->ddev); + drm_mode_create_scaling_mode_property(adev_to_drm(adev)); sz = ARRAY_SIZE(amdgpu_underscan_enum_list); adev->mode_info.underscan_property = - drm_property_create_enum(adev->ddev, 0, - "underscan", - amdgpu_underscan_enum_list, sz); + drm_property_create_enum(adev_to_drm(adev), 0, + "underscan", + amdgpu_underscan_enum_list, sz); adev->mode_info.underscan_hborder_property = - drm_property_create_range(adev->ddev, 0, - "underscan hborder", 0, 128); + drm_property_create_range(adev_to_drm(adev), 0, + "underscan hborder", 0, 128); if (!adev->mode_info.underscan_hborder_property) return -ENOMEM; adev->mode_info.underscan_vborder_property = - drm_property_create_range(adev->ddev, 0, - "underscan vborder", 0, 128); + drm_property_create_range(adev_to_drm(adev), 0, + "underscan vborder", 0, 128); if (!adev->mode_info.underscan_vborder_property) return -ENOMEM; sz = ARRAY_SIZE(amdgpu_audio_enum_list); adev->mode_info.audio_property = - drm_property_create_enum(adev->ddev, 0, + drm_property_create_enum(adev_to_drm(adev), 0, "audio", amdgpu_audio_enum_list, sz); sz = ARRAY_SIZE(amdgpu_dither_enum_list); adev->mode_info.dither_property = - drm_property_create_enum(adev->ddev, 0, + drm_property_create_enum(adev_to_drm(adev), 0, "dither", amdgpu_dither_enum_list, sz); if (amdgpu_device_has_dc_support(adev)) { adev->mode_info.abm_level_property = - drm_property_create_range(adev->ddev, 0, - "abm level", 0, 4); + drm_property_create_range(adev_to_drm(adev), 0, + "abm level", 0, 4); if (!adev->mode_info.abm_level_property) return -ENOMEM; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index db731f573f982..e2c2eb45a7934 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -135,7 +135,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | AMDGPU_GEM_CREATE_VRAM_CLEARED; - info = drm_get_format_info(adev->ddev, mode_cmd); + info = drm_get_format_info(adev_to_drm(adev), mode_cmd); cpp = info->cpp[0]; /* need to align pitch with crtc limits */ @@ -231,7 +231,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, goto out; } - ret = amdgpu_display_framebuffer_init(adev->ddev, &rfbdev->rfb, + ret = amdgpu_display_framebuffer_init(adev_to_drm(adev), &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); @@ -254,7 +254,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, drm_fb_helper_fill_info(info, &rfbdev->helper, sizes); /* setup aperture base/size for vesafb takeover */ - info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base; + info->apertures->ranges[0].base = adev_to_drm(adev)->mode_config.fb_base; info->apertures->ranges[0].size = adev->gmc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ @@ -270,7 +270,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); - vga_switcheroo_client_fb_set(adev->ddev->pdev, info); + vga_switcheroo_client_fb_set(adev_to_drm(adev)->pdev, info); return 0; out: @@ -318,7 +318,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) return 0; /* don't init fbdev if there are no connectors */ - if (list_empty(&adev->ddev->mode_config.connector_list)) + if (list_empty(&adev_to_drm(adev)->mode_config.connector_list)) return 0; /* select 8 bpp console on low vram cards */ @@ -332,10 +332,10 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) rfbdev->adev = adev; adev->mode_info.rfbdev = rfbdev; - drm_fb_helper_prepare(adev->ddev, &rfbdev->helper, - &amdgpu_fb_helper_funcs); + drm_fb_helper_prepare(adev_to_drm(adev), &rfbdev->helper, + &amdgpu_fb_helper_funcs); - ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper); + ret = drm_fb_helper_init(adev_to_drm(adev), &rfbdev->helper); if (ret) { kfree(rfbdev); return ret; @@ -343,7 +343,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) /* disable all the possible outputs/crtcs before entering KMS mode */ if (!amdgpu_device_has_dc_support(adev)) - drm_helper_disable_unused_functions(adev->ddev); + drm_helper_disable_unused_functions(adev_to_drm(adev)); drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; @@ -354,7 +354,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev) if (!adev->mode_info.rfbdev) return; - amdgpu_fbdev_destroy(adev->ddev, adev->mode_info.rfbdev); + amdgpu_fbdev_destroy(adev_to_drm(adev), adev->mode_info.rfbdev); kfree(adev->mode_info.rfbdev); adev->mode_info.rfbdev = NULL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index cfccd3d33341b..fe2d495d08ab0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -155,7 +155,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, seq); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, flags | AMDGPU_FENCE_FLAG_INT); - pm_runtime_get_noresume(adev->ddev->dev); + pm_runtime_get_noresume(adev_to_drm(adev)->dev); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; if (unlikely(rcu_dereference_protected(*ptr, 1))) { struct dma_fence *old; @@ -284,8 +284,8 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) BUG(); dma_fence_put(fence); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); } while (last_seq != seq); return true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 8371a87240873..f4c2e2e75b8f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -93,7 +93,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, void amdgpu_gem_force_release(struct amdgpu_device *adev) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct drm_file *file; mutex_lock(&ddev->filelist_mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index 411c84194f97c..47cad23a6b9e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c @@ -253,7 +253,7 @@ void amdgpu_i2c_add(struct amdgpu_device *adev, const struct amdgpu_i2c_bus_rec *rec, const char *name) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); int i; for (i = 0; i < AMDGPU_MAX_I2C_BUS; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 508cb34a91428..300ac73b47382 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -85,7 +85,7 @@ static void amdgpu_hotplug_work_func(struct work_struct *work) { struct amdgpu_device *adev = container_of(work, struct amdgpu_device, hotplug_work); - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; struct drm_connector_list_iter iter; @@ -268,9 +268,9 @@ int amdgpu_irq_init(struct amdgpu_device *adev) if (!adev->enable_virtual_display) /* Disable vblank IRQs aggressively for power-saving */ /* XXX: can this be enabled for DC? */ - adev->ddev->vblank_disable_immediate = true; + adev_to_drm(adev)->vblank_disable_immediate = true; - r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); + r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc); if (r) return r; @@ -284,14 +284,14 @@ int amdgpu_irq_init(struct amdgpu_device *adev) adev->irq.installed = true; /* Use vector 0 for MSI-X */ - r = drm_irq_install(adev->ddev, pci_irq_vector(adev->pdev, 0)); + r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0)); if (r) { adev->irq.installed = false; if (!amdgpu_device_has_dc_support(adev)) flush_work(&adev->hotplug_work); return r; } - adev->ddev->max_vblank_count = 0x00ffffff; + adev_to_drm(adev)->max_vblank_count = 0x00ffffff; DRM_DEBUG("amdgpu: irq initialized.\n"); return 0; @@ -311,7 +311,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev) unsigned i, j; if (adev->irq.installed) { - drm_irq_uninstall(adev->ddev); + drm_irq_uninstall(adev_to_drm(adev)); adev->irq.installed = false; if (adev->irq.msi_enabled) pci_free_irq_vectors(adev->pdev); @@ -522,7 +522,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return -ENOENT; if (type >= src->num_types) @@ -552,7 +552,7 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return -ENOENT; if (type >= src->num_types) @@ -583,7 +583,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return false; if (type >= src->num_types) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 3080b56441211..92fbbfb16cff7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -555,7 +555,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; - drm_gem_private_object_init(adev->ddev, &bo->tbo.base, size); + drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); INIT_LIST_HEAD(&bo->shadow_list); bo->vm_bo = NULL; bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c index 1311d6aec5d4b..69af462db34df 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c @@ -226,7 +226,7 @@ static int init_pmu_by_type(struct amdgpu_device *adev, pmu_entry->pmu.attr_groups = attr_groups; pmu_entry->pmu_perf_type = pmu_perf_type; snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d", - pmu_file_prefix, adev->ddev->primary->index); + pmu_file_prefix, adev_to_drm(adev)->primary->index); ret = perf_pmu_register(&pmu_entry->pmu, pmu_name, -1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c index 87cbc9011b2d6..8da5356c36f17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c @@ -46,7 +46,7 @@ static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; struct ta_rap_shared_memory *rap_shared_mem; struct ta_rap_cmd_output_data *rap_cmd_output; - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); uint32_t op; int ret; @@ -116,7 +116,7 @@ static const struct file_operations amdgpu_rap_debugfs_ops = { void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) { #if defined(CONFIG_DEBUG_FS) - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; if (!adev->psp.rap_context.rap_initialized) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index ec377a8147a21..9b718749919a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1197,7 +1197,7 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev) static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; con->dir = debugfs_create_dir(RAS_FS_NAME, minor->debugfs_root); debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 6d4fc79bf84aa..15ee13c3bd9e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -420,7 +420,7 @@ int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring) { #if defined(CONFIG_DEBUG_FS) - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; char name[32]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 245d9352ef511..798985b946851 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1921,8 +1921,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) /* No others user of address space so set it to 0 */ r = ttm_bo_device_init(&adev->mman.bdev, &amdgpu_bo_driver, - adev->ddev->anon_inode->i_mapping, - adev->ddev->vma_offset_manager, + adev_to_drm(adev)->anon_inode->i_mapping, + adev_to_drm(adev)->vma_offset_manager, dma_addressing_limited(adev->dev)); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); @@ -2606,7 +2606,7 @@ int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) #if defined(CONFIG_DEBUG_FS) unsigned count; - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; for (count = 0; count < ARRAY_SIZE(ttm_debugfs_entries); count++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index d84649b4d51a0..f76961d172460 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -45,7 +45,7 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) if (adev->mode_info.num_crtc == 0) adev->mode_info.num_crtc = 1; adev->enable_virtual_display = true; - adev->ddev->driver->driver_features &= ~DRIVER_ATOMIC; + adev_to_drm(adev)->driver->driver_features &= ~DRIVER_ATOMIC; adev->cg_flags = 0; adev->pg_flags = 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index bda3f709a8e17..1162913c8bf42 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -294,7 +294,7 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, remove_link: - sysfs_remove_link(&adev->dev->kobj, adev->ddev->unique); + sysfs_remove_link(&adev->dev->kobj, adev_to_drm(adev)->unique); remove_file: device_remove_file(adev->dev, &dev_attr_xgmi_device_id); diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index a7466f3562bc7..8339c8c3a328f 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -1673,7 +1673,7 @@ amdgpu_atombios_encoder_set_crtc_source(struct drm_encoder *encoder) void amdgpu_atombios_encoder_init_dig(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 65301a56344b2..5963cbe0d455c 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -328,7 +328,7 @@ static void dce_v10_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -383,7 +383,7 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2701,7 +2701,7 @@ static int dce_v10_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v10_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v10_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2709,8 +2709,8 @@ static int dce_v10_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = 128; amdgpu_crtc->max_cursor_height = 128; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; switch (amdgpu_crtc->crtc_id) { case 0: @@ -2792,24 +2792,24 @@ static int dce_v10_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2819,7 +2819,7 @@ static int dce_v10_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2832,7 +2832,7 @@ static int dce_v10_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2844,13 +2844,13 @@ static int dce_v10_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v10_0_audio_fini(adev); dce_v10_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3157,14 +3157,14 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3176,7 +3176,7 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3245,7 +3245,7 @@ static int dce_v10_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); @@ -3485,7 +3485,7 @@ static void dce_v10_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 0847fb6485de7..1954472c8e8f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -346,7 +346,7 @@ static void dce_v11_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -400,7 +400,7 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2809,7 +2809,7 @@ static int dce_v11_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v11_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v11_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2817,8 +2817,8 @@ static int dce_v11_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = 128; amdgpu_crtc->max_cursor_height = 128; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; switch (amdgpu_crtc->crtc_id) { case 0: @@ -2913,24 +2913,24 @@ static int dce_v11_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ @@ -2941,7 +2941,7 @@ static int dce_v11_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2954,7 +2954,7 @@ static int dce_v11_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2966,13 +2966,13 @@ static int dce_v11_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v11_0_audio_fini(adev); dce_v11_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3283,14 +3283,14 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev, if(amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3302,7 +3302,7 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev, if(works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3372,7 +3372,7 @@ static int dce_v11_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); @@ -3611,7 +3611,7 @@ static void dce_v11_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e234d6fb49ab5..3a44753a80d10 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -279,7 +279,7 @@ static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -324,7 +324,7 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2591,7 +2591,7 @@ static int dce_v6_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v6_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v6_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2599,8 +2599,8 @@ static int dce_v6_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = CURSOR_WIDTH; amdgpu_crtc->max_cursor_height = CURSOR_HEIGHT; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; amdgpu_crtc->crtc_offset = crtc_offsets[amdgpu_crtc->crtc_id]; @@ -2669,20 +2669,20 @@ static int dce_v6_0_sw_init(void *handle) adev->mode_info.mode_config_initialized = true; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2693,7 +2693,7 @@ static int dce_v6_0_sw_init(void *handle) ret = amdgpu_atombios_get_connector_info_from_object_table(adev); if (ret) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2706,7 +2706,7 @@ static int dce_v6_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); return r; } @@ -2717,12 +2717,12 @@ static int dce_v6_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v6_0_audio_fini(adev); dce_v6_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -2967,7 +2967,7 @@ static int dce_v6_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); break; @@ -3036,14 +3036,14 @@ static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3055,7 +3055,7 @@ static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3297,7 +3297,7 @@ static void dce_v6_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 7cc8f7c4bc1ff..3603e5f130775 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -273,7 +273,7 @@ static void dce_v8_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -318,7 +318,7 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2609,7 +2609,7 @@ static int dce_v8_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v8_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v8_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2617,8 +2617,8 @@ static int dce_v8_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = CIK_CURSOR_WIDTH; amdgpu_crtc->max_cursor_height = CIK_CURSOR_HEIGHT; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; amdgpu_crtc->crtc_offset = crtc_offsets[amdgpu_crtc->crtc_id]; @@ -2689,24 +2689,24 @@ static int dce_v8_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2716,7 +2716,7 @@ static int dce_v8_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2729,7 +2729,7 @@ static int dce_v8_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2741,13 +2741,13 @@ static int dce_v8_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v8_0_audio_fini(adev); dce_v8_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3057,7 +3057,7 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); break; @@ -3126,14 +3126,14 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3145,7 +3145,7 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3373,7 +3373,7 @@ static void dce_v8_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 5bc784531e650..cc93577dee03f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -235,7 +235,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -374,24 +374,24 @@ static int dce_virtual_sw_init(void *handle) if (r) return r; - adev->ddev->max_vblank_count = 0; + adev_to_drm(adev)->max_vblank_count = 0; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs, encoders, connectors */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -403,7 +403,7 @@ static int dce_virtual_sw_init(void *handle) return r; } - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -415,9 +415,9 @@ static int dce_virtual_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); /* clear crtcs pointer to avoid dce irq finish routine access freed data */ memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS); adev->mode_info.mode_config_initialized = false; @@ -602,7 +602,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, if (!encoder) return -ENOMEM; encoder->possible_crtcs = 1 << index; - drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, + drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs, DRM_MODE_ENCODER_VIRTUAL, NULL); drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); @@ -613,7 +613,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, } /* add a new connector */ - drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, + drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; @@ -663,14 +663,14 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -682,7 +682,7 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); amdgpu_bo_unref(&works->old_abo); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a81c74f322093..ec6710f6c8736 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -268,7 +268,7 @@ static struct amdgpu_crtc * get_crtc_by_otg_inst(struct amdgpu_device *adev, int otg_inst) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; @@ -320,7 +320,7 @@ static void dm_pflip_high_irq(void *interrupt_params) return; } - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", @@ -328,7 +328,7 @@ static void dm_pflip_high_irq(void *interrupt_params) AMDGPU_FLIP_SUBMITTED, amdgpu_crtc->crtc_id, amdgpu_crtc); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return; } @@ -380,7 +380,7 @@ static void dm_pflip_high_irq(void *interrupt_params) e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base); e->pipe = amdgpu_crtc->crtc_id; - list_add_tail(&e->base.link, &adev->ddev->vblank_event_list); + list_add_tail(&e->base.link, &adev_to_drm(adev)->vblank_event_list); e = NULL; } @@ -393,7 +393,7 @@ static void dm_pflip_high_irq(void *interrupt_params) amdgpu_get_vblank_counter_kms(&amdgpu_crtc->base); amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n", amdgpu_crtc->crtc_id, amdgpu_crtc, @@ -429,7 +429,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) /* BTR processing for pre-DCE12 ASICs */ if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI) { - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); mod_freesync_handle_v_update( adev->dm.freesync_module, acrtc_state->stream, @@ -439,7 +439,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) adev->dm.dc, acrtc_state->stream, &acrtc_state->vrr_params.adjust); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } } } @@ -489,7 +489,7 @@ static void dm_crtc_high_irq(void *interrupt_params) if (adev->family < AMDGPU_FAMILY_AI) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); if (acrtc_state->stream && acrtc_state->vrr_params.supported && acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { @@ -522,7 +522,7 @@ static void dm_crtc_high_irq(void *interrupt_params) acrtc->pflip_status = AMDGPU_FLIP_NONE; } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static int dm_set_clockgating_state(void *handle, @@ -850,7 +850,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) #endif int r; - adev->dm.ddev = adev->ddev; + adev->dm.ddev = adev_to_drm(adev); adev->dm.adev = adev; /* Zero all the fields */ @@ -986,10 +986,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ - adev->ddev->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; - adev->ddev->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; + adev_to_drm(adev)->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; + adev_to_drm(adev)->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; - if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { + if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) { DRM_ERROR( "amdgpu: failed to initialize sw for display support.\n"); goto error; @@ -1390,7 +1390,7 @@ static int dm_late_init(void *handle) bool ret = true; if (!adev->dm.fw_dmcu) - return detect_mst_link_for_all_connectors(adev->ddev); + return detect_mst_link_for_all_connectors(adev_to_drm(adev)); dmcu = adev->dm.dc->res_pool->dmcu; @@ -1420,7 +1420,7 @@ static int dm_late_init(void *handle) if (!ret) return -EINVAL; - return detect_mst_link_for_all_connectors(adev->ddev); + return detect_mst_link_for_all_connectors(adev_to_drm(adev)); } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -1672,9 +1672,9 @@ static int dm_suspend(void *handle) } WARN_ON(adev->dm.cached_state); - adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); + adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev)); - s3_handle_mst(adev->ddev, true); + s3_handle_mst(adev_to_drm(adev), true); amdgpu_dm_irq_suspend(adev); @@ -1828,7 +1828,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, static int dm_resume(void *handle) { struct amdgpu_device *adev = handle; - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; @@ -2443,7 +2443,7 @@ static void handle_hpd_rx_irq(void *param) static void register_hpd_handlers(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct amdgpu_dm_connector *aconnector; const struct dc_link *dc_link; @@ -2874,18 +2874,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; - adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; - adev->ddev->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; + adev_to_drm(adev)->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + adev_to_drm(adev)->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) @@ -2899,7 +2899,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) dc_resource_state_copy_construct_current(adev->dm.dc, state->context); - drm_atomic_private_obj_init(adev->ddev, + drm_atomic_private_obj_init(adev_to_drm(adev), &adev->dm.atomic_obj, &state->base, &dm_atomic_state_funcs); @@ -3065,13 +3065,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) props.type = BACKLIGHT_RAW; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", - dm->adev->ddev->primary->index); + adev_to_drm(dm->adev)->primary->index); dm->backlight_dev = backlight_device_register(bl_name, - dm->adev->ddev->dev, - dm, - &amdgpu_dm_backlight_ops, - &props); + adev_to_drm(dm->adev)->dev, + dm, + &amdgpu_dm_backlight_ops, + &props); if (IS_ERR(dm->backlight_dev)) DRM_ERROR("DM: Backlight registration failed!\n"); @@ -3395,7 +3395,7 @@ static ssize_t s3_debug_store(struct device *device, if (ret == 0) { if (s3_state) { dm_resume(adev); - drm_kms_helper_hotplug_event(adev->ddev); + drm_kms_helper_hotplug_event(adev_to_drm(adev)); } else dm_suspend(adev); } @@ -3522,7 +3522,7 @@ static int dm_early_init(void *handle) */ #if defined(CONFIG_DEBUG_KERNEL_DC) device_create_file( - adev->ddev->dev, + adev_to_drm(adev)->dev, &dev_attr_s3_debug); #endif @@ -5986,7 +5986,7 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, num_formats = get_plane_formats(plane, plane_cap, formats, ARRAY_SIZE(formats)); - res = drm_universal_plane_init(dm->adev->ddev, plane, possible_crtcs, + res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs, &dm_plane_funcs, formats, num_formats, NULL, plane->type, NULL); if (res) @@ -6830,7 +6830,7 @@ static void update_freesync_state_on_stream( if (!new_stream->timing.h_total || !new_stream->timing.v_total) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); vrr_params = new_crtc_state->vrr_params; if (surface) { @@ -6883,7 +6883,7 @@ static void update_freesync_state_on_stream( (int)new_crtc_state->base.vrr_enabled, (int)vrr_params.state); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static void pre_update_freesync_state_on_stream( @@ -6906,7 +6906,7 @@ static void pre_update_freesync_state_on_stream( if (!new_stream->timing.h_total || !new_stream->timing.v_total) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); vrr_params = new_crtc_state->vrr_params; if (new_crtc_state->vrr_supported && @@ -6929,7 +6929,7 @@ static void pre_update_freesync_state_on_stream( sizeof(vrr_params.adjust)) != 0); new_crtc_state->vrr_params = vrr_params; - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, @@ -7741,7 +7741,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) * send vblank event on all events not handled in flip and * mark consumed event for drm_atomic_helper_commit_hw_done */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->event) @@ -7749,7 +7749,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) new_crtc_state->event = NULL; } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); /* Signal HW programming completion */ drm_atomic_helper_commit_hw_done(state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 5703a68d8302d..f878575d17bbc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2194,7 +2194,7 @@ static int force_timing_sync_set(void *data, u64 val) adev->dm.force_timing_sync = (bool)val; - amdgpu_dm_trigger_timing_sync(adev->ddev); + amdgpu_dm_trigger_timing_sync(adev_to_drm(adev)); return 0; } @@ -2253,7 +2253,7 @@ int dtn_debugfs_init(struct amdgpu_device *adev) .llseek = default_llseek }; - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; int ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index cbcf504f73a51..357778556b06c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -719,7 +719,7 @@ void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) */ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; @@ -755,7 +755,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) */ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 8aba40345b54e..bbc20834c643b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -310,7 +310,7 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { void dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); int i; for (i = 0; i < adev->dm.display_indexes_num; i++) { @@ -426,7 +426,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, aconnector->mst_mgr.cbs = &dm_mst_cbs; drm_dp_mst_topology_mgr_init( &aconnector->mst_mgr, - dm->adev->ddev, + adev_to_drm(dm->adev), &aconnector->dm_dp_aux.aux, 16, 4, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index ca3fb32979d4d..17a45baff638c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -122,7 +122,7 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; @@ -143,7 +143,7 @@ void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; u32 vblank_in_pixels; @@ -170,7 +170,7 @@ u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; u32 vrefresh = 0; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ea00c4b0e74b1..2d924e88a215b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1903,7 +1903,7 @@ static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", - adev->ddev->unique, + adev_to_drm(adev)->unique, atomic_read(&adev->throttling_logging_enabled) ? "enabled" : "disabled", adev->throttling_logging_rs.interval / HZ + 1); } @@ -2199,9 +2199,9 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, if (channel >= PP_TEMP_MAX) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2226,8 +2226,8 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, break; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2332,9 +2332,9 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2342,16 +2342,16 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return sprintf(buf, "%i\n", pwm_mode); } @@ -2372,9 +2372,9 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, if (err) return err; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2382,16 +2382,16 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, smu_set_fan_control_mode(&adev->smu, value); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, value); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return count; } @@ -2422,9 +2422,9 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2435,15 +2435,15 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } err = kstrtou32(buf, 10, &value); if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2456,8 +2456,8 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2476,9 +2476,9 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2489,8 +2489,8 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2511,9 +2511,9 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2524,8 +2524,8 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2545,17 +2545,17 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, (void *)&min_rpm, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2575,17 +2575,17 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, (void *)&max_rpm, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2604,9 +2604,9 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2617,8 +2617,8 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2638,9 +2638,9 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2650,15 +2650,15 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -ENODATA; } err = kstrtou32(buf, 10, &value); if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2669,8 +2669,8 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2689,9 +2689,9 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2699,16 +2699,16 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); } @@ -2737,9 +2737,9 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, else return -EINVAL; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2747,15 +2747,15 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, smu_set_fan_control_mode(&adev->smu, pwm_mode); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return count; } @@ -2771,9 +2771,9 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2781,8 +2781,8 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&vddgfx, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2812,9 +2812,9 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, if (!(adev->flags & AMD_IS_APU)) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2822,8 +2822,8 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&vddnb, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2850,9 +2850,9 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2860,8 +2860,8 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2891,9 +2891,9 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2907,8 +2907,8 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return size; } @@ -2925,9 +2925,9 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2941,8 +2941,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return size; } @@ -2970,9 +2970,9 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, value = value / 1000000; /* convert to Watt */ - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2983,8 +2983,8 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -3003,9 +3003,9 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -3013,8 +3013,8 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&sclk, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -3040,9 +3040,9 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -3050,8 +3050,8 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&mclk, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; -- GitLab From ced026e959bec5046afa310d6474e147b6294da2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi <rodrigo.vivi@intel.com> Date: Mon, 24 Aug 2020 14:26:38 -0400 Subject: [PATCH 0593/1494] drm/i915: Update DRIVER_DATE to 20200824 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4b5c25a018b7f..1314e0e92c411 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -108,8 +108,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20200715" -#define DRIVER_TIMESTAMP 1594811881 +#define DRIVER_DATE "20200824" +#define DRIVER_TIMESTAMP 1598293597 struct drm_i915_gem_object; -- GitLab From 274d77648eaa7a88787bb5c2e53e1f8c709ce7ac Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 19 Aug 2020 17:23:31 +0800 Subject: [PATCH 0594/1494] drm/hisilicon: Use drm_err instead of DRM_ERROR in hibmc_ttm Use drm_err instead of DRM_ERROR in hibmc_ttm. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597829014-39942-2-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 322bd542e89d9..602ece11bb4a4 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -32,7 +32,7 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc) hibmc->fb_size); if (IS_ERR(vmm)) { ret = PTR_ERR(vmm); - DRM_ERROR("Error initializing VRAM MM; %d\n", ret); + drm_err(dev, "Error initializing VRAM MM; %d\n", ret); return ret; } -- GitLab From ae34c15be62f679991826fc7531820d881f21a5d Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 19 Aug 2020 17:23:32 +0800 Subject: [PATCH 0595/1494] drm/hisilicon: Use drm_err instead of DRM_ERROR in hibmc_drm_vdac Use drm_err instead of DRM_ERROR in hibmc_drm_vdac Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597829014-39942-3-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index ed12f61cf46ea..376a05ddbc2f3 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -85,7 +85,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); if (ret) { - DRM_ERROR("failed to init encoder: %d\n", ret); + drm_err(dev, "failed to init encoder: %d\n", ret); return ret; } @@ -94,7 +94,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) ret = drm_connector_init(dev, connector, &hibmc_connector_funcs, DRM_MODE_CONNECTOR_VGA); if (ret) { - DRM_ERROR("failed to init connector: %d\n", ret); + drm_err(dev, "failed to init connector: %d\n", ret); return ret; } drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); -- GitLab From e7187bab295a5aead366c9f4a132db7c890afc9e Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 19 Aug 2020 17:23:33 +0800 Subject: [PATCH 0596/1494] drm/hisilicon: Use drm_err instead of DRM_ERROR in hibmc_drm_de Use drm_err instead of DRM_ERROR in hibmc_drm_de Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597829014-39942-4-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index d9062a3f5b82d..4d57ec688f827 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -71,12 +71,12 @@ static int hibmc_plane_atomic_check(struct drm_plane *plane, return PTR_ERR(crtc_state); if (src_w != state->crtc_w || src_h != state->crtc_h) { - DRM_DEBUG_ATOMIC("scale not support\n"); + drm_dbg_atomic(plane->dev, "scale not support\n"); return -EINVAL; } if (state->crtc_x < 0 || state->crtc_y < 0) { - DRM_DEBUG_ATOMIC("crtc_x/y of drm_plane state is invalid\n"); + drm_dbg_atomic(plane->dev, "crtc_x/y of drm_plane state is invalid\n"); return -EINVAL; } @@ -87,12 +87,12 @@ static int hibmc_plane_atomic_check(struct drm_plane *plane, crtc_state->adjusted_mode.hdisplay || state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay) { - DRM_DEBUG_ATOMIC("visible portion of plane is invalid\n"); + drm_dbg_atomic(plane->dev, "visible portion of plane is invalid\n"); return -EINVAL; } if (state->fb->pitches[0] % 128 != 0) { - DRM_DEBUG_ATOMIC("wrong stride with 128-byte aligned\n"); + drm_dbg_atomic(plane->dev, "wrong stride with 128-byte aligned\n"); return -EINVAL; } return 0; @@ -515,7 +515,7 @@ int hibmc_de_init(struct hibmc_drm_private *priv) NULL); if (ret) { - DRM_ERROR("failed to init plane: %d\n", ret); + drm_err(dev, "failed to init plane: %d\n", ret); return ret; } @@ -524,13 +524,13 @@ int hibmc_de_init(struct hibmc_drm_private *priv) ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &hibmc_crtc_funcs, NULL); if (ret) { - DRM_ERROR("failed to init crtc: %d\n", ret); + drm_err(dev, "failed to init crtc: %d\n", ret); return ret; } ret = drm_mode_crtc_set_gamma_size(crtc, 256); if (ret) { - DRM_ERROR("failed to set gamma size: %d\n", ret); + drm_err(dev, "failed to set gamma size: %d\n", ret); return ret; } drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs); -- GitLab From 389be5006317371eba354969886affdf714f57c6 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 19 Aug 2020 17:23:34 +0800 Subject: [PATCH 0597/1494] drm/hisilicon: Use drm_err instead of DRM_ERROR in hibmc_drm_drv Use drm_err instead of DRM_ERROR in hibmc_drm_drv Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1597829014-39942-5-git-send-email-tiantao6@hisilicon.com --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 2b4f82163b99e..085d1b2fa8c0a 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -98,13 +98,13 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) ret = hibmc_de_init(priv); if (ret) { - DRM_ERROR("failed to init de: %d\n", ret); + drm_err(priv->dev, "failed to init de: %d\n", ret); return ret; } ret = hibmc_vdac_init(priv); if (ret) { - DRM_ERROR("failed to init vdac: %d\n", ret); + drm_err(priv->dev, "failed to init vdac: %d\n", ret); return ret; } @@ -212,7 +212,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) iosize = pci_resource_len(pdev, 1); priv->mmio = devm_ioremap(dev->dev, ioaddr, iosize); if (!priv->mmio) { - DRM_ERROR("Cannot map mmio region\n"); + drm_err(dev, "Cannot map mmio region\n"); return -ENOMEM; } @@ -220,7 +220,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) size = pci_resource_len(pdev, 0); priv->fb_map = devm_ioremap(dev->dev, addr, size); if (!priv->fb_map) { - DRM_ERROR("Cannot map framebuffer\n"); + drm_err(dev, "Cannot map framebuffer\n"); return -ENOMEM; } priv->fb_base = addr; @@ -265,7 +265,7 @@ static int hibmc_load(struct drm_device *dev) priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) { - DRM_ERROR("no memory to allocate for hibmc_drm_private\n"); + drm_err(dev, "no memory to allocate for hibmc_drm_private\n"); return -ENOMEM; } dev->dev_private = priv; @@ -285,17 +285,17 @@ static int hibmc_load(struct drm_device *dev) ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) { - DRM_ERROR("failed to initialize vblank: %d\n", ret); + drm_err(dev, "failed to initialize vblank: %d\n", ret); goto err; } ret = pci_enable_msi(dev->pdev); if (ret) { - DRM_WARN("enabling MSI failed: %d\n", ret); + drm_warn(dev, "enabling MSI failed: %d\n", ret); } else { ret = drm_irq_install(dev, dev->pdev->irq); if (ret) - DRM_WARN("install irq failed: %d\n", ret); + drm_warn(dev, "install irq failed: %d\n", ret); } /* reset all the states of crtc/plane/encoder/connector */ @@ -305,7 +305,7 @@ static int hibmc_load(struct drm_device *dev) err: hibmc_unload(dev); - DRM_ERROR("failed to initialize drm driver: %d\n", ret); + drm_err(dev, "failed to initialize drm driver: %d\n", ret); return ret; } @@ -331,19 +331,19 @@ static int hibmc_pci_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) { - DRM_ERROR("failed to enable pci device: %d\n", ret); + drm_err(dev, "failed to enable pci device: %d\n", ret); goto err_free; } ret = hibmc_load(dev); if (ret) { - DRM_ERROR("failed to load hibmc: %d\n", ret); + drm_err(dev, "failed to load hibmc: %d\n", ret); goto err_disable; } ret = drm_dev_register(dev, 0); if (ret) { - DRM_ERROR("failed to register drv for userspace access: %d\n", + drm_err(dev, "failed to register drv for userspace access: %d\n", ret); goto err_unload; } -- GitLab From dbda95809457875ded5d596acf929fc9de4d36c2 Mon Sep 17 00:00:00 2001 From: Anshuman Gupta <anshuman.gupta@intel.com> Date: Wed, 5 Aug 2020 17:15:20 +0530 Subject: [PATCH 0598/1494] drm/i915/hdcp: Add update_pipe early return Currently intel_hdcp_update_pipe() is also getting called for non-hdcp connectors and get through its conditional code flow, which is completely unnecessary for non-hdcp connectors, therefore it make sense to have an early return. No functional change. v2: - rebased. Reviewed-by: Uma Shankar <uma.shankar@intel.com> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805114521.867-2-anshuman.gupta@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 89a4d294822d5..a1e0d518e529e 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2082,11 +2082,15 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_hdcp *hdcp = &connector->hdcp; - bool content_protection_type_changed = + bool content_protection_type_changed, desired_and_not_enabled = false; + + if (!connector->hdcp.shim) + return; + + content_protection_type_changed = (conn_state->hdcp_content_type != hdcp->content_type && conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED); - bool desired_and_not_enabled = false; /* * During the HDCP encryption session if Type change is requested, -- GitLab From 4fcee7be650c7f7c0581034b9cc4336190226abf Mon Sep 17 00:00:00 2001 From: Anshuman Gupta <anshuman.gupta@intel.com> Date: Wed, 5 Aug 2020 17:15:21 +0530 Subject: [PATCH 0599/1494] drm/i915/hdcp: No direct access to power_well desc HDCP code doesn't require to access power_well internal stuff, instead it should use the intel_display_power_well_is_enabled() to get the status of desired power_well. No functional change. v2: - used with_intel_runtime_pm instead of get/put. [Jani] v3: - rebased. Cc: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805114521.867-3-anshuman.gupta@intel.com --- drivers/gpu/drm/i915/display/intel_hdcp.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index a1e0d518e529e..e76b049618dbd 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -148,9 +148,8 @@ static int intel_hdcp_poll_ksv_fifo(struct intel_digital_port *dig_port, static bool hdcp_key_loadable(struct drm_i915_private *dev_priv) { - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; enum i915_power_well_id id; + intel_wakeref_t wakeref; bool enabled = false; /* @@ -162,17 +161,9 @@ static bool hdcp_key_loadable(struct drm_i915_private *dev_priv) else id = SKL_DISP_PW_1; - mutex_lock(&power_domains->lock); - /* PG1 (power well #1) needs to be enabled */ - for_each_power_well(dev_priv, power_well) { - if (power_well->desc->id == id) { - enabled = power_well->desc->ops->is_enabled(dev_priv, - power_well); - break; - } - } - mutex_unlock(&power_domains->lock); + with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) + enabled = intel_display_power_well_is_enabled(dev_priv, id); /* * Another req for hdcp key loadability is enabled state of pll for -- GitLab From c5589b39549d1875bb506da473bf4580c959db8c Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:15:22 +0200 Subject: [PATCH 0600/1494] drm/bridge_connector: Set default status connected for eDP connectors In an eDP application, HPD is not required and on most bridge chips useless. If HPD is not used, we need to set initial status as connected, otherwise the connector created by the drm_bridge_connector API remains in an unknown state. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Reviewed-by: Bilal Wasim <bwasim.lkml@gmail.com> Tested-by: Bilal Wasim <bwasim.lkml@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200826081526.674866-2-enric.balletbo@collabora.com --- drivers/gpu/drm/drm_bridge_connector.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index c6994fe673f31..a58cbde59c34a 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -187,6 +187,7 @@ drm_bridge_connector_detect(struct drm_connector *connector, bool force) case DRM_MODE_CONNECTOR_DPI: case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_DSI: + case DRM_MODE_CONNECTOR_eDP: status = connector_status_connected; break; default: -- GitLab From d82c12ab16b8477a6a79452f820f395c3899efa4 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:15:23 +0200 Subject: [PATCH 0601/1494] drm/bridge: ps8640: Get the EDID from eDP control The PS8640 DSI-to-eDP bridge can retrieve the EDID, so implement the .get_edid callback and set the flag to indicate the core to use it. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200826081526.674866-3-enric.balletbo@collabora.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 4b099196afeba..13755d278db6d 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -242,8 +242,18 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, return ret; } +static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + return drm_get_edid(connector, + ps_bridge->page[PAGE0_DP_CNTL]->adapter); +} + static const struct drm_bridge_funcs ps8640_bridge_funcs = { .attach = ps8640_bridge_attach, + .get_edid = ps8640_bridge_get_edid, .post_disable = ps8640_post_disable, .pre_enable = ps8640_pre_enable, }; @@ -294,6 +304,8 @@ static int ps8640_probe(struct i2c_client *client) ps_bridge->bridge.funcs = &ps8640_bridge_funcs; ps_bridge->bridge.of_node = dev->of_node; + ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID; + ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP; ps_bridge->page[PAGE0_DP_CNTL] = client; -- GitLab From 812a65ba9411c5b3a68e92da061ec91a328774d2 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:15:24 +0200 Subject: [PATCH 0602/1494] drm/bridge: ps8640: Return an error for incorrect attach flags Bridge drivers that implement the new model only shall return an error from their attach() handler when the DRM_BRIDGE_ATTACH_NO_CONNECTOR flag is not set. So make sure we return an error because only the new drm_bridge model is supported. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Reviewed-by: Bilal Wasim <bwasim.lkml@gmail.com> Tested-by: Bilal Wasim <bwasim.lkml@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200826081526.674866-4-enric.balletbo@collabora.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 13755d278db6d..ce3e8b2da8c9b 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -200,6 +200,10 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge, .channel = 0, .node = NULL, }; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + /* port@0 is ps8640 dsi input port */ in_ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!in_ep) -- GitLab From 94d4c13233c21234f6cdccf8cf2593a6772b85f3 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:15:25 +0200 Subject: [PATCH 0603/1494] drm/bridge: ps8640: Print an error if VDO control fails Print an error message inside ps8640_bridge_vdo_control() function when it fails so we can simplify a bit the callers, they will only need to check the error code. Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Reviewed-by: Bilal Wasim <bwasim.lkml@gmail.com> Tested-by: Bilal Wasim <bwasim.lkml@gmail.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200826081526.674866-5-enric.balletbo@collabora.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index ce3e8b2da8c9b..9f7b7a9c53c52 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -82,8 +82,11 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, ret = i2c_smbus_write_i2c_block_data(client, PAGE3_SET_ADD, sizeof(vdo_ctrl_buf), vdo_ctrl_buf); - if (ret < 0) + if (ret < 0) { + DRM_ERROR("failed to %sable VDO: %d\n", + ctrl == ENABLE ? "en" : "dis", ret); return ret; + } return 0; } @@ -150,10 +153,8 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) } ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE); - if (ret) { - DRM_ERROR("failed to enable VDO: %d\n", ret); + if (ret) goto err_regulators_disable; - } /* Switch access edp panel's edid through i2c */ ret = i2c_smbus_write_byte_data(client, PAGE2_I2C_BYPASS, @@ -175,9 +176,7 @@ static void ps8640_post_disable(struct drm_bridge *bridge) struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); int ret; - ret = ps8640_bridge_vdo_control(ps_bridge, DISABLE); - if (ret < 0) - DRM_ERROR("failed to disable VDO: %d\n", ret); + ps8640_bridge_vdo_control(ps_bridge, DISABLE); gpiod_set_value(ps_bridge->gpio_reset, 1); gpiod_set_value(ps_bridge->gpio_powerdown, 1); -- GitLab From a91da66861084df3521e7e001aa4c49d5ff51879 Mon Sep 17 00:00:00 2001 From: Clint Taylor <clinton.a.taylor@intel.com> Date: Tue, 25 Aug 2020 19:57:24 -0700 Subject: [PATCH 0604/1494] drm/i915/gt: Implement WA_1406941453 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable HW Default flip for small PL. bspec: 52890 bspec: 53508 bspec: 53273 v2: rebase to drm-tip v3: move from ctx to gt workarounds. Remove whitelist. v4: move to rcs WA init Cc: Matt Atwood <matthew.s.atwood@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Clint Taylor <clinton.a.taylor@intel.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826025724.20944-1-clinton.a.taylor@intel.com --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 7 +++++++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index be5a4685c9915..7622d8ae1bb9a 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1725,6 +1725,13 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) FF_DOP_CLOCK_GATE_DISABLE); } + if (IS_GEN(i915, 12)) { + /* Wa_1406941453:gen12 */ + wa_masked_en(wal, + GEN10_SAMPLER_MODE, + ENABLE_SMALLPL); + } + if (IS_GEN(i915, 11)) { /* This is not an Wa. Enable for better image quality */ wa_masked_en(wal, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ac691927e29d8..ab4b1abd4364d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9315,6 +9315,7 @@ enum { #define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7) #define GEN10_SAMPLER_MODE _MMIO(0xE18C) +#define ENABLE_SMALLPL REG_BIT(15) #define GEN11_SAMPLER_ENABLE_HEADLESS_MSG REG_BIT(5) /* IVYBRIDGE DPF */ -- GitLab From 8aba21b75136c39c4bf63345d699d97dc477ce0e Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Fri, 14 Aug 2020 20:41:55 -0400 Subject: [PATCH 0605/1494] drm/amdgpu: Embed drm_device into amdgpu_device (v3) a) Embed struct drm_device into struct amdgpu_device. b) Modify the inline-f drm_to_adev() accordingly. c) Modify the inline-f adev_to_drm() accordingly. d) Eliminate the use of drm_device.dev_private, in amdgpu. e) Switch from using drm_dev_alloc() to drm_dev_init(). f) Add a DRM driver release function, which frees the container amdgpu_device after all krefs on the contained drm_device have been released. v2: Split out adding adev_to_drm() into its own patch (previous commit), making this patch more succinct and clear. More detailed commit description. v3: squash in fix to call drmm_add_final_kfree() to avoid a warning. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 10 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 +++----- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 45 ++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 +++------- 4 files changed, 45 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9d93b3170cd62..2509b1e302c00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -722,8 +722,8 @@ struct amd_powerplay { #define AMDGPU_MAX_DF_PERFMONS 4 struct amdgpu_device { struct device *dev; - struct drm_device *ddev; struct pci_dev *pdev; + struct drm_device ddev; #ifdef CONFIG_DRM_AMD_ACP struct amdgpu_acp acp; @@ -988,12 +988,12 @@ struct amdgpu_device { static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) { - return ddev->dev_private; + return container_of(ddev, struct amdgpu_device, ddev); } static inline struct drm_device *adev_to_drm(struct amdgpu_device *adev) { - return adev->ddev; + return &adev->ddev; } static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) @@ -1002,8 +1002,6 @@ static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) } int amdgpu_device_init(struct amdgpu_device *adev, - struct drm_device *ddev, - struct pci_dev *pdev, uint32_t flags); void amdgpu_device_fini(struct amdgpu_device *adev); int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev); @@ -1194,7 +1192,7 @@ static inline void *amdgpu_atpx_get_dhandle(void) { return NULL; } extern const struct drm_ioctl_desc amdgpu_ioctls_kms[]; extern const int amdgpu_max_kms_ioctl; -int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags); +int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags); void amdgpu_driver_unload_kms(struct drm_device *dev); void amdgpu_driver_lastclose_kms(struct drm_device *dev); int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index afe8cb37d5b46..64d6e58bcb0a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1216,7 +1216,8 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) * Callback for the switcheroo driver. Suspends or resumes the * the asics before or after it is powered up using ACPI methods. */ -static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) +static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) { struct drm_device *dev = pci_get_drvdata(pdev); int r; @@ -2978,8 +2979,6 @@ static const struct attribute *amdgpu_dev_attributes[] = { * amdgpu_device_init - initialize the driver * * @adev: amdgpu_device pointer - * @ddev: drm dev pointer - * @pdev: pci dev pointer * @flags: driver flags * * Initializes the driver info and hw (all asics). @@ -2987,18 +2986,15 @@ static const struct attribute *amdgpu_dev_attributes[] = { * Called at driver startup. */ int amdgpu_device_init(struct amdgpu_device *adev, - struct drm_device *ddev, - struct pci_dev *pdev, uint32_t flags) { + struct drm_device *ddev = adev_to_drm(adev); + struct pci_dev *pdev = adev->pdev; int r, i; bool boco = false; u32 max_MBps; adev->shutdown = false; - adev->dev = &pdev->dev; - adev->ddev = ddev; - adev->pdev = pdev; adev->flags = flags; if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST) @@ -3453,9 +3449,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) struct drm_connector_list_iter iter; int r; - if (dev == NULL || dev->dev_private == NULL) { + if (!dev) return -ENODEV; - } adev = drm_to_adev(dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 651b51ab14cb6..ed29f0ce007cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -26,6 +26,7 @@ #include <drm/drm_drv.h> #include <drm/drm_gem.h> #include <drm/drm_vblank.h> +#include <drm/drm_managed.h> #include "amdgpu_drv.h" #include <drm/drm_pciids.h> @@ -1082,7 +1083,7 @@ static struct drm_driver kms_driver; static int amdgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct drm_device *dev; + struct drm_device *ddev; struct amdgpu_device *adev; unsigned long flags = ent->driver_data; int ret, retry = 0; @@ -1138,36 +1139,44 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, if (ret) return ret; - dev = drm_dev_alloc(&kms_driver, &pdev->dev); - if (IS_ERR(dev)) - return PTR_ERR(dev); + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + adev->dev = &pdev->dev; + adev->pdev = pdev; + ddev = adev_to_drm(adev); + ret = drm_dev_init(ddev, &kms_driver, &pdev->dev); + if (ret) + goto err_free; + + drmm_add_final_kfree(ddev, ddev); if (!supports_atomic) - dev->driver_features &= ~DRIVER_ATOMIC; + ddev->driver_features &= ~DRIVER_ATOMIC; ret = pci_enable_device(pdev); if (ret) goto err_free; - dev->pdev = pdev; - - pci_set_drvdata(pdev, dev); + ddev->pdev = pdev; + pci_set_drvdata(pdev, ddev); - ret = amdgpu_driver_load_kms(dev, ent->driver_data); + ret = amdgpu_driver_load_kms(adev, ent->driver_data); if (ret) goto err_pci; retry_init: - ret = drm_dev_register(dev, ent->driver_data); + ret = drm_dev_register(ddev, ent->driver_data); if (ret == -EAGAIN && ++retry <= 3) { DRM_INFO("retry init %d\n", retry); /* Don't request EX mode too frequently which is attacking */ msleep(5000); goto retry_init; - } else if (ret) + } else if (ret) { goto err_pci; + } - adev = drm_to_adev(dev); ret = amdgpu_debugfs_init(adev); if (ret) DRM_ERROR("Creating debugfs files failed (%d).\n", ret); @@ -1177,7 +1186,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, err_pci: pci_disable_device(pdev); err_free: - drm_dev_put(dev); + drm_dev_put(ddev); return ret; } @@ -1197,6 +1206,13 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_dev_put(dev); } +static void amdgpu_driver_release(struct drm_device *ddev) +{ + struct amdgpu_device *adev = drm_to_adev(ddev); + + kfree(adev); +} + static void amdgpu_pci_shutdown(struct pci_dev *pdev) { @@ -1491,6 +1507,7 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, + .release = amdgpu_driver_release, .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, .gem_free_object_unlocked = amdgpu_gem_object_free, @@ -1525,8 +1542,6 @@ static struct pci_driver amdgpu_kms_pci_driver = { .driver.pm = &amdgpu_pm_ops, }; - - static int __init amdgpu_init(void) { int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c2a697d3f830f..d125c4b2af53a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -86,7 +86,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) amdgpu_unregister_gpu_instance(adev); if (adev->rmmio == NULL) - goto done_free; + return; if (adev->runpm) { pm_runtime_get_sync(dev->dev); @@ -94,12 +94,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) } amdgpu_acpi_fini(adev); - amdgpu_device_fini(adev); - -done_free: - kfree(adev); - dev->dev_private = NULL; } void amdgpu_register_gpu_instance(struct amdgpu_device *adev) @@ -130,22 +125,18 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev) /** * amdgpu_driver_load_kms - Main load function for KMS. * - * @dev: drm dev pointer + * @adev: pointer to struct amdgpu_device * @flags: device flags * * This is the main load function for KMS (all asics). * Returns 0 on success, error on failure. */ -int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) +int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) { - struct amdgpu_device *adev; + struct drm_device *dev; int r, acpi_status; - adev = kzalloc(sizeof(struct amdgpu_device), GFP_KERNEL); - if (adev == NULL) { - return -ENOMEM; - } - dev->dev_private = (void *)adev; + dev = adev_to_drm(adev); if (amdgpu_has_atpx() && (amdgpu_is_atpx_hybrid() || @@ -160,7 +151,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) * properly initialize the GPU MC controller and permit * VRAM allocation */ - r = amdgpu_device_init(adev, dev, dev->pdev, flags); + r = amdgpu_device_init(adev, flags); if (r) { dev_err(&dev->pdev->dev, "Fatal error during GPU init\n"); goto out; -- GitLab From 7323923260cd6f72c3b38c4da3fcc7909df48ac0 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 21 Aug 2020 12:05:03 +0800 Subject: [PATCH 0606/1494] drm/amd/pm: correct Vega10 swctf limit setting Correct the Vega10 thermal swctf limit. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1267 Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 468bdd6f66973..ce9514c881ec2 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -363,6 +363,9 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -372,8 +375,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; if (low > high) return -EINVAL; -- GitLab From b23f9f60424732ce517cc6f02d7c34cf2f25ac50 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 21 Aug 2020 12:18:58 +0800 Subject: [PATCH 0607/1494] drm/amd/pm: correct Vega12 swctf limit setting Correct the Vega12 thermal swctf limit. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index c15b9756025d9..e755fc0c98860 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -170,6 +170,8 @@ int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -179,8 +181,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- GitLab From bfcc0c162a6ad3c8025fea0e966b2a09add80b8e Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 21 Aug 2020 12:21:30 +0800 Subject: [PATCH 0608/1494] drm/amd/pm: correct Vega20 swctf limit setting Correct the Vega20 thermal swctf limit. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index 7add2f60f49c4..a9bc9d16641a2 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -240,6 +240,8 @@ int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -249,8 +251,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- GitLab From 6127896f4a272578a62d1b439e86e64721296d65 Mon Sep 17 00:00:00 2001 From: Huang Rui <ray.huang@amd.com> Date: Tue, 18 Aug 2020 14:54:23 +0800 Subject: [PATCH 0609/1494] drm/amdkfd: implement the dGPU fallback path for apu (v6) We still have a few iommu issues which need to address, so force raven as "dgpu" path for the moment. This is to add the fallback path to bypass IOMMU if IOMMU v2 is disabled or ACPI CRAT table not correct. v2: Use ignore_crat parameter to decide whether it will go with IOMMUv2. v3: Align with existed thunk, don't change the way of raven, only renoir will use "dgpu" path by default. v4: don't update global ignore_crat in the driver, and revise fallback function if CRAT is broken. v5: refine acpi crat good but no iommu support case, and rename the title. v6: fix the issue of dGPU initialized firstly, just modify the report value in the node_show(). Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 +++- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 18 +++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++- .../amd/amdkfd/kfd_device_queue_manager_v9.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | 4 +-- drivers/gpu/drm/amd/amdkfd/kfd_iommu.c | 10 +++---- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +++ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 29 +++++++++++++++++-- 9 files changed, 64 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ed29f0ce007cb..dfc1a9721867e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -680,11 +680,14 @@ MODULE_PARM_DESC(debug_largebar, * Ignore CRAT table during KFD initialization. By default, KFD uses the ACPI CRAT * table to get information about AMD APUs. This option can serve as a workaround on * systems with a broken CRAT table. + * + * Default is auto (according to asic type, iommu_v2, and crat table, to decide + * whehter use CRAT) */ int ignore_crat; module_param(ignore_crat, int, 0444); MODULE_PARM_DESC(ignore_crat, - "Ignore CRAT table during KFD initialization (0 = use CRAT (default), 1 = ignore CRAT)"); + "Ignore CRAT table during KFD initialization (0 = auto (default), 1 = ignore CRAT)"); /** * DOC: halt_if_hws_hang (int) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index e9b96ad3d9a52..b7b16adb0615d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1254,7 +1254,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev) return true; } - if (dev->device_info->needs_iommu_device) + if (dev->use_iommu_v2) return false; amdgpu_amdkfd_get_local_mem_info(dev->kgd, &mem_info); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 6a250f8fcfb81..3fac06b281ce0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -742,6 +742,22 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, return 0; } +static bool kfd_ignore_crat(void) +{ + bool ret; + + if (ignore_crat) + return true; + +#ifndef KFD_SUPPORT_IOMMU_V2 + ret = true; +#else + ret = false; +#endif + + return ret; +} + /* * kfd_create_crat_image_acpi - Allocates memory for CRAT image and * copies CRAT from ACPI (if available). @@ -776,7 +792,7 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size) return -EINVAL; } - if (ignore_crat) { + if (kfd_ignore_crat()) { pr_info("CRAT table disabled by module option\n"); return -ENODATA; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index d5e790f046b4b..b15b620e731b7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -116,6 +116,7 @@ static const struct kfd_device_info carrizo_device_info = { .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, }; +#endif static const struct kfd_device_info raven_device_info = { .asic_family = CHIP_RAVEN, @@ -134,7 +135,6 @@ static const struct kfd_device_info raven_device_info = { .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, }; -#endif static const struct kfd_device_info hawaii_device_info = { .asic_family = CHIP_HAWAII, @@ -738,6 +738,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto gws_error; } + /* If CRAT is broken, won't set iommu enabled */ + kfd_double_confirm_iommu_support(kfd); + if (kfd_iommu_device_init(kfd)) { dev_err(kfd_device, "Error initializing iommuv2\n"); goto device_iommu_error; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 95a82ac455f2b..309f63a0b34a1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -62,7 +62,7 @@ static int update_qpd_v9(struct device_queue_manager *dqm, SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; if (amdgpu_noretry && - !dqm->dev->device_info->needs_iommu_device) + !dqm->dev->use_iommu_v2) qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index c1166c40ac15e..3c22909470f20 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c @@ -321,7 +321,7 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id) pdd->lds_base = MAKE_LDS_APP_BASE_VI(); pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); - if (!pdd->dev->device_info->needs_iommu_device) { + if (!pdd->dev->use_iommu_v2) { /* dGPUs: SVM aperture starting at 0 * with small reserved space for kernel. * Set them to CANONICAL addresses. @@ -425,7 +425,7 @@ int kfd_init_apertures(struct kfd_process *process) return -EINVAL; } - if (!dev->device_info->needs_iommu_device) { + if (!dev->use_iommu_v2) { /* dGPUs: the reserved space for kernel * before SVM */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c index 7c8786b9eb0aa..5a64915abaf7f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c @@ -41,7 +41,7 @@ int kfd_iommu_check_device(struct kfd_dev *kfd) struct amd_iommu_device_info iommu_info; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return -ENODEV; iommu_info.flags = 0; @@ -63,7 +63,7 @@ int kfd_iommu_device_init(struct kfd_dev *kfd) unsigned int pasid_limit; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return 0; iommu_info.flags = 0; @@ -109,7 +109,7 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd) struct kfd_process *p = pdd->process; int err; - if (!dev->device_info->needs_iommu_device || pdd->bound == PDD_BOUND) + if (!dev->use_iommu_v2 || pdd->bound == PDD_BOUND) return 0; if (unlikely(pdd->bound == PDD_BOUND_SUSPENDED)) { @@ -284,7 +284,7 @@ static void kfd_unbind_processes_from_device(struct kfd_dev *kfd) */ void kfd_iommu_suspend(struct kfd_dev *kfd) { - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return; kfd_unbind_processes_from_device(kfd); @@ -304,7 +304,7 @@ int kfd_iommu_resume(struct kfd_dev *kfd) unsigned int pasid_limit; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return 0; pasid_limit = kfd_get_pasid_limit(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 6727e9de5b8b0..f14beb93acb43 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -297,6 +297,9 @@ struct kfd_dev { bool pci_atomic_requested; + /* Use IOMMU v2 flag */ + bool use_iommu_v2; + /* SRAM ECC flag */ atomic_t sram_ecc_flag; @@ -892,6 +895,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); struct kfd_dev *kfd_device_by_kgd(const struct kgd_dev *kgd); int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); int kfd_numa_node_to_apic_id(int numa_node_id); +void kfd_double_confirm_iommu_support(struct kfd_dev *gpu); /* Interrupts */ int kfd_interrupt_init(struct kfd_dev *dev); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index f185f6cbc05c6..5e8eb783d2d52 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -446,7 +446,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, sysfs_show_32bit_prop(buffer, offs, "cpu_cores_count", dev->node_props.cpu_cores_count); sysfs_show_32bit_prop(buffer, offs, "simd_count", - dev->node_props.simd_count); + dev->gpu ? dev->node_props.simd_count : 0); sysfs_show_32bit_prop(buffer, offs, "mem_banks_count", dev->node_props.mem_banks_count); sysfs_show_32bit_prop(buffer, offs, "caches_count", @@ -1139,7 +1139,7 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) /* Discrete GPUs need their own topology device list * entries. Don't assign them to CPU/APU nodes. */ - if (!gpu->device_info->needs_iommu_device && + if (!gpu->use_iommu_v2 && dev->node_props.cpu_cores_count) continue; @@ -1388,7 +1388,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) * Overwrite ATS capability according to needs_iommu_device to fix * potential missing corresponding bit in CRAT of BIOS. */ - if (dev->gpu->device_info->needs_iommu_device) + if (dev->gpu->use_iommu_v2) dev->node_props.capability |= HSA_CAP_ATS_PRESENT; else dev->node_props.capability &= ~HSA_CAP_ATS_PRESENT; @@ -1515,6 +1515,29 @@ int kfd_numa_node_to_apic_id(int numa_node_id) return kfd_cpumask_to_apic_id(cpumask_of_node(numa_node_id)); } +void kfd_double_confirm_iommu_support(struct kfd_dev *gpu) +{ + struct kfd_topology_device *dev; + + gpu->use_iommu_v2 = false; + + if (!gpu->device_info->needs_iommu_device) + return; + + down_read(&topology_lock); + + /* Only use IOMMUv2 if there is an APU topology node with no GPU + * assigned yet. This GPU will be assigned to it. + */ + list_for_each_entry(dev, &topology_device_list, list) + if (dev->node_props.cpu_cores_count && + dev->node_props.simd_count && + !dev->gpu) + gpu->use_iommu_v2 = true; + + up_read(&topology_lock); +} + #if defined(CONFIG_DEBUG_FS) int kfd_debugfs_hqds_by_device(struct seq_file *m, void *data) -- GitLab From d3bbba79eb83e8356cd3ac7b250fdd0cc4f85c01 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Mon, 24 Aug 2020 18:44:09 +0800 Subject: [PATCH 0610/1494] drm/amdgpu/gfx10: refine mgcg setting 1. enable ENABLE_CGTS_LEGACY to fix specviewperf11 random hang. 2. remove obsolete RLC_CGTT_SCLK_OVERRIDE workaround. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index d851fe80eaf4f..2db195ec8d0c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7285,10 +7285,8 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | - RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK); - - /* only for Vega10 & Raven1 */ - data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK; + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK); if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); -- GitLab From 387f3a30cc895abcdad0791fa6c6f3c1f1a69c83 Mon Sep 17 00:00:00 2001 From: Sung Lee <sung.lee@amd.com> Date: Tue, 11 Aug 2020 17:23:20 -0400 Subject: [PATCH 0611/1494] drm/amd/display: Send DISPLAY_OFF after power down on boot [WHY] update_clocks might not be called on headless adapters. This means DISPLAY_OFF may not be sent in headless cases. [HOW] If hardware is powered down on boot because it is headless (mode set does not happen on that adapter) also send DISPLAY_OFF notification. Signed-off-by: Sung Lee <sung.lee@amd.com> Reviewed-by: Yongqiang Sun <yongqiang.sun@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 10 ++++ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 +++++++++++-------- .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 2 + 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c664404a75d4f..543afa34d87aa 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -94,6 +94,15 @@ int rn_get_active_display_cnt_wa( return display_count; } +void rn_set_low_power_state(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); + /* update power state */ + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; +} + void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) @@ -516,6 +525,7 @@ static struct clk_mgr_funcs dcn21_funcs = { .init_clocks = rn_init_clocks, .enable_pme_wa = rn_enable_pme_wa, .are_clock_states_equal = rn_are_clock_states_equal, + .set_low_power_state = rn_set_low_power_state, .notify_wm_ranges = rn_notify_wm_ranges, .notify_link_rate_change = rn_notify_link_rate_change, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 95e9d05f884b2..8ca94f5061957 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1450,33 +1450,42 @@ void dcn10_init_hw(struct dc *dc) void dcn10_power_down_on_boot(struct dc *dc) { int i = 0; + struct dc_link *edp_link; - if (dc->config.power_down_display_on_boot) { - struct dc_link *edp_link = get_edp_link(dc); - - if (edp_link && - edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwseq->funcs.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwseq->funcs.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); - } else { - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - - if (link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc) && - dc->hwss.power_down) { - dc->hwss.power_down(dc); - break; - } + if (!dc->config.power_down_display_on_boot) + return; + + edp_link = get_edp_link(dc); + if (edp_link && + edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwseq->funcs.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwseq->funcs.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwss.power_down) { + dc->hwss.power_down(dc); + break; } + } } + + /* + * Call update_clocks with empty context + * to send DISPLAY_OFF + * Otherwise DISPLAY_OFF may not be asserted + */ + if (dc->clk_mgr->funcs->set_low_power_state) + dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); } void dcn10_reset_hw_ctx_wrap( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 5994d2a33c40b..947d6106f3413 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -230,6 +230,8 @@ struct clk_mgr_funcs { int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr); + void (*set_low_power_state)(struct clk_mgr *clk_mgr); + void (*init_clocks)(struct clk_mgr *clk_mgr); void (*enable_pme_wa) (struct clk_mgr *clk_mgr); -- GitLab From f8c000a59fd7ec86e20d17cbc22bb90e00ca1f23 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 10 Aug 2020 10:19:04 -0400 Subject: [PATCH 0612/1494] drm/amd/display: 3.2.99 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f3ac9e3df7607..1d9c8e09c08b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.98" +#define DC_VER "3.2.99" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 8e1f47e6bb44d148ca53cfd557f5aa1430fe6a47 Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Mon, 10 Aug 2020 14:20:16 -0400 Subject: [PATCH 0613/1494] drm/amd/display: Call DMUB for eDP power control [Why] If DMUB is used, LVTMA VBIOS call can be used to control eDP instead of tranditional transmitter control. Interface is agreed with VBIOS for eDP to use this new path to program LVTMA registers. [How] Expose DAL interface to send DMUB command for LVTMA control that VBIOS currently uses. Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/bios/command_table2.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index a91d7be5d86e0..25bdf1c38e0ad 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -920,11 +920,39 @@ static void init_enable_lvtma_control(struct bios_parser *bp) } +static void enable_lvtma_control_dmcub( + struct dc_dmub_srv *dmcub, + uint8_t uc_pwr_on) +{ + + union dmub_rb_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.cmd_common.header.type = DMUB_CMD__VBIOS; + cmd.cmd_common.header.sub_type = + DMUB_CMD__VBIOS_LVTMA_CONTROL; + cmd.cmd_common.cmd_buffer[0] = + uc_pwr_on; + + dc_dmub_srv_cmd_queue(dmcub, &cmd); + dc_dmub_srv_cmd_execute(dmcub); + dc_dmub_srv_wait_idle(dmcub); + +} + static enum bp_result enable_lvtma_control( struct bios_parser *bp, uint8_t uc_pwr_on) { enum bp_result result = BP_RESULT_FAILURE; + + if (bp->base.ctx->dc->ctx->dmub_srv && + bp->base.ctx->dc->debug.dmub_command_table) { + enable_lvtma_control_dmcub(bp->base.ctx->dmub_srv, + uc_pwr_on); + return BP_RESULT_OK; + } return result; } -- GitLab From 75f77aafe281c5d971ca876a025093ee62c8a2a8 Mon Sep 17 00:00:00 2001 From: Wayne Lin <Wayne.Lin@amd.com> Date: Wed, 15 Jul 2020 16:45:09 +0800 Subject: [PATCH 0614/1494] drm/amd/display: Send H14b-VSIF specified in HDMI [Why] Current function excludes the logic to generate H14b-VSIF. Now it constructs HF-VSIF only and causes HDMI compliace test fail. [How] According to HDMI spec, source devices shall utilize the H14b-VSIF whenever the signaling capabilities of the H14b-VSIF allow this. Here keep the logic for HF-VSIF and add H14b-VSIF construction part. Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Reviewed-by: Roman Li <Roman.Li@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- .../amd/display/modules/inc/mod_info_packet.h | 2 +- .../display/modules/info_packet/info_packet.c | 16 ++-------------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ec6710f6c8736..785f21ea35df3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4685,7 +4685,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, update_stream_signal(stream, sink); if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false); + mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); + if (stream->link->psr_settings.psr_feature_enabled) { // // should decide stream support vsc sdp colorimetry capability diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 13c57ff2abdce..1ab813b4fd14f 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -37,6 +37,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet); void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue); + struct dc_info_packet *info_packet); #endif diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 7cd8a43d18896..0fdf7a3e96dea 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -421,15 +421,13 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, ***************************************************************************** */ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue) + struct dc_info_packet *info_packet) { unsigned int length = 5; bool hdmi_vic_mode = false; uint8_t checksum = 0; uint32_t i = 0; enum dc_timing_3d_format format; - bool bALLM = (bool)ALLMEnabled; - bool bALLMVal = (bool)ALLMValue; info_packet->valid = false; format = stream->timing.timing_3d_format; @@ -442,20 +440,13 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, && format == TIMING_3D_FORMAT_NONE) hdmi_vic_mode = true; - if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode && !bALLM) + if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode) return; info_packet->sb[1] = 0x03; info_packet->sb[2] = 0x0C; info_packet->sb[3] = 0x00; - if (bALLM) { - info_packet->sb[1] = 0xD8; - info_packet->sb[2] = 0x5D; - info_packet->sb[3] = 0xC4; - info_packet->sb[4] = HF_VSIF_VERSION; - } - if (format != TIMING_3D_FORMAT_NONE) info_packet->sb[4] = (2 << 5); @@ -490,9 +481,6 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, info_packet->hb1 = 0x01; info_packet->hb2 = (uint8_t) (length); - if (bALLM) - info_packet->sb[5] = (info_packet->sb[5] & ~0x02) | (bALLMVal << 1); - checksum += info_packet->hb0; checksum += info_packet->hb1; checksum += info_packet->hb2; -- GitLab From 2d6870d31484a24e864b1649b6d28b2c9b25bf0f Mon Sep 17 00:00:00 2001 From: Jaehyun Chung <jaehyun.chung@amd.com> Date: Mon, 10 Aug 2020 16:02:47 -0400 Subject: [PATCH 0615/1494] drm/amd/display: Revert HDCP disable sequence change [Why] Revert HDCP disable sequence change that blanks stream before disabling HDCP. PSP and HW teams are currently investigating the root cause of why HDCP cannot be disabled before stream blank, which is expected to work without issues. Signed-off-by: Jaehyun Chung <jaehyun.chung@amd.com> Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 117d8aaf2a9bf..405452b736e1d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,10 +3286,10 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } - dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif + dc->hwss.blank_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- GitLab From 237070fd12967aa3a778aa46fe8eadffa7c5ab68 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Mon, 10 Aug 2020 14:02:55 -0400 Subject: [PATCH 0616/1494] drm/amd/display: Add debugfs for connector's FEC & DSC capabilities [why & how] Useful entry to understand if link has DSC or FEC capabilities, implemented to read DPCD caps stored on the link. Better than manually reading the registers with aux dpcd helper. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index f878575d17bbc..e097a60596308 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -49,6 +49,10 @@ struct dmub_debugfs_trace_entry { uint32_t param1; }; +static inline const char *yesno(bool v) +{ + return v ? "yes" : "no"; +} /* parse_write_buffer_into_params - Helper function to parse debugfs write buffer into an array * @@ -980,6 +984,71 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +/* function: Read link's DSC & FEC capabilities + * + * + * Access it with the following command (you need to specify + * connector like DP-1): + * + * cat /sys/kernel/debug/dri/0/DP-X/dp_dsc_fec_support + * + */ +static int dp_dsc_fec_support_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct drm_modeset_acquire_ctx ctx; + struct drm_device *dev = connector->dev; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + int ret = 0; + bool try_again = false; + bool is_fec_supported = false; + bool is_dsc_supported = false; + struct dpcd_caps dpcd_caps; + + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); + do { + try_again = false; + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); + if (ret) { + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) { + try_again = true; + continue; + } + } + break; + } + if (connector->status != connector_status_connected) { + ret = -ENODEV; + break; + } + dpcd_caps = aconnector->dc_link->dpcd_caps; + if (aconnector->port) { + /* aconnector sets dsc_aux during get_modes call + * if MST connector has it means it can either + * enable DSC on the sink device or on MST branch + * its connected to. + */ + if (aconnector->dsc_aux) { + is_fec_supported = true; + is_dsc_supported = true; + } + } else { + is_fec_supported = dpcd_caps.fec_cap.raw & 0x1; + is_dsc_supported = dpcd_caps.dsc_caps.dsc_basic_caps.raw[0] & 0x1; + } + } while (try_again); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + seq_printf(m, "FEC_Sink_Support: %s\n", yesno(is_fec_supported)); + seq_printf(m, "DSC_Sink_Support: %s\n", yesno(is_dsc_supported)); + + return ret; +} + /* function: read DSC status on the connector * * The read function: dp_dsc_clock_en_read @@ -1838,6 +1907,7 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, return result; } +DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support); DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(output_bpc); @@ -1963,7 +2033,8 @@ static const struct { {"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops}, {"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops}, {"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops}, - {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops} + {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops}, + {"dp_dsc_fec_support", &dp_dsc_fec_support_fops} }; #ifdef CONFIG_DRM_AMD_DC_HDCP -- GitLab From 6f77b2ac628073f647041a92b36c824ae3aef16e Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Mon, 10 Aug 2020 14:08:11 -0400 Subject: [PATCH 0617/1494] drm/amd/display: Add connector HPD trigger debugfs entry [why] Need a tool to retrigger a virtual hotplug for testing purposes with force redetection in both DC and DM. [how] Emulate handle_hpd_irq for connector as if usermode would trigger a hotplug. Perform DC link discovery, DM connector update, and DM force atomic commit. In order to trigger HPD on the connector user needs to echo 1 into "trigger_hotplug" debugfs entry on its respective connector. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Reviewed-by: Mikita Lipski <Mikita.Lipski@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index e097a60596308..94fcb086154c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1049,6 +1049,81 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data) return ret; } +/* function: Trigger virtual HPD redetection on connector + * + * This function will perform link rediscovery, link disable + * and enable, and dm connector state update. + * + * Retrigger HPD on an existing connector by echoing 1 into + * its respectful "trigger_hotplug" debugfs entry: + * + * echo 1 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug + * + */ +static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + enum dc_connection_type new_connection_type = dc_connection_none; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (!aconnector || !aconnector->dc_link) + return -EINVAL; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) + return -EINVAL; + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + if (param[0] == 1) { + mutex_lock(&aconnector->hpd_lock); + + if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type) && + new_connection_type != dc_connection_none) + goto unlock; + + if (!dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) + goto unlock; + + amdgpu_dm_update_connector_after_detect(aconnector); + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + drm_kms_helper_hotplug_event(dev); + +unlock: + mutex_unlock(&aconnector->hpd_lock); + } + + kfree(wr_buf); + return size; +} + /* function: read DSC status on the connector * * The read function: dp_dsc_clock_en_read @@ -1967,6 +2042,12 @@ static const struct file_operations dp_dsc_slice_bpg_offset_debugfs_fops = { .llseek = default_llseek }; +static const struct file_operations dp_trigger_hotplug_debugfs_fops = { + .owner = THIS_MODULE, + .write = dp_trigger_hotplug, + .llseek = default_llseek +}; + static const struct file_operations dp_link_settings_debugfs_fops = { .owner = THIS_MODULE, .read = dp_link_settings_read, -- GitLab From 5019d8f1034324f284bd3fdb26aee6e7f34b83f9 Mon Sep 17 00:00:00 2001 From: Samson Tam <Samson.Tam@amd.com> Date: Thu, 13 Aug 2020 10:50:21 -0400 Subject: [PATCH 0618/1494] drm/amd/display: Fix passive dongle mistaken as active dongle in EDID emulation [Why] dongle_type is set during dongle connection but for passive dongles, dongle_type is not set. If user starts with an active dongle and then switches to a passive dongle, it will still report as an active dongle. Trying to emulate the wrong connecter type results in display not lighting up. [How] Set dpcd_caps.dongle_type for passive dongles in detect_dp(). Signed-off-by: Samson Tam <Samson.Tam@amd.com> Reviewed-by: Joshua Aberback <Joshua.Aberback@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 405452b736e1d..437d1a7a16fe7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -763,6 +763,7 @@ static bool detect_dp(struct dc_link *link, sink_caps->signal = dp_passive_dongle_detection(link->ddc, sink_caps, audio_support); + link->dpcd_caps.dongle_type = sink_caps->dongle_type; } return true; -- GitLab From f0372d4f3f8d27599ee78fb036ca5404b954b944 Mon Sep 17 00:00:00 2001 From: Brandon Syu <Brandon.Syu@amd.com> Date: Wed, 10 Jun 2020 16:44:33 +0800 Subject: [PATCH 0619/1494] drm/amd/display: Keep current gain when ABM disable immediately [Why] When system enters s3/s0i3, backlight PWM would set user level. [How] ABM disable function add keep current gain to avoid it. Signed-off-by: Brandon Syu <Brandon.Syu@amd.com> Reviewed-by: Josip Pavic <Josip.Pavic@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 37743073772bb..c246af7c584b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -233,7 +233,7 @@ struct dc_stream_state { union stream_update_flags update_flags; }; -#define ABM_LEVEL_IMMEDIATE_DISABLE 0xFFFFFFFF +#define ABM_LEVEL_IMMEDIATE_DISABLE 255 struct dc_stream_update { struct dc_stream_state *stream; -- GitLab From a590a83d74fd4804e95f1e485d552ed7feda9ae1 Mon Sep 17 00:00:00 2001 From: Youling Tang <tangyouling@loongson.cn> Date: Sat, 22 Aug 2020 16:27:23 +0800 Subject: [PATCH 0620/1494] gpu: amd: Remove duplicate semicolons at the end of line Remove duplicate semicolons at the end of line. Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 2719ef9de3bd9..139fac0d8e76e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1103,7 +1103,7 @@ static int vcn_v2_5_mmsch_start(struct amdgpu_device *adev, { uint32_t data = 0, loop = 0, size = 0; uint64_t addr = table->gpu_addr; - struct mmsch_v1_1_init_header *header = NULL;; + struct mmsch_v1_1_init_header *header = NULL; header = (struct mmsch_v1_1_init_header *)table->cpu_addr; size = header->total_size; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index afdd4f0d9d718..b320931360893 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -467,7 +467,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] = 1; mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0; - mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; -- GitLab From 778879b9466b3d2538b56f7972046dbb80b882f3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Sun, 23 Aug 2020 15:35:36 -0700 Subject: [PATCH 0621/1494] amdgpu: fix Documentation builds for pm/ file movement Fix Documentation errors for amdgpu.rst due to file rename (moved to another subdirectory). Error: Cannot open file ../drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c WARNING: kernel-doc '../scripts/kernel-doc -rst -enable-lineno -function hwmon ../drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c' failed with return code 1 Fixes: e098bc9612c2 ("drm/amd/pm: optimize the power related source code layout") Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Evan Quan <evan.quan@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- Documentation/gpu/amdgpu.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Documentation/gpu/amdgpu.rst b/Documentation/gpu/amdgpu.rst index 0f7679a7cf542..29ca5f5feb35d 100644 --- a/Documentation/gpu/amdgpu.rst +++ b/Documentation/gpu/amdgpu.rst @@ -153,7 +153,7 @@ This section covers hwmon and power/thermal controls. HWMON Interfaces ---------------- -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: hwmon GPU sysfs Power State Interfaces @@ -164,52 +164,52 @@ GPU power controls are exposed via sysfs files. power_dpm_state ~~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: power_dpm_state power_dpm_force_performance_level ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: power_dpm_force_performance_level pp_table ~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: pp_table pp_od_clk_voltage ~~~~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: pp_od_clk_voltage pp_dpm_* ~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie pp_power_profile_mode ~~~~~~~~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: pp_power_profile_mode *_busy_percent ~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: gpu_busy_percent -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: mem_busy_percent gpu_metrics ~~~~~~~~~~~~~~~~~~~~~ -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: gpu_metrics GPU Product Information @@ -239,7 +239,7 @@ serial_number unique_id --------- -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: unique_id GPU Memory Usage Information @@ -289,7 +289,7 @@ PCIe Accounting Information pcie_bw ------- -.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +.. kernel-doc:: drivers/gpu/drm/amd/pm/amdgpu_pm.c :doc: pcie_bw pcie_replay_count -- GitLab From 817154c1a2035fdecead78873245f5b528da451e Mon Sep 17 00:00:00 2001 From: Felix Kuehling <Felix.Kuehling@amd.com> Date: Mon, 24 Aug 2020 09:55:16 -0400 Subject: [PATCH 0622/1494] drm/amdkfd: call amdgpu_amdkfd_get_unique_id directly No need to use a function pointer because the implementation is not ASIC-specific. This fixes missing support due to a missing function pointer on Arcturus. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 +-- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 4 ---- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index b0dcc800251ee..e9aee50a07908 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -777,5 +777,4 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, - .get_unique_id = amdgpu_amdkfd_get_unique_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index d08839d9491f4..1769cd4b6cef4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -727,5 +727,4 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, - .get_unique_id = amdgpu_amdkfd_get_unique_id, }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index b15b620e731b7..5ffd036857224 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -715,8 +715,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, if (kfd->kfd2kgd->get_hive_id) kfd->hive_id = kfd->kfd2kgd->get_hive_id(kfd->kgd); - if (kfd->kfd2kgd->get_unique_id) - kfd->unique_id = kfd->kfd2kgd->get_unique_id(kfd->kgd); + kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd); if (kfd_interrupt_init(kfd)) { dev_err(kfd_device, "Error initializing interrupts\n"); diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index a3c238c39ef57..017f973943447 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -214,8 +214,6 @@ struct tile_config { * * @get_hive_id: Returns hive id of current device, 0 if xgmi is not enabled * - * @get_unique_id: Returns uuid id of current device - * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -291,8 +289,6 @@ struct kfd2kgd_calls { uint32_t vmid, uint64_t page_table_base); uint32_t (*read_vmid_from_vmfault_reg)(struct kgd_dev *kgd); uint64_t (*get_hive_id)(struct kgd_dev *kgd); - uint64_t (*get_unique_id)(struct kgd_dev *kgd); - }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ -- GitLab From 332f6e1e9880c75b0c7287b8af2547ad28f389cd Mon Sep 17 00:00:00 2001 From: Felix Kuehling <Felix.Kuehling@amd.com> Date: Mon, 24 Aug 2020 10:18:37 -0400 Subject: [PATCH 0623/1494] drm/amdkfd: call amdgpu_amdkfd_get_hive_id directly No need to use a function pointer because the implementation is not ASIC-specific. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 +-- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 3 --- 6 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index a2cb317373783..1afa8f122e7d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -304,5 +304,4 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index e9aee50a07908..df0aab0fc67e6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -776,5 +776,4 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index 7e59e473a1901..e12623a9f7c2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -822,7 +822,6 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { .address_watch_get_offset = address_watch_get_offset_v10_3, .get_atc_vmid_pasid_mapping_info = NULL, .set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3, - .get_hive_id = amdgpu_amdkfd_get_hive_id, #if 0 .enable_debug_trap = enable_debug_trap_v10_3, .disable_debug_trap = disable_debug_trap_v10_3, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 1769cd4b6cef4..e6aede7251978 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -726,5 +726,4 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 5ffd036857224..e1cd6599529fb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -712,8 +712,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto kfd_doorbell_error; } - if (kfd->kfd2kgd->get_hive_id) - kfd->hive_id = kfd->kfd2kgd->get_hive_id(kfd->kgd); + kfd->hive_id = amdgpu_amdkfd_get_hive_id(kfd->kgd); kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd); diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 017f973943447..fc592f60e6a04 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -212,8 +212,6 @@ struct tile_config { * IH ring entry. This function allows the KFD ISR to get the VMID * from the fault status register as early as possible. * - * @get_hive_id: Returns hive id of current device, 0 if xgmi is not enabled - * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -288,7 +286,6 @@ struct kfd2kgd_calls { void (*set_vm_context_page_table_base)(struct kgd_dev *kgd, uint32_t vmid, uint64_t page_table_base); uint32_t (*read_vmid_from_vmfault_reg)(struct kgd_dev *kgd); - uint64_t (*get_hive_id)(struct kgd_dev *kgd); }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ -- GitLab From b04e48bcac08ae900b5ea77a86f90356f51cf26c Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Fri, 21 Aug 2020 11:57:15 -0400 Subject: [PATCH 0624/1494] drm/amd/display: Add DPCS regs for dcn3 link encoder dpcs reg are missing for dcn3 link encoder regs list, so add them. Also remove DPCSTX_DEBUG_CONFIG and RDPCSTX_DEBUG_CONFIG as they are unused and cause compile errors for dcn3 Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 2 -- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index dcbf28dd72d4a..864acd695cbbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -231,8 +231,6 @@ SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ - SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ SR(RDPCSTX0_RDPCSTX_SCRATCH) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 957fc37b971ee..8be4f21169d07 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } -- GitLab From f8646661f713fb7d33ebe404d418bd3fa55c383e Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 18 Aug 2020 19:24:03 -0400 Subject: [PATCH 0625/1494] drm/amdgpu: fix up DCHUBBUB_SDPIF_MMIO_CNTRL_0 handling Properly define this register using a relative offset rather than an absolute offset and use the proper SOC15 macros to access it. It's also DCN, not DCE, so remove it from the DCE12 header. No functional change. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +++++-- drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index e1a0ae327cf5a..a858912eb0942 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -67,6 +67,9 @@ #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH_MASK 0x00003FFFL #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT_MASK 0x3FFF0000L +#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x049d +#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 + static const u32 golden_settings_vega10_hdp[] = { @@ -1282,7 +1285,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) static void gmc_v9_0_restore_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) - WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); + WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); } /** @@ -1394,7 +1397,7 @@ static int gmc_v9_0_hw_init(void *handle) static void gmc_v9_0_save_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) - adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); + adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); } /** diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h index 27bb8c1ab8587..b6f74bf4af023 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h @@ -7376,8 +7376,6 @@ #define mmCRTC4_CRTC_DRR_CONTROL 0x0f3e #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX 2 -#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x395d -#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 // addressBlock: dce_dc_fmt4_dispdec // base address: 0x2000 -- GitLab From 9737a923c91b70779f770e7a9ab69231ea8e946a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 13:40:56 -0400 Subject: [PATCH 0626/1494] drm/amdgpu: add an asic callback for pre asic init This callback can be used by asics that need to do something special prior to calling atom asic init. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2509b1e302c00..3a9d10220ec12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -618,6 +618,8 @@ struct amdgpu_asic_funcs { uint64_t (*get_pcie_replay_count)(struct amdgpu_device *adev); /* device supports BACO */ bool (*supports_baco)(struct amdgpu_device *adev); + /* pre asic_init quirks */ + void (*pre_asic_init)(struct amdgpu_device *adev); }; /* @@ -1138,6 +1140,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_asic_need_reset_on_init(adev) (adev)->asic_funcs->need_reset_on_init((adev)) #define amdgpu_asic_get_pcie_replay_count(adev) ((adev)->asic_funcs->get_pcie_replay_count((adev))) #define amdgpu_asic_supports_baco(adev) (adev)->asic_funcs->supports_baco((adev)) +#define amdgpu_asic_pre_asic_init(adev) (adev)->asic_funcs->pre_asic_init((adev)) #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); -- GitLab From 632d9f9492a9e62a85447ba3203f8f4ca6a5de0e Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 17:02:41 -0400 Subject: [PATCH 0627/1494] drm/amdgpu: add pre_asic_init callback for SI Nothing to do for this family. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/si.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index eaa2f071b1394..455d5e366c690 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1871,6 +1871,10 @@ static int si_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk) return 0; } +static void si_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs si_asic_funcs = { .read_disabled_bios = &si_read_disabled_bios, @@ -1892,6 +1896,7 @@ static const struct amdgpu_asic_funcs si_asic_funcs = .need_reset_on_init = &si_need_reset_on_init, .get_pcie_replay_count = &si_get_pcie_replay_count, .supports_baco = &si_asic_supports_baco, + .pre_asic_init = &si_pre_asic_init, }; static uint32_t si_get_rev_id(struct amdgpu_device *adev) -- GitLab From 819515c7f30555a970559bedf1aece461dd463a6 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 17:03:39 -0400 Subject: [PATCH 0628/1494] drm/amdgpu: add pre_asic_init callback for CIK Nothing to do for this family. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/cik.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 7e71ffbca93d8..03ff8bd1fee84 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1921,6 +1921,10 @@ static uint64_t cik_get_pcie_replay_count(struct amdgpu_device *adev) return (nak_r + nak_g); } +static void cik_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs cik_asic_funcs = { .read_disabled_bios = &cik_read_disabled_bios, @@ -1941,6 +1945,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs = .need_reset_on_init = &cik_need_reset_on_init, .get_pcie_replay_count = &cik_get_pcie_replay_count, .supports_baco = &cik_asic_supports_baco, + .pre_asic_init = &cik_pre_asic_init, }; static int cik_common_early_init(void *handle) -- GitLab From cff6c7f91a340788dde3b95f471885f7bf36c6c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 17:04:31 -0400 Subject: [PATCH 0629/1494] drm/amdgpu: add pre_asic_init callback for VI Nothing to do for this family. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index a92880c678410..9bcd0eebc6d7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1068,6 +1068,10 @@ static bool vi_need_reset_on_init(struct amdgpu_device *adev) return false; } +static void vi_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs vi_asic_funcs = { .read_disabled_bios = &vi_read_disabled_bios, @@ -1088,6 +1092,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs = .need_reset_on_init = &vi_need_reset_on_init, .get_pcie_replay_count = &vi_get_pcie_replay_count, .supports_baco = &vi_asic_supports_baco, + .pre_asic_init = &vi_pre_asic_init, }; #define CZ_REV_BRISTOL(rev) \ -- GitLab From b0a2db9b482f16a91b2d67bac6b4977dc471fcab Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 16:48:17 -0400 Subject: [PATCH 0630/1494] drm/amdgpu: add pre_asic_init callback for SOC15 We need to restore some registers prior to running asic init to work around a firmware bug. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 35 +++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h | 2 ++ drivers/gpu/drm/amd/amdgpu/soc15.c | 7 ++++++ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index a858912eb0942..1ca79030e95eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1075,6 +1075,20 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } +/** + * gmc_v9_0_save_registers - saves regs + * + * @adev: amdgpu_device pointer + * + * This saves potential register values that should be + * restored upon resume + */ +static void gmc_v9_0_save_registers(struct amdgpu_device *adev) +{ + if (adev->asic_type == CHIP_RAVEN) + adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); +} + static int gmc_v9_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -1229,6 +1243,8 @@ static int gmc_v9_0_sw_init(void *handle) amdgpu_vm_manager_init(adev); + gmc_v9_0_save_registers(adev); + return 0; } @@ -1282,7 +1298,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) * * This restores register values, saved at suspend. */ -static void gmc_v9_0_restore_registers(struct amdgpu_device *adev) +void gmc_v9_0_restore_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); @@ -1386,20 +1402,6 @@ static int gmc_v9_0_hw_init(void *handle) return r; } -/** - * gmc_v9_0_save_registers - saves regs - * - * @adev: amdgpu_device pointer - * - * This saves potential register values that should be - * restored upon resume - */ -static void gmc_v9_0_save_registers(struct amdgpu_device *adev) -{ - if (adev->asic_type == CHIP_RAVEN) - adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); -} - /** * gmc_v9_0_gart_disable - gart disable * @@ -1440,8 +1442,6 @@ static int gmc_v9_0_suspend(void *handle) if (r) return r; - gmc_v9_0_save_registers(adev); - return 0; } @@ -1450,7 +1450,6 @@ static int gmc_v9_0_resume(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - gmc_v9_0_restore_registers(adev); r = gmc_v9_0_hw_init(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h index e0585e8c6c1b7..c415c439f6905 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h @@ -26,4 +26,6 @@ extern const struct amd_ip_funcs gmc_v9_0_ip_funcs; extern const struct amdgpu_ip_block_version gmc_v9_0_ip_block; + +void gmc_v9_0_restore_registers(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3c3a7adad0249..2f93c475d6d86 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1029,6 +1029,11 @@ static uint64_t soc15_get_pcie_replay_count(struct amdgpu_device *adev) return (nak_r + nak_g); } +static void soc15_pre_asic_init(struct amdgpu_device *adev) +{ + gmc_v9_0_restore_registers(adev); +} + static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, @@ -1049,6 +1054,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs = .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, .supports_baco = &soc15_supports_baco, + .pre_asic_init = &soc15_pre_asic_init, }; static const struct amdgpu_asic_funcs vega20_asic_funcs = @@ -1072,6 +1078,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs = .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, .supports_baco = &soc15_supports_baco, + .pre_asic_init = &soc15_pre_asic_init, }; static int soc15_common_early_init(void *handle) -- GitLab From a71737313e57a1885c5cba7e006be24cce0f27c2 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 19 Aug 2020 17:04:47 -0400 Subject: [PATCH 0631/1494] drm/amdgpu: add pre_asic_init callback for navi Nothing to do for this family. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 54e941e0db608..33a6d2d5fc16c 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -691,6 +691,10 @@ static void nv_init_doorbell_index(struct amdgpu_device *adev) adev->doorbell_index.sdma_doorbell_range = 20; } +static void nv_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs nv_asic_funcs = { .read_disabled_bios = &nv_read_disabled_bios, @@ -710,6 +714,7 @@ static const struct amdgpu_asic_funcs nv_asic_funcs = .need_reset_on_init = &nv_need_reset_on_init, .get_pcie_replay_count = &nv_get_pcie_replay_count, .supports_baco = &nv_asic_supports_baco, + .pre_asic_init = &nv_pre_asic_init, }; static int nv_common_early_init(void *handle) -- GitLab From 4d2997ab2182fc58e93d33819ea2e2a0a87e6bb9 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 24 Aug 2020 12:34:10 -0400 Subject: [PATCH 0632/1494] drm/amdgpu: add a wrapper for atom asic_init This allows us to add asic specific workarounds for atom asic init while keeping the adev specifics out of the atombios parser code. Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 64d6e58bcb0a8..5a948edcc93c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -653,6 +653,20 @@ static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev, BUG(); } +/** + * amdgpu_device_asic_init - Wrapper for atom asic_init + * + * @dev: drm_device pointer + * + * Does any asic specific work and then calls atom asic init. + */ +static int amdgpu_device_asic_init(struct amdgpu_device *adev) +{ + amdgpu_asic_pre_asic_init(adev); + + return amdgpu_atom_asic_init(adev->mode_info.atom_context); +} + /** * amdgpu_device_vram_scratch_init - allocate the VRAM scratch page * @@ -3201,7 +3215,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, goto failed; } DRM_INFO("GPU posting now...\n"); - r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + r = amdgpu_device_asic_init(adev); if (r) { dev_err(adev->dev, "gpu post error!\n"); goto failed; @@ -3549,7 +3563,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) /* post card */ if (amdgpu_device_need_post(adev)) { - r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + r = amdgpu_device_asic_init(adev); if (r) dev_err(adev->dev, "amdgpu asic init failed\n"); } @@ -4106,7 +4120,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (need_full_reset) { /* post card */ - if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) + if (amdgpu_device_asic_init(tmp_adev)) dev_warn(tmp_adev->dev, "asic atom init failed!"); if (!r) { -- GitLab From 9ddcbf1f4c2d8dadd577c7ee5ae3a5168ebfae96 Mon Sep 17 00:00:00 2001 From: Alex Dewar <alex.dewar90@gmail.com> Date: Mon, 24 Aug 2020 22:15:25 +0100 Subject: [PATCH 0633/1494] drm/amd/pm: use kmemdup() rather than kmalloc+memcpy Issue identified with Coccinelle. Signed-off-by: Alex Dewar <alex.dewar90@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c index f56a3cbdfa3b3..1f90825394575 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c @@ -890,14 +890,12 @@ static int init_powerplay_table_information( power_saving_clock_count); } - pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmemdup(&(powerplay_table->smcPPTable), + sizeof(PPTable_t), + GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; - memcpy(pptable_information->smc_pptable, - &(powerplay_table->smcPPTable), - sizeof(PPTable_t)); - result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); if (result) -- GitLab From c56c90f41343c0ec9606d7d297110ecc84c7f891 Mon Sep 17 00:00:00 2001 From: Tao Zhou <tao.zhou1@amd.com> Date: Tue, 28 Jul 2020 12:44:59 +0800 Subject: [PATCH 0634/1494] drm/amdgpu: add asd fw check before loading asd asd is not ready for some ASICs in early stage, and psp->asd_fw is more generic than ASIC name in the check. Signed-off-by: Tao Zhou <tao.zhou1@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Jiansong Chen <Jiansong.Chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c22fb0194df78..d6c38e24f130d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -522,8 +522,7 @@ static int psp_asd_load(struct psp_context *psp) * add workaround to bypass it for sriov now. * TODO: add version check to make it common */ - if (amdgpu_sriov_vf(psp->adev) || - (psp->adev->asic_type == CHIP_NAVY_FLOUNDER)) + if (amdgpu_sriov_vf(psp->adev) || !psp->asd_fw) return 0; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); -- GitLab From 1887544d4ddd89fab8a76d150b46c329e7925da1 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 25 Aug 2020 10:35:11 +0800 Subject: [PATCH 0635/1494] drm/amd/pm: correct the thermal alert temperature limit settings Do the maths in celsius degree. This can fix the issues caused by the changes below: drm/amd/pm: correct Vega20 swctf limit setting drm/amd/pm: correct Vega12 swctf limit setting drm/amd/pm: correct Vega10 swctf limit setting Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 15 +++++++-------- .../drm/amd/pm/powerplay/hwmgr/vega12_thermal.c | 15 +++++++-------- .../drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 15 +++++++-------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index ce9514c881ec2..d572ba4ec9b16 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -367,14 +367,13 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, (struct phm_ppt_v2_information *)(hwmgr->pptable); struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > tdp_table->usSoftwareShutdownTemp) high = tdp_table->usSoftwareShutdownTemp; @@ -385,8 +384,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index e755fc0c98860..7ace439dcde7a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -173,14 +173,13 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -191,8 +190,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index a9bc9d16641a2..364162ddaa9c6 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -243,14 +243,13 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -261,8 +260,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); -- GitLab From 5436ab94cd946006271f4e80de90b9a2276e93e3 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Mon, 17 Aug 2020 15:48:21 +0800 Subject: [PATCH 0636/1494] drm/amdkfd: fix set kfd node ras properties value The ctx->features are new RAS implementation which is only available for Vega20 and onwards, it is not available for vega10, vega10 should follow legacy ECC implementation. Changed from V1: wrap function to initialize kfd node properties Changed from V2: remove wrap function and SDMA SRAM ECC check Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 28 +++++++++++++++-------- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 24 +++++++++---------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3a9d10220ec12..4009d2e307275 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -986,6 +986,7 @@ struct amdgpu_device { atomic_t throttling_logging_enabled; struct ratelimit_state throttling_logging_rs; + uint32_t ras_features; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 9b718749919a9..e5ea14774c0cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1963,6 +1963,17 @@ int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev, return 0; } +static int amdgpu_ras_check_asic_type(struct amdgpu_device *adev) +{ + if (adev->asic_type != CHIP_VEGA10 && + adev->asic_type != CHIP_VEGA20 && + adev->asic_type != CHIP_ARCTURUS && + adev->asic_type != CHIP_SIENNA_CICHLID) + return 1; + else + return 0; +} + /* * check hardware's ras ability which will be saved in hw_supported. * if hardware does not support ras, we can skip some ras initializtion and @@ -1979,9 +1990,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = 0; if (amdgpu_sriov_vf(adev) || !adev->is_atom_fw || - (adev->asic_type != CHIP_VEGA20 && - adev->asic_type != CHIP_ARCTURUS && - adev->asic_type != CHIP_SIENNA_CICHLID)) + amdgpu_ras_check_asic_type(adev)) return; if (amdgpu_atomfirmware_mem_ecc_supported(adev)) { @@ -2003,6 +2012,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = amdgpu_ras_enable == 0 ? 0 : *hw_supported & amdgpu_ras_mask; + adev->ras_features = *supported; } int amdgpu_ras_init(struct amdgpu_device *adev) @@ -2025,9 +2035,9 @@ int amdgpu_ras_init(struct amdgpu_device *adev) amdgpu_ras_check_supported(adev, &con->hw_supported, &con->supported); - if (!con->hw_supported) { + if (!con->hw_supported || (adev->asic_type == CHIP_VEGA10)) { r = 0; - goto err_out; + goto release_con; } con->features = 0; @@ -2038,25 +2048,25 @@ int amdgpu_ras_init(struct amdgpu_device *adev) if (adev->nbio.funcs->init_ras_controller_interrupt) { r = adev->nbio.funcs->init_ras_controller_interrupt(adev); if (r) - goto err_out; + goto release_con; } if (adev->nbio.funcs->init_ras_err_event_athub_interrupt) { r = adev->nbio.funcs->init_ras_err_event_athub_interrupt(adev); if (r) - goto err_out; + goto release_con; } if (amdgpu_ras_fs_init(adev)) { r = -EINVAL; - goto err_out; + goto release_con; } dev_info(adev->dev, "RAS INFO: ras initialized successfully, " "hardware ability[%x] ras_mask[%x]\n", con->hw_supported, con->supported); return 0; -err_out: +release_con: amdgpu_ras_set_context(adev, NULL); kfree(con); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5e8eb783d2d52..2b31c3066aaae 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1239,7 +1239,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) void *crat_image = NULL; size_t image_size = 0; int proximity_domain; - struct amdgpu_ras *ctx; + struct amdgpu_device *adev; INIT_LIST_HEAD(&temp_topology_device_list); @@ -1404,19 +1404,17 @@ int kfd_topology_add_device(struct kfd_dev *gpu) dev->node_props.max_waves_per_simd = 10; } - ctx = amdgpu_ras_get_context((struct amdgpu_device *)(dev->gpu->kgd)); - if (ctx) { - /* kfd only concerns sram ecc on GFX/SDMA and HBM ecc on UMC */ - dev->node_props.capability |= - (((ctx->features & BIT(AMDGPU_RAS_BLOCK__SDMA)) != 0) || - ((ctx->features & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0)) ? - HSA_CAP_SRAM_EDCSUPPORTED : 0; - dev->node_props.capability |= ((ctx->features & BIT(AMDGPU_RAS_BLOCK__UMC)) != 0) ? - HSA_CAP_MEM_EDCSUPPORTED : 0; - - dev->node_props.capability |= (ctx->features != 0) ? + adev = (struct amdgpu_device *)(dev->gpu->kgd); + /* kfd only concerns sram ecc on GFX and HBM ecc on UMC */ + dev->node_props.capability |= + ((adev->ras_features & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0) ? + HSA_CAP_SRAM_EDCSUPPORTED : 0; + dev->node_props.capability |= ((adev->ras_features & BIT(AMDGPU_RAS_BLOCK__UMC)) != 0) ? + HSA_CAP_MEM_EDCSUPPORTED : 0; + + if (adev->asic_type != CHIP_VEGA10) + dev->node_props.capability |= (adev->ras_features != 0) ? HSA_CAP_RASEVENTNOTIFY : 0; - } kfd_debug_print_topology(); -- GitLab From 22dd44f47cf74c2891c359976f308941a3736605 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Tue, 25 Aug 2020 15:39:57 +0800 Subject: [PATCH 0637/1494] drm/amdgpu: use MODE1 reset for navy_flounder by default Switch default gpu reset method to MODE1 for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 33a6d2d5fc16c..4d14023562627 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -364,6 +364,7 @@ nv_asic_reset_method(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: return AMD_RESET_METHOD_MODE1; default: if (smu_baco_is_support(smu)) -- GitLab From 6178aed011a31b7d242b80ed3e83fcc9b67444e1 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Date: Fri, 14 Aug 2020 11:49:13 -0400 Subject: [PATCH 0638/1494] drm/amd/powerplay: Fix hardmins not being sent to SMU for RV [Why] DC uses these to raise the voltage as needed for higher dispclk/dppclk and to ensure that we have enough bandwidth to drive the displays. There's a bug preventing these from actuially sending messages since it's checking the actual clock (which is 0) instead of the incoming clock (which shouldn't be 0) when deciding to send the hardmin. [How] Check the clocks != 0 instead of the actual clocks. Fixes: 9ed9203c3ee7 ("drm/amd/powerplay: rv dal-pplib interface refactor powerplay part") Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index c9cfe90a29471..9ee8cf8267c88 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -204,8 +204,7 @@ static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clo { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->need_min_deep_sleep_dcefclk && - smu10_data->deep_sleep_dcefclk != clock) { + if (clock && smu10_data->deep_sleep_dcefclk != clock) { smu10_data->deep_sleep_dcefclk = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, @@ -219,8 +218,7 @@ static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t c { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->dcf_actual_hard_min_freq && - smu10_data->dcf_actual_hard_min_freq != clock) { + if (clock && smu10_data->dcf_actual_hard_min_freq != clock) { smu10_data->dcf_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinDcefclkByFreq, @@ -234,8 +232,7 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t cloc { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->f_actual_hard_min_freq && - smu10_data->f_actual_hard_min_freq != clock) { + if (clock && smu10_data->f_actual_hard_min_freq != clock) { smu10_data->f_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinFclkByFreq, -- GitLab From c997e8e26c001c1a92200f44027f6c915c8f5487 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 24 Aug 2020 20:17:30 -0400 Subject: [PATCH 0639/1494] drm/amdgpu: report DC not supported if virtual display is enabled (v2) Virtual display is non-atomic so report false to avoid checking atomic state and other atomic things at runtime. v2: squash into the sr-iov check Acked-by: Nirmoy Das <nirmoy.das@amd.com> Acked-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5a948edcc93c8..8f37f9f99105f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2861,7 +2861,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) */ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) { - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev) || adev->enable_virtual_display) return false; return amdgpu_device_asic_has_dc_support(adev->asic_type); -- GitLab From cf851f3ff891ff8cb204e7118682d55429c6fb96 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 25 Aug 2020 11:43:45 -0400 Subject: [PATCH 0640/1494] drm/amdgpu: Fix buffer overflow in INFO ioctl The values for "se_num" and "sh_num" come from the user in the ioctl. They can be in the 0-255 range but if they're more than AMDGPU_GFX_MAX_SE (4) or AMDGPU_GFX_MAX_SH_PER_SE (2) then it results in an out of bounds read. Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Acked-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d125c4b2af53a..deba6873bfeac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -669,8 +669,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file * in the bitfields */ if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) se_num = 0xffffffff; + else if (se_num >= AMDGPU_GFX_MAX_SE) + return -EINVAL; if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) sh_num = 0xffffffff; + else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) + return -EINVAL; if (info->read_mmr_reg.count > 128) return -EINVAL; -- GitLab From ec314c4612653aaf6e8d6a7c23fed9b3f7a0039f Mon Sep 17 00:00:00 2001 From: Wayne Lin <Wayne.Lin@amd.com> Date: Tue, 18 Aug 2020 11:19:42 +0800 Subject: [PATCH 0641/1494] drm/amd/display: Retry AUX write when fail occurs [Why] In dm_dp_aux_transfer() now, we forget to handle AUX_WR fail cases. We suppose every write wil get done successfully and hence some AUX commands might not sent out indeed. [How] Check if AUX_WR success. If not, retry it. Signed-off-by: Wayne Lin <Wayne.Lin@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index bbc20834c643b..bd477a166015d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -67,7 +67,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, &operation_result); - if (payload.write) + if (payload.write && result >= 0) result = msg->size; if (result < 0) -- GitLab From faeefe4e54d65c06dd23e5486e5423c564c4a12a Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 26 Aug 2020 14:11:52 +0800 Subject: [PATCH 0642/1494] drm/amdgpu: disable runtime pm for navy_flounder Disable runtime pm for navy_flounder temporarily. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index deba6873bfeac..b4077be9ba698 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -170,6 +170,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) case CHIP_VEGA20: case CHIP_ARCTURUS: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: /* enable runpm if runpm=1 */ if (amdgpu_runtime_pm > 0) adev->runpm = true; -- GitLab From 08572451b4b1783fdff787b0188c4d50fdf96b81 Mon Sep 17 00:00:00 2001 From: Dinghao Liu <dinghao.liu@zju.edu.cn> Date: Wed, 26 Aug 2020 21:24:58 +0800 Subject: [PATCH 0643/1494] drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init When amdgpu_display_modeset_create_props() fails, state and state->context should be freed to prevent memleak. It's the same when amdgpu_dm_audio_init() fails. Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 785f21ea35df3..e2e7138c4e3f3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2905,12 +2905,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) &dm_atomic_state_funcs); r = amdgpu_display_modeset_create_props(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } r = amdgpu_dm_audio_init(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } return 0; } -- GitLab From 0bbb5462d30cb1a99d442a7d4b4bc5302fe24821 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Wed, 26 Aug 2020 15:43:42 +0800 Subject: [PATCH 0644/1494] drm/amdgpu: correct SE number for arcturus gfx ras When resetting EDC related register, all CUs needs to be visited, otherwise, garbage data from EDC register of missed SEs would present. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c index 46351db369226..bd85aed3523a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c @@ -57,10 +57,10 @@ static const struct soc15_reg_entry gfx_v9_4_edc_counter_regs[] = { /* SPI */ { SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT), 0, 4, 1 }, /* SQ */ - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT), 0, 4, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT), 0, 8, 16 }, /* SQC */ { SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 0, 4, 6 }, { SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 0, 4, 6 }, -- GitLab From ea6e3c31548ebd9be3d2405c680cac1706e7c7b2 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich <frank-w@public-files.de> Date: Wed, 19 Aug 2020 10:17:46 +0200 Subject: [PATCH 0645/1494] dt-bindings: mediatek: add mt7623 display-nodes mt7623 uses mt2701/mt8173 for drm, but have own compatibles Signed-off-by: Frank Wunderlich <frank-w@public-files.de> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- .../devicetree/bindings/display/mediatek/mediatek,disp.txt | 2 +- .../devicetree/bindings/display/mediatek/mediatek,dpi.txt | 2 +- .../devicetree/bindings/display/mediatek/mediatek,dsi.txt | 4 ++-- .../devicetree/bindings/display/mediatek/mediatek,hdmi.txt | 4 ++++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt index b91e709db7a4e..121220745d465 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt @@ -43,7 +43,7 @@ Required properties (all function blocks): "mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt "mediatek,<chip>-disp-mutex" - display mutex "mediatek,<chip>-disp-od" - overdrive - the supported chips are mt2701, mt2712 and mt8173. + the supported chips are mt2701, mt7623, mt2712 and mt8173. - reg: Physical base address and length of the function block register space - interrupts: The interrupt signal from the function block (required, except for merge and split function blocks). diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt index 77def4456706b..dc1ebd13cc880 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt @@ -7,7 +7,7 @@ output bus. Required properties: - compatible: "mediatek,<chip>-dpi" - the supported chips are mt2701 , mt8173 and mt8183. + the supported chips are mt2701, mt7623, mt8173 and mt8183. - reg: Physical base address and length of the controller's registers - interrupts: The interrupt signal from the function block. - clocks: device clocks diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt index 8e4729de8c85d..f06f24d405a5a 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt @@ -7,7 +7,7 @@ channel output. Required properties: - compatible: "mediatek,<chip>-dsi" - the supported chips are mt2701, mt8173 and mt8183. +- the supported chips are mt2701, mt7623, mt8173 and mt8183. - reg: Physical base address and length of the controller's registers - interrupts: The interrupt signal from the function block. - clocks: device clocks @@ -26,7 +26,7 @@ The MIPI TX configuration module controls the MIPI D-PHY. Required properties: - compatible: "mediatek,<chip>-mipi-tx" - the supported chips are mt2701, mt8173 and mt8183. +- the supported chips are mt2701, 7623, mt8173 and mt8183. - reg: Physical base address and length of the controller's registers - clocks: PLL reference clock - clock-output-names: name of the output clock line to the DSI encoder diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt index 7b124242b0c55..6b1c586403e44 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt @@ -6,6 +6,7 @@ its parallel input. Required properties: - compatible: Should be "mediatek,<chip>-hdmi". +- the supported chips are mt2701, mt7623 and mt8173 - reg: Physical base address and length of the controller's registers - interrupts: The interrupt signal from the function block. - clocks: device clocks @@ -32,6 +33,7 @@ The HDMI CEC controller handles hotplug detection and CEC communication. Required properties: - compatible: Should be "mediatek,<chip>-cec" +- the supported chips are mt7623 and mt8173 - reg: Physical base address and length of the controller's registers - interrupts: The interrupt signal from the function block. - clocks: device clock @@ -44,6 +46,7 @@ The Mediatek's I2C controller is used to interface with I2C devices. Required properties: - compatible: Should be "mediatek,<chip>-hdmi-ddc" +- the supported chips are mt7623 and mt8173 - reg: Physical base address and length of the controller's registers - clocks: device clock - clock-names: Should be "ddc-i2c". @@ -56,6 +59,7 @@ output and drives the HDMI pads. Required properties: - compatible: "mediatek,<chip>-hdmi-phy" +- the supported chips are mt2701, mt7623 and mt8173 - reg: Physical base address and length of the module's registers - clocks: PLL reference clock - clock-names: must contain "pll_ref" -- GitLab From 7bde3c0c172858423dc54b6f2c6aabd1e2dda569 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich <frank-w@public-files.de> Date: Wed, 19 Aug 2020 10:17:47 +0200 Subject: [PATCH 0646/1494] drm/mediatek: Add ddp routing for mt7623 on BPi-R2/mt7623 main-path have to be routed to DPI0 (hdmi) instead of DSI0 using compatible "mt7623-mmsys" already defined in dts Signed-off-by: Frank Wunderlich <frank-w@public-files.de> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 040a8f393fe24..2350e3200b591 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -74,6 +74,19 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { DDP_COMPONENT_DPI0, }; +static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main[] = { + DDP_COMPONENT_OVL0, + DDP_COMPONENT_RDMA0, + DDP_COMPONENT_COLOR0, + DDP_COMPONENT_BLS, + DDP_COMPONENT_DPI0, +}; + +static const enum mtk_ddp_comp_id mt7623_mtk_ddp_ext[] = { + DDP_COMPONENT_RDMA1, + DDP_COMPONENT_DSI0, +}; + static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main[] = { DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, @@ -127,6 +140,14 @@ static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { .shadow_register = true, }; +static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = { + .main_path = mt7623_mtk_ddp_main, + .main_len = ARRAY_SIZE(mt7623_mtk_ddp_main), + .ext_path = mt7623_mtk_ddp_ext, + .ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext), + .shadow_register = true, +}; + static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { .main_path = mt2712_mtk_ddp_main, .main_len = ARRAY_SIZE(mt2712_mtk_ddp_main), @@ -422,6 +443,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { static const struct of_device_id mtk_drm_of_ids[] = { { .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data}, + { .compatible = "mediatek,mt7623-mmsys", + .data = &mt7623_mmsys_driver_data}, { .compatible = "mediatek,mt2712-mmsys", .data = &mt2712_mmsys_driver_data}, { .compatible = "mediatek,mt8173-mmsys", -- GitLab From cd6da0b113512b15a4d35f355f9ecd8858297369 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 26 Aug 2020 09:47:27 +0100 Subject: [PATCH 0647/1494] drm/mgag200: fix spelling mistake "expeced" -> "expected" There is a spelling mistake in a drm_warn message. Fix it. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200826084727.42703-1-colin.king@canonical.com --- drivers/gpu/drm/mgag200/mgag200_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index b282b0e42c2df..771b26aeee197 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -168,7 +168,7 @@ static void mgag200_g200_interpret_bios(struct mga_device *mdev, return; } if (pins_len != expected_length[version]) { - drm_warn(dev, "Unexpected BIOS PInS size: %d expeced: %d\n", + drm_warn(dev, "Unexpected BIOS PInS size: %d expected: %d\n", pins_len, expected_length[version]); return; } -- GitLab From 97e48c1d60a7237f0e7fb0a33d2a8bc53a23db93 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Mon, 10 Aug 2020 10:59:52 +0100 Subject: [PATCH 0648/1494] drm/i915/vlv_dsi_pll: fix spelling mistake "Cant" -> "Can't" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a spelling mistake in a drm_err message. Fix it. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200810095952.60968-1-colin.king@canonical.com --- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index d0a5143015757..4070b00c36909 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -483,7 +483,7 @@ int bxt_dsi_pll_compute(struct intel_encoder *encoder, if (dsi_ratio < dsi_ratio_min || dsi_ratio > dsi_ratio_max) { drm_err(&dev_priv->drm, - "Cant get a suitable ratio from DSI PLL ratios\n"); + "Can't get a suitable ratio from DSI PLL ratios\n"); return -ECHRNG; } else drm_dbg_kms(&dev_priv->drm, "DSI PLL calculation is Done!!\n"); -- GitLab From 3d14a79b5134173ced9364411800ea60029e785e Mon Sep 17 00:00:00 2001 From: Kevin Wang <kevin1.wang@amd.com> Date: Mon, 24 Aug 2020 16:50:12 +0800 Subject: [PATCH 0649/1494] drm/amd/pm: fix is_dpm_running() run error on 32bit system v1: the C type "unsigned long" size is 32bit on 32bit system, it will cause code logic error, so replace it with "uint64_t". v2: remove duplicate cast operation. Signed-off-by: Kevin <kevin1.wang@amd.com> Suggest-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Jiansong Chen <Jiansong.Chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 10 +++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 10 +++++++--- .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 8347b1f2509fb..59b245c6c4d7b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1844,10 +1844,14 @@ static bool arcturus_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 72f3d68691d8d..cc67d5c60f3d0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1345,10 +1345,14 @@ static bool navi10_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 66d655958a789..b48ac591db8b2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1150,10 +1150,14 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } -- GitLab From e1b08ae52b25f7d77a030bbaff745d4818344598 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 25 Aug 2020 13:51:29 +0800 Subject: [PATCH 0650/1494] drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting Normally softwareshutdowntemp should be greater than Thotspotlimit. However, on some VEGA10 ASIC, the softwareshutdowntemp is 91C while Thotspotlimit is 105C. This seems not right and may trigger some false alarms. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index d572ba4ec9b16..952cd3d7240e3 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -374,8 +374,18 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, /* compare them in unit celsius degree */ if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - if (high > tdp_table->usSoftwareShutdownTemp) - high = tdp_table->usSoftwareShutdownTemp; + + /* + * As a common sense, usSoftwareShutdownTemp should be bigger + * than ThotspotLimit. For any invalid usSoftwareShutdownTemp, + * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP + * to avoid false alarms. + */ + if ((tdp_table->usSoftwareShutdownTemp > + range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) { + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; + } if (low > high) return -EINVAL; -- GitLab From 6c4d1f43ed0edeee7f38069619cc8c43459a6171 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 11:28:19 +0800 Subject: [PATCH 0651/1494] drm/amd/pm: suppress static checker warning Suppress the warning below: drivers/gpu/drm/amd/amdgpu/../pm/powerplay/hwmgr/hardwaremanager.c:274 phm_check_smc_update_required_for_display_configuration() warn: signedness bug returning '(-22)' Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c index 9454ab50f9a12..1f9b9facdf1f4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -271,7 +271,10 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) { - PHM_FUNC_CHECK(hwmgr); + if (hwmgr == NULL || + hwmgr->hwmgr_func == NULL) + return false; + if (hwmgr->pp_one_vf) return false; -- GitLab From 4cd2a96d3a0ac6b07c443e904f5b8a52f2471571 Mon Sep 17 00:00:00 2001 From: Jiawei <Jiawei.Gu@amd.com> Date: Thu, 27 Aug 2020 10:07:52 +0800 Subject: [PATCH 0652/1494] drm/amdgpu: simplify hw status clear/set logic Optimize code to iterate less loops in amdgpu_device_ip_reinit_early_sriov() Signed-off-by: Jiawei <Jiawei.Gu@amd.com> Reviewed-by: Emily.Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8f37f9f99105f..696a61cc3ac66 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2598,17 +2598,16 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; - for (i = 0; i < adev->num_ip_blocks; i++) - adev->ip_blocks[i].status.hw = false; - - for (i = 0; i < ARRAY_SIZE(ip_order); i++) { + for (i = 0; i < adev->num_ip_blocks; i++) { int j; struct amdgpu_ip_block *block; - for (j = 0; j < adev->num_ip_blocks; j++) { - block = &adev->ip_blocks[j]; + block = &adev->ip_blocks[i]; + block->status.hw = false; - if (block->version->type != ip_order[i] || + for (j = 0; j < ARRAY_SIZE(ip_order); j++) { + + if (block->version->type != ip_order[j] || !block->status.valid) continue; -- GitLab From ce7e5a6e130d4fe76e09bd082e98b65f630aa474 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Thu, 27 Aug 2020 14:31:20 +0800 Subject: [PATCH 0653/1494] drm/amd/pm: enable MP0 DPM for sienna_cichlid Enable MP0 clock DPM for sienna_cichlid. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index b48ac591db8b2..b67931fd64b4a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -68,7 +68,8 @@ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) + FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)) #define SMU_11_0_7_GFX_BUSY_THRESHOLD 15 @@ -230,6 +231,7 @@ sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) + | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) | FEATURE_MASK(FEATURE_DS_FCLK_BIT) -- GitLab From 177e38a48168f9e70faaec34df053d2f8134ede6 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman <sandy.8925@gmail.com> Date: Thu, 27 Aug 2020 17:07:33 +0530 Subject: [PATCH 0654/1494] drm/amdgpu: Specify get_argument function for ci_smu_funcs Starting in Linux 5.8, the graphics and memory clock frequency were not being reported for CIK cards. This is a regression, since they were reported correctly in Linux 5.7. After investigation, I discovered that the smum_send_msg_to_smc() function, attempts to call the corresponding get_argument() function of ci_smu_funcs. However, the get_argument() function is not defined in ci_smu_funcs. This patch fixes the bug by specifying the correct get_argument() function. Fixes: a0ec225633d9f6 ("drm/amd/powerplay: unified interfaces for message issuing and response checking") Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c index c18169aa59ce5..e4d1f3d66ef48 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -37,6 +37,7 @@ #include "cgs_common.h" #include "atombios.h" #include "pppcielanes.h" +#include "smu7_smumgr.h" #include "smu/smu_7_0_1_d.h" #include "smu/smu_7_0_1_sh_mask.h" @@ -2948,6 +2949,7 @@ const struct pp_smumgr_func ci_smu_funcs = { .request_smu_load_specific_fw = NULL, .send_msg_to_smc = ci_send_msg_to_smc, .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, .download_pptable_settings = NULL, .upload_pptable_settings = NULL, .get_offsetof = ci_get_offsetof, -- GitLab From 3425740adf97b2258966ee3f0d871fd5cc314028 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman <sandy.8925@gmail.com> Date: Thu, 27 Aug 2020 18:43:37 +0530 Subject: [PATCH 0655/1494] drm/amdgpu: Fix bug in reporting voltage for CIK On my R9 390, the voltage was reported as a constant 1000 mV. This was due to a bug in smu7_hwmgr.c, in the smu7_read_sensor() function, where some magic constants were used in a condition, to determine whether the voltage should be read from PLANE2_VID or PLANE1_VID. The VDDC mask was incorrectly used, instead of the VDDGFX mask. This patch changes the code to use the correct defined constants (and apply the correct bitshift), thus resulting in correct voltage reporting. Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index ffe05b7cc1f0a..4a3b64aa21ceb 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -3581,7 +3581,8 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, case AMDGPU_PP_SENSOR_GPU_POWER: return smu7_get_gpu_power(hwmgr, (uint32_t *)value); case AMDGPU_PP_SENSOR_VDDGFX: - if ((data->vr_config & 0xff) == 0x2) + if ((data->vr_config & VRCONF_VDDGFX_MASK) == + (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT)) val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); else -- GitLab From 5150dd85bdfa08143cacf1b4249121651bed3c35 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng <kai.heng.feng@canonical.com> Date: Wed, 26 Aug 2020 01:33:48 +0800 Subject: [PATCH 0656/1494] drm/radeon: Prefer lower feedback dividers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") fixed screen flicker for HP Compaq nx9420 but breaks other laptops like Asus X50SL. Turns out we also need to favor lower feedback dividers. Users confirmed this change fixes the regression and doesn't regress the original fix. Fixes: 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") BugLink: https://bugs.launchpad.net/bugs/1791312 BugLink: https://bugs.launchpad.net/bugs/1861554 Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e0ae911ef427d..7b69d6dfe44a3 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -933,7 +933,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, /* get matching reference and feedback divider */ *ref_div = min(max(den/post_div, 1u), ref_div_max); - *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); + *fb_div = max(nom * *ref_div * post_div / den, 1u); /* limit fb divider to its maximum */ if (*fb_div > fb_div_max) { -- GitLab From 3bc46a083fa9f475dd2e0ab8717d9839b070b8d9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Sat, 4 Jul 2020 15:38:03 +0200 Subject: [PATCH 0657/1494] drm/sun4i: lvds: Invert the LVDS polarity The LVDS controller can invert the polarity / lanes of the LVDS output. The default polarity causes some issues on some panels. However, U-Boot has always used the opposite polarity without any reported issue, and the only currently supported LVDS panel in-tree (the TBS A711) seems to be able to work with both settings. Let's just use the same polarity than U-Boot to be more consistent and hopefully support all the panels. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Reviewed-by: Chen-Yu Tsai <wens@csie.org> Cc: Ondrej Jirman <megous@megous.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200704133803.37330-1-maxime@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index ae177b2bcf4b9..09ad8506a81be 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -474,9 +474,7 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) | SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)); - reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0 | - SUN4I_TCON0_LVDS_IF_DATA_POL_NORMAL | - SUN4I_TCON0_LVDS_IF_CLK_POL_NORMAL; + reg = SUN4I_TCON0_LVDS_IF_CLK_SEL_TCON0; if (sun4i_tcon_get_pixel_depth(encoder) == 24) reg |= SUN4I_TCON0_LVDS_IF_BITWIDTH_24BITS; else -- GitLab From be2dd718ed4ad302708464d6f60a228a7eb7e344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Tue, 25 Aug 2020 10:13:29 -0700 Subject: [PATCH 0658/1494] drm/i915/display: Compute has_drrs after compute has_psr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRRS and PSR can't be enable together, so giving preference to PSR as it allows more power-savings by complete shutting down display, so to guarantee this, it should compute DRRS state after compute PSR. Cc: Srinivas K <srinivasx.k@intel.com> Cc: Hariom Pandey <hariom.pandey@intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200825171331.17971-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 52 +++++++++++++++---------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d6295eb20b636..82525cbeafe2d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2575,6 +2575,34 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); } +static void +intel_dp_drrs_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *pipe_config, + int output_bpp, bool constant_n) +{ + struct intel_connector *intel_connector = intel_dp->attached_connector; + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + /* + * DRRS and PSR can't be enable together, so giving preference to PSR + * as it allows more power-savings by complete shutting down display, + * so to guarantee this, intel_dp_drrs_compute_config() must be called + * after intel_psr_compute_config(). + */ + if (pipe_config->has_psr) + return; + + if (!intel_connector->panel.downclock_mode || + dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) + return; + + pipe_config->has_drrs = true; + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, + intel_connector->panel.downclock_mode->clock, + pipe_config->port_clock, &pipe_config->dp_m2_n2, + constant_n, pipe_config->fec_enable); +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2605,7 +2633,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, if (ret) return ret; - pipe_config->has_drrs = false; if (!intel_dp_port_has_audio(dev_priv, port)) pipe_config->has_audio = false; else if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) @@ -2657,21 +2684,12 @@ intel_dp_compute_config(struct intel_encoder *encoder, &pipe_config->dp_m_n, constant_n, pipe_config->fec_enable); - if (intel_connector->panel.downclock_mode != NULL && - dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { - pipe_config->has_drrs = true; - intel_link_compute_m_n(output_bpp, - pipe_config->lane_count, - intel_connector->panel.downclock_mode->clock, - pipe_config->port_clock, - &pipe_config->dp_m2_n2, - constant_n, pipe_config->fec_enable); - } - if (!HAS_DDI(dev_priv)) intel_dp_set_clock(encoder, pipe_config); intel_psr_compute_config(intel_dp, pipe_config); + intel_dp_drrs_compute_config(intel_dp, pipe_config, output_bpp, + constant_n); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); @@ -7722,16 +7740,10 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (!crtc_state->has_drrs) { - drm_dbg_kms(&dev_priv->drm, "Panel doesn't support DRRS\n"); + if (!crtc_state->has_drrs) return; - } - if (dev_priv->psr.enabled) { - drm_dbg_kms(&dev_priv->drm, - "PSR enabled. Not enabling DRRS.\n"); - return; - } + drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); mutex_lock(&dev_priv->drrs.mutex); if (dev_priv->drrs.dp) { -- GitLab From 8040fefa387c5aea14d2f5753d7fbdd3344f2b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Tue, 25 Aug 2020 10:13:30 -0700 Subject: [PATCH 0659/1494] drm/i915/display: Disable DRRS when needed in fastsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes in the configuration could cause PSR to be compatible and enabled so driver must also be able to disable DRRS when doing fastsets. v2: Fixed name of DRRS compute function (Anshuman) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/209 Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/173 Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/209 Cc: Srinivas K <srinivasx.k@intel.com> Cc: Hariom Pandey <hariom.pandey@intel.com> Cc: Anshuman Gupta <anshuman.gupta@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200825171331.17971-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 71 +++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_dp.h | 2 + 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index de5b216561d8f..ff05a852417cc 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4012,7 +4012,7 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, intel_psr_update(intel_dp, crtc_state, conn_state); intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_edp_drrs_enable(intel_dp, crtc_state); + intel_edp_drrs_update(intel_dp, crtc_state); intel_panel_update_backlight(state, encoder, crtc_state, conn_state); } diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 82525cbeafe2d..e6caeaf179260 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7728,6 +7728,15 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, refresh_rate); } +static void +intel_edp_drrs_enable_locked(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + dev_priv->drrs.busy_frontbuffer_bits = 0; + dev_priv->drrs.dp = intel_dp; +} + /** * intel_edp_drrs_enable - init drrs struct if supported * @intel_dp: DP struct @@ -7746,19 +7755,34 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp, drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); mutex_lock(&dev_priv->drrs.mutex); + if (dev_priv->drrs.dp) { - drm_dbg_kms(&dev_priv->drm, "DRRS already enabled\n"); + drm_warn(&dev_priv->drm, "DRRS already enabled\n"); goto unlock; } - dev_priv->drrs.busy_frontbuffer_bits = 0; - - dev_priv->drrs.dp = intel_dp; + intel_edp_drrs_enable_locked(intel_dp); unlock: mutex_unlock(&dev_priv->drrs.mutex); } +static void +intel_edp_drrs_disable_locked(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) { + int refresh; + + refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode); + intel_dp_set_drrs_state(dev_priv, crtc_state, refresh); + } + + dev_priv->drrs.dp = NULL; +} + /** * intel_edp_drrs_disable - Disable DRRS * @intel_dp: DP struct @@ -7779,16 +7803,45 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp, return; } - if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) - intel_dp_set_drrs_state(dev_priv, old_crtc_state, - drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode)); - - dev_priv->drrs.dp = NULL; + intel_edp_drrs_disable_locked(intel_dp, old_crtc_state); mutex_unlock(&dev_priv->drrs.mutex); cancel_delayed_work_sync(&dev_priv->drrs.work); } +/** + * intel_edp_drrs_update - Update DRRS state + * @intel_dp: Intel DP + * @crtc_state: new CRTC state + * + * This function will update DRRS states, disabling or enabling DRRS when + * executing fastsets. For full modeset, intel_edp_drrs_disable() and + * intel_edp_drrs_enable() should be called instead. + */ +void +intel_edp_drrs_update(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + + if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) + return; + + mutex_lock(&dev_priv->drrs.mutex); + + /* New state matches current one? */ + if (crtc_state->has_drrs == !!dev_priv->drrs.dp) + goto unlock; + + if (crtc_state->has_drrs) + intel_edp_drrs_enable_locked(intel_dp); + else + intel_edp_drrs_disable_locked(intel_dp, crtc_state); + +unlock: + mutex_unlock(&dev_priv->drrs.mutex); +} + static void intel_edp_drrs_downclock_work(struct work_struct *work) { struct drm_i915_private *dev_priv = diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index b901ab850cbd9..057b2c152cbdc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -81,6 +81,8 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); void intel_edp_drrs_disable(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +void intel_edp_drrs_update(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_edp_drrs_flush(struct drm_i915_private *dev_priv, -- GitLab From caab25dc9e36e83d3ff870cabd80b811ed02242d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Tue, 25 Aug 2020 10:13:31 -0700 Subject: [PATCH 0660/1494] drm/i915/display: Fix DRRS debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supported and enabled are different things so printing both. v3: using drrs->type instead of vbt.drrs_type Cc: Anshuman Gupta <anshuman.gupta@intel.com> Cc: Srinivas K <srinivasx.k@intel.com> Cc: Hariom Pandey <hariom.pandey@intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200825171331.17971-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index f549381048b3c..65ccf5d6cd399 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1069,10 +1069,18 @@ static void drrs_status_per_crtc(struct seq_file *m, drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + bool supported = false; + if (connector->state->crtc != &intel_crtc->base) continue; seq_printf(m, "%s:\n", connector->name); + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && + drrs->type == SEAMLESS_DRRS_SUPPORT) + supported = true; + + seq_printf(m, "\tDRRS Supported: %s\n", yesno(supported)); } drm_connector_list_iter_end(&conn_iter); @@ -1083,7 +1091,7 @@ static void drrs_status_per_crtc(struct seq_file *m, mutex_lock(&drrs->mutex); /* DRRS Supported */ - seq_puts(m, "\tDRRS Supported: Yes\n"); + seq_puts(m, "\tDRRS Enabled: Yes\n"); /* disable_drrs() will make drrs->dp NULL */ if (!drrs->dp) { @@ -1118,7 +1126,7 @@ static void drrs_status_per_crtc(struct seq_file *m, mutex_unlock(&drrs->mutex); } else { /* DRRS not supported. Print the VBT parameter*/ - seq_puts(m, "\tDRRS Supported : No"); + seq_puts(m, "\tDRRS Enabled : No"); } seq_puts(m, "\n"); } -- GitLab From 5aa8e76476766c48a4820f57015935429a50b928 Mon Sep 17 00:00:00 2001 From: Stu Hsieh <stu.hsieh@mediatek.com> Date: Wed, 19 Aug 2020 10:17:49 +0200 Subject: [PATCH 0661/1494] drm/mediatek: dpi/dsi: Change the getting possible_crtc way For current mediatek dsi encoder, its possible crtc is fixed in crtc 0, and mediatek dpi encoder's possible crtc is fixed in crtc 1. In some SoC the possible crtc is not fixed in this case, so search pipeline information to find out the correct possible crtc. Signed-off-by: Stu Hsieh <stu.hsieh@mediatek.com> Signed-off-by: Jitao Shi <jitao.shi@mediatek.com> Signed-off-by: Frank Wunderlich <frank-w@public-files.de> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_dpi.c | 3 +- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 38 +++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 ++ drivers/gpu/drm/mediatek/mtk_dsi.c | 6 +--- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index d4f0fb7ad3120..5b2026f3291d9 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -607,8 +607,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) } drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); - /* Currently DPI0 is fixed to be driven by OVL1 */ - dpi->encoder.possible_crtcs = BIT(1); + dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->ddp_comp); ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL, 0); if (ret) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 57c88de9a3293..bfd42ae1f64c2 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -13,6 +13,8 @@ #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/soc/mediatek/mtk-cmdq.h> +#include <drm/drm_print.h> + #include "mtk_drm_drv.h" #include "mtk_drm_plane.h" #include "mtk_drm_ddp_comp.h" @@ -412,6 +414,22 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, }; +static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp, + const enum mtk_ddp_comp_id *path, + unsigned int path_len) +{ + unsigned int i; + + if (path == NULL) + return false; + + for (i = 0U; i < path_len; i++) + if (ddp_comp.id == path[i]) + return true; + + return false; +} + int mtk_ddp_comp_get_id(struct device_node *node, enum mtk_ddp_comp_type comp_type) { @@ -427,6 +445,26 @@ int mtk_ddp_comp_get_id(struct device_node *node, return -EINVAL; } +unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, + struct mtk_ddp_comp ddp_comp) +{ + struct mtk_drm_private *private = drm->dev_private; + unsigned int ret = 0; + + if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->main_path, private->data->main_len)) + ret = BIT(0); + else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->ext_path, + private->data->ext_len)) + ret = BIT(1); + else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->third_path, + private->data->third_len)) + ret = BIT(2); + else + DRM_INFO("Failed to find comp in ddp table\n"); + + return ret; +} + int mtk_ddp_comp_init(struct device *dev, struct device_node *node, struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id, const struct mtk_ddp_comp_funcs *funcs) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index debe36395fe72..1d9e00b694625 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -202,6 +202,8 @@ static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp *comp, int mtk_ddp_comp_get_id(struct device_node *node, enum mtk_ddp_comp_type comp_type); +unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, + struct mtk_ddp_comp ddp_comp); int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id, const struct mtk_ddp_comp_funcs *funcs); diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 16fd99dcdacf8..20f3489920864 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -970,11 +970,7 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) return ret; } - /* - * Currently display data paths are statically assigned to a crtc each. - * crtc 0 is OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 - */ - dsi->encoder.possible_crtcs = 1; + dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->ddp_comp); ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); -- GitLab From c33298cb34f555592a030ab828c78c1c3046aa3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Thu, 27 Aug 2020 16:39:43 -0700 Subject: [PATCH 0662/1494] drm/i915/tgl: Fix stepping WA matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TGL made stepping a litte mess, workarounds refer to the stepping of the IP(GT or Display) not of the GPU stepping so it would already require the same solution as used in commit 96c5a15f9f39 ("drm/i915/kbl: Fix revision ID checks"). But to make things even more messy it have a different IP stepping mapping between SKUs and the same stepping revision of GT do not match the same HW between TGL U/Y and regular TGL. So it was required to have 2 different macros to check GT WAs while for Display we are able to use just one macro that uses the right revids table. All TGL workarounds checked and updated accordingly. v2: - removed TODO to check if WA 14010919138 applies to regular TGL. - fixed display stepping in regular TGL (Anusha) BSpec: 52890 BSpec: 55378 BSpec: 44455 Reviewed-by: Anusha Srivatsa <anusha.srivtsa@intel.com> Cc: Anusha Srivatsa <anusha.srivatsa@intel.com> Cc: Penne Lee <penne.y.lee@intel.com> Cc: Guangyao Bai <guangyao.bai@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200827233943.400946-1-jose.souza@intel.com --- .../drm/i915/display/intel_display_power.c | 2 +- drivers/gpu/drm/i915/display/intel_psr.c | 4 +- drivers/gpu/drm/i915/display/intel_sprite.c | 2 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 23 ++++++++--- drivers/gpu/drm/i915/i915_drv.h | 39 ++++++++++++++++--- drivers/gpu/drm/i915/intel_pm.c | 2 +- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 7946c6af4b1e7..7277e58b01f13 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5263,7 +5263,7 @@ static void tgl_bw_buddy_init(struct drm_i915_private *dev_priv) unsigned long abox_mask = INTEL_INFO(dev_priv)->abox_mask; int config, i; - if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B0)) + if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B0)) /* Wa_1409767108: tgl */ table = wa_1409767108_buddy_page_masks; else diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 2b004ee9619cd..8a9d0bdde1bfb 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -555,7 +555,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) if (dev_priv->psr.psr2_sel_fetch_enabled) { /* WA 1408330847 */ - if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, DIS_RAM_BYPASS_PSR2_MAN_TRACK, @@ -1109,7 +1109,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* WA 1408330847 */ if (dev_priv->psr.psr2_sel_fetch_enabled && - (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))) intel_de_rmw(dev_priv, CHICKEN_PAR1_1, DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index c26ca029fc0aa..1797a06cfd604 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2845,7 +2845,7 @@ static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv, { /* Wa_14010477008:tgl[a0..c0],rkl[all] */ if (IS_ROCKETLAKE(dev_priv) || - IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) + IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) return false; return plane_id < PLANE_SPRITE4; diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 7622d8ae1bb9a..9542038949e3d 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -70,6 +70,19 @@ const struct i915_rev_steppings kbl_revids[] = { [7] = { .gt_stepping = KBL_REVID_G0, .disp_stepping = KBL_REVID_C0 }, }; +const struct i915_rev_steppings tgl_uy_revids[] = { + [0] = { .gt_stepping = TGL_REVID_A0, .disp_stepping = TGL_REVID_A0 }, + [1] = { .gt_stepping = TGL_REVID_B0, .disp_stepping = TGL_REVID_C0 }, + [2] = { .gt_stepping = TGL_REVID_B1, .disp_stepping = TGL_REVID_C0 }, + [3] = { .gt_stepping = TGL_REVID_C0, .disp_stepping = TGL_REVID_D0 }, +}; + +/* Same GT stepping between tgl_uy_revids and tgl_revids don't mean the same HW */ +const struct i915_rev_steppings tgl_revids[] = { + [0] = { .gt_stepping = TGL_REVID_A0, .disp_stepping = TGL_REVID_B0 }, + [1] = { .gt_stepping = TGL_REVID_B0, .disp_stepping = TGL_REVID_D0 }, +}; + static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name) { wal->name = name; @@ -1219,13 +1232,13 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) gen12_gt_workarounds_init(i915, wal); /* Wa_1409420604:tgl */ - if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) + if (IS_TGL_UY_GT_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) wa_write_or(wal, SUBSLICE_UNIT_LEVEL_CLKGATE2, CPSSUNIT_CLKGATE_DIS); /* Wa_1607087056:tgl also know as BUG:1409180338 */ - if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) + if (IS_TGL_UY_GT_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) wa_write_or(wal, SLICE_UNIT_LEVEL_CLKGATE, L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS); @@ -1660,7 +1673,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { struct drm_i915_private *i915 = engine->i915; - if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) { + if (IS_TGL_UY_GT_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) { /* * Wa_1607138336:tgl * Wa_1607063988:tgl @@ -1700,7 +1713,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) * Wa_1407928979:tgl A* * Wa_18011464164:tgl B0+ * Wa_22010931296:tgl B0+ - * Wa_14010919138:rkl + * Wa_14010919138:rkl,tgl */ wa_write_or(wal, GEN7_FF_THREAD_MODE, GEN12_FF_TESSELATION_DOP_GATE_DISABLE); @@ -1718,7 +1731,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN8_RC_SEMA_IDLE_MSG_DISABLE); } - if (IS_TIGERLAKE(i915)) { + if (IS_TGL_U(i915) || IS_TGL_Y(i915)) { /* Wa_1606700617:tgl */ wa_masked_en(wal, GEN9_CS_DEBUG_MODE1, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1314e0e92c411..bf33cbfcf2a1a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1582,12 +1582,41 @@ extern const struct i915_rev_steppings kbl_revids[]; #define IS_EHL_REVID(p, since, until) \ (IS_ELKHARTLAKE(p) && IS_REVID(p, since, until)) -#define TGL_REVID_A0 0x0 -#define TGL_REVID_B0 0x1 -#define TGL_REVID_C0 0x2 +enum { + TGL_REVID_A0, + TGL_REVID_B0, + TGL_REVID_B1, + TGL_REVID_C0, + TGL_REVID_D0, +}; + +extern const struct i915_rev_steppings tgl_uy_revids[]; +extern const struct i915_rev_steppings tgl_revids[]; + +static inline const struct i915_rev_steppings * +tgl_revids_get(struct drm_i915_private *dev_priv) +{ + if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) + return tgl_uy_revids; + else + return tgl_revids; +} -#define IS_TGL_REVID(p, since, until) \ - (IS_TIGERLAKE(p) && IS_REVID(p, since, until)) +#define IS_TGL_DISP_REVID(p, since, until) \ + (IS_TIGERLAKE(p) && \ + tgl_revids_get(p)->disp_stepping >= (since) && \ + tgl_revids_get(p)->disp_stepping <= (until)) + +#define IS_TGL_UY_GT_REVID(p, since, until) \ + ((IS_TGL_U(p) || IS_TGL_Y(p)) && \ + tgl_uy_revids->gt_stepping >= (since) && \ + tgl_uy_revids->gt_stepping <= (until)) + +#define IS_TGL_GT_REVID(p, since, until) \ + (IS_TIGERLAKE(p) && \ + !(IS_TGL_U(p) || IS_TGL_Y(p)) && \ + tgl_revids->gt_stepping >= (since) && \ + tgl_revids->gt_stepping <= (until)) #define RKL_REVID_A0 0x0 #define RKL_REVID_B0 0x1 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b4bd19266b8c5..34e0d22d456bd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7136,7 +7136,7 @@ static void tgl_init_clock_gating(struct drm_i915_private *dev_priv) I915_READ(POWERGATE_ENABLE) | vd_pg_enable); /* Wa_1409825376:tgl (pre-prod)*/ - if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0)) + if (IS_TGL_DISP_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_B1)) I915_WRITE(GEN9_CLKGATE_DIS_3, I915_READ(GEN9_CLKGATE_DIS_3) | TGL_VRH_GATING_DIS); -- GitLab From a8c90bc11990168b76ecd0546821a90fa353098a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Wed, 26 Aug 2020 13:15:47 -0700 Subject: [PATCH 0663/1494] drm/i915/display/tgl: Use TGL DP tables for eDP ports without low power support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reusing icl_get_combo_buf_trans() for eDP was causing the wrong table being used when the eDP port don't support low power voltage swing table. Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Cc: Lee Shawn C <shawn.c.lee@intel.com> Cc: Khaled Almahallawy <khaled.almahallawy@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826201549.83658-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 52 +++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index ff05a852417cc..cdd457990bba1 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1088,30 +1088,44 @@ tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.hobl) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - - if (!intel_dp->hobl_failed && rate <= 540000) { - /* Same table applies to TGL, RKL and DG1 */ - *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_edp_hbr2_hobl); - return tgl_combo_phy_ddi_translations_edp_hbr2_hobl; + switch (type) { + case INTEL_OUTPUT_HDMI: + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); + return icl_combo_phy_ddi_translations_hdmi; + case INTEL_OUTPUT_EDP: + if (dev_priv->vbt.edp.hobl) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (!intel_dp->hobl_failed && rate <= 540000) { + /* Same table applies to TGL, RKL and DG1 */ + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_edp_hbr2_hobl); + return tgl_combo_phy_ddi_translations_edp_hbr2_hobl; + } } - } - if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { - return icl_get_combo_buf_trans(encoder, type, rate, n_entries); - } else if (rate > 270000) { - if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) { - *n_entries = ARRAY_SIZE(tgl_uy_combo_phy_ddi_translations_dp_hbr2); - return tgl_uy_combo_phy_ddi_translations_dp_hbr2; + if (rate > 540000) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3); + return icl_combo_phy_ddi_translations_edp_hbr3; + } else if (dev_priv->vbt.edp.low_vswing) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2); + return icl_combo_phy_ddi_translations_edp_hbr2; + } + /* fall through */ + default: + /* All combo DP and eDP ports that do not support low_vswing */ + if (rate > 270000) { + if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) { + *n_entries = ARRAY_SIZE(tgl_uy_combo_phy_ddi_translations_dp_hbr2); + return tgl_uy_combo_phy_ddi_translations_dp_hbr2; + } + + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2); + return tgl_combo_phy_ddi_translations_dp_hbr2; } - *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2); - return tgl_combo_phy_ddi_translations_dp_hbr2; + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr); + return tgl_combo_phy_ddi_translations_dp_hbr; } - - *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr); - return tgl_combo_phy_ddi_translations_dp_hbr; } static const struct tgl_dkl_phy_ddi_buf_trans * -- GitLab From 2a498ab49256eafd2bba1f19b7fe22ce5d880a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Wed, 26 Aug 2020 13:15:48 -0700 Subject: [PATCH 0664/1494] drm/i915/display/ehl: Use EHL DP tables for eDP ports without low power support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reusing icl_get_combo_buf_trans() for eDP was causing the wrong table being used when the eDP port don't support low power voltage swing table. v2: Only use icl_combo_phy_ddi_translations_edp_hbr3 if low_vswing is set as EHL combo phy supports HBR3 (Matt R) Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Cc: Lee Shawn C <shawn.c.lee@intel.com> Cc: Khaled Almahallawy <khaled.almahallawy@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826201549.83658-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index cdd457990bba1..747f0511412cd 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1074,12 +1074,28 @@ static const struct cnl_ddi_buf_trans * ehl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { - if (type != INTEL_OUTPUT_HDMI && type != INTEL_OUTPUT_EDP) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + switch (type) { + case INTEL_OUTPUT_HDMI: + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); + return icl_combo_phy_ddi_translations_hdmi; + case INTEL_OUTPUT_EDP: + if (dev_priv->vbt.edp.low_vswing) { + if (rate > 540000) { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3); + return icl_combo_phy_ddi_translations_edp_hbr3; + } else { + *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2); + return icl_combo_phy_ddi_translations_edp_hbr2; + } + } + /* fall through */ + default: + /* All combo DP and eDP ports that do not support low_vswing */ *n_entries = ARRAY_SIZE(ehl_combo_phy_ddi_translations_dp); return ehl_combo_phy_ddi_translations_dp; } - - return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } static const struct cnl_ddi_buf_trans * -- GitLab From 3baea2697b6817d53ece9682f50916db891dfc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= <jose.souza@intel.com> Date: Wed, 26 Aug 2020 13:15:49 -0700 Subject: [PATCH 0665/1494] drm/i915/ehl: Update voltage swing table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update with latest tuning in the table. v3: Fix values of to last columns. BSpec: 21257 Cc: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826201549.83658-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 747f0511412cd..d6f84bc3b8fdb 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -572,13 +572,13 @@ static const struct cnl_ddi_buf_trans ehl_combo_phy_ddi_translations_dp[] = { /* NT mV Trans mV db */ { 0xA, 0x33, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ { 0xA, 0x47, 0x36, 0x00, 0x09 }, /* 350 500 3.1 */ - { 0xC, 0x64, 0x30, 0x00, 0x0F }, /* 350 700 6.0 */ - { 0x6, 0x7F, 0x2C, 0x00, 0x13 }, /* 350 900 8.2 */ + { 0xC, 0x64, 0x34, 0x00, 0x0B }, /* 350 700 6.0 */ + { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 350 900 8.2 */ { 0xA, 0x46, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */ - { 0xC, 0x64, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */ - { 0x6, 0x7F, 0x30, 0x00, 0x0F }, /* 500 900 5.1 */ + { 0xC, 0x64, 0x38, 0x00, 0x07 }, /* 500 700 2.9 */ + { 0x6, 0x7F, 0x32, 0x00, 0x0D }, /* 500 900 5.1 */ { 0xC, 0x61, 0x3F, 0x00, 0x00 }, /* 650 700 0.6 */ - { 0x6, 0x7F, 0x37, 0x00, 0x08 }, /* 600 900 3.5 */ + { 0x6, 0x7F, 0x38, 0x00, 0x07 }, /* 600 900 3.5 */ { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; -- GitLab From e230ac11182b3d9f8448498e925e479bcd1e79f7 Mon Sep 17 00:00:00 2001 From: Nirmoy Das <nirmoy.das@amd.com> Date: Thu, 27 Aug 2020 17:50:36 +0200 Subject: [PATCH 0666/1494] drm/amdgpu: fix compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes below compiler warnings: CC [M] drivers/gpu/drm/amd/amdgpu/amdgpu_device.o drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:381:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] 381 | void static inline amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) | ^~~~ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:381:1: warning: ‘inline’ is not at beginning of declaration [-Wold-style-declaration] drivers/gpu/drm/amd/amdgpu/amdgpu_device.c: In function ‘amdgpu_device_fini’: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:3381:6: warning: variable ‘r’ set but not used [-Wunused-but-set-variable] 3381 | int r; | ^ Signed-off-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 696a61cc3ac66..6518e444beada 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -378,7 +378,9 @@ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) BUG(); } -void static inline amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) +static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, + uint32_t reg, uint32_t v, + uint32_t acc_flags) { trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); @@ -3378,8 +3380,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, */ void amdgpu_device_fini(struct amdgpu_device *adev) { - int r; - dev_info(adev->dev, "amdgpu: finishing device.\n"); flush_delayed_work(&adev->delayed_init_work); adev->shutdown = true; @@ -3402,7 +3402,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) if (adev->pm_sysfs_en) amdgpu_pm_sysfs_fini(adev); amdgpu_fbdev_fini(adev); - r = amdgpu_device_ip_fini(adev); + amdgpu_device_ip_fini(adev); release_firmware(adev->firmware.gpu_info_fw); adev->firmware.gpu_info_fw = NULL; adev->accel_working = false; -- GitLab From 2034c2129bc4a91d471815d4dc7a2a69eaa5338d Mon Sep 17 00:00:00 2001 From: Nathan Chancellor <natechancellor@gmail.com> Date: Fri, 28 Aug 2020 13:28:30 -0700 Subject: [PATCH 0667/1494] drm/i915/display: Ensure that ret is always initialized in icl_combo_phy_verify_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang warns: drivers/gpu/drm/i915/display/intel_combo_phy.c:268:3: warning: variable 'ret' is uninitialized when used here [-Wuninitialized] ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN0(phy), ^~~ drivers/gpu/drm/i915/display/intel_combo_phy.c:261:10: note: initialize the variable 'ret' to silence this warning bool ret; ^ = 0 1 warning generated. In practice, the bug this warning appears to be concerned with would not actually matter because ret gets initialized to the return value of cnl_verify_procmon_ref_values. However, that does appear to be a bug since it means the first hunk of the patch this fixes won't actually do anything (since the values of check_phy_reg won't factor into the final ret value). Initialize ret to true then make all of the assignments a bitwise AND with itself so that the function always does what it should do. Fixes: 239bef676d8e ("drm/i915/display: Implement new combo phy initialization step") Link: https://github.com/ClangBuiltLinux/linux/issues/1094 Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> Reviewed-by: Matt Roper <matthew.d.roper@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200828202830.7165-1-jose.souza@intel.com Signed-off-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_combo_phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index eccaa79cb4a9d..a4b8aa6d0a9e9 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -258,7 +258,7 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { - bool ret; + bool ret = true; u32 expected_val = 0; if (!icl_combo_phy_enabled(dev_priv, phy)) @@ -276,7 +276,7 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, DCC_MODE_SELECT_CONTINUOSLY); } - ret = cnl_verify_procmon_ref_values(dev_priv, phy); + ret &= cnl_verify_procmon_ref_values(dev_priv, phy); if (phy_is_master(dev_priv, phy)) { ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy), -- GitLab From a8f94c4a87885c33c034e8548d4ff623eb8a9366 Mon Sep 17 00:00:00 2001 From: Jagan Teki <jagan@amarulasolutions.com> Date: Sat, 29 Aug 2020 22:03:27 +0530 Subject: [PATCH 0668/1494] dt-bindings: display: simple: Add AM-1280800N3TZQW-T00H Add dt-bindings for 10.1" TFT LCD module from Ampire Co. Ltd. as part of panel-simple. Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200829163328.249211-1-jagan@amarulasolutions.com --- .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index f2204f17a9dc1..edb53ab0d9eb2 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -29,6 +29,8 @@ properties: # compatible must be listed in alphabetical order, ordered by compatible. # The description in the comment is mandatory for each compatible. + # Ampire AM-1280800N3TZQW-T00H 10.1" WQVGA TFT LCD panel + - ampire,am-1280800n3tzqw-t00h # Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel - ampire,am-480272h3tmqw-t01h # Ampire AM-800480R3TMQW-A1H 7.0" WVGA TFT LCD panel -- GitLab From bca684e69c4ced7cd141ee3ad0486446eef628a2 Mon Sep 17 00:00:00 2001 From: Jagan Teki <jagan@amarulasolutions.com> Date: Sat, 29 Aug 2020 22:03:28 +0530 Subject: [PATCH 0669/1494] drm/panel: simple: Add AM-1280800N3TZQW-T00H Add Ampire, AM-1280800N3TZQW-T00H 10.1" TFT LCD panel timings. Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200829163328.249211-2-jagan@amarulasolutions.com --- drivers/gpu/drm/panel/panel-simple.c | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index f499de71ab3d6..a1e5a02c328f7 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -659,6 +659,32 @@ static void panel_simple_shutdown(struct device *dev) drm_panel_unprepare(&panel->base); } +static const struct drm_display_mode ampire_am_1280800n3tzqw_t00h_mode = { + .clock = 71100, + .hdisplay = 1280, + .hsync_start = 1280 + 40, + .hsync_end = 1280 + 40 + 80, + .htotal = 1280 + 40 + 80 + 40, + .vdisplay = 800, + .vsync_start = 800 + 3, + .vsync_end = 800 + 3 + 10, + .vtotal = 800 + 3 + 10 + 10, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc ampire_am_1280800n3tzqw_t00h = { + .modes = &ire_am_1280800n3tzqw_t00h_mode, + .num_modes = 1, + .bpc = 6, + .size = { + .width = 217, + .height = 136, + }, + .bus_flags = DRM_BUS_FLAG_DE_HIGH, + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + .connector_type = DRM_MODE_CONNECTOR_LVDS, +}; + static const struct drm_display_mode ampire_am_480272h3tmqw_t01h_mode = { .clock = 9000, .hdisplay = 480, @@ -3875,6 +3901,9 @@ static const struct panel_desc arm_rtsm = { static const struct of_device_id platform_of_match[] = { { + .compatible = "ampire,am-1280800n3tzqw-t00h", + .data = &ire_am_1280800n3tzqw_t00h, + }, { .compatible = "ampire,am-480272h3tmqw-t01h", .data = &ire_am_480272h3tmqw_t01h, }, { -- GitLab From 3b634b479abeeae58e08c03db4293f47078ff87d Mon Sep 17 00:00:00 2001 From: Robert Chiras <robert.chiras@nxp.com> Date: Fri, 28 Aug 2020 17:58:33 +0300 Subject: [PATCH 0670/1494] drm/panel: rm67191: Remove CLOCK_NON_CONTINUOUS flag The flag MIPI_DSI_CLOCK_NON_CONTINUOUS was wrong used in the DSI driver, so it was added to this panel, but not necessary. So, remove this flag since it is not needed. Signed-off-by: Robert Chiras <robert.chiras@nxp.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/1598626713-5595-1-git-send-email-robert.chiras@oss.nxp.com --- drivers/gpu/drm/panel/panel-raydium-rm67191.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c index 23b62081e951d..572547d1aa832 100644 --- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -552,8 +552,7 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi) panel->dsi = dsi; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | - MIPI_DSI_CLOCK_NON_CONTINUOUS; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO; ret = of_property_read_u32(np, "video-mode", &video_mode); if (!ret) { -- GitLab From 85a51673660d43a3f4543f4623f747dc9a51d35b Mon Sep 17 00:00:00 2001 From: Vinod Koul <vkoul@kernel.org> Date: Fri, 28 Aug 2020 13:12:50 +0530 Subject: [PATCH 0671/1494] drm/bridge: Fix the dsi remote end-points DSI end-points are supposed to be at node 0 and node 1 as per binding. So fix this and use node 0 and node 1 for dsi. Reported-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Fixes: 23278bf54afe ("drm/bridge: Introduce LT9611 DSI to HDMI bridge") Signed-off-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200828074251.3788165-1-vkoul@kernel.org --- drivers/gpu/drm/bridge/lontium-lt9611.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index 1009fc4ed4edc..d734d9402c350 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -960,13 +960,13 @@ static const struct drm_bridge_funcs lt9611_bridge_funcs = { static int lt9611_parse_dt(struct device *dev, struct lt9611 *lt9611) { - lt9611->dsi0_node = of_graph_get_remote_node(dev->of_node, 1, -1); + lt9611->dsi0_node = of_graph_get_remote_node(dev->of_node, 0, -1); if (!lt9611->dsi0_node) { dev_err(lt9611->dev, "failed to get remote node for primary dsi\n"); return -ENODEV; } - lt9611->dsi1_node = of_graph_get_remote_node(dev->of_node, 2, -1); + lt9611->dsi1_node = of_graph_get_remote_node(dev->of_node, 1, -1); lt9611->ac_mode = of_property_read_bool(dev->of_node, "lt,ac-mode"); -- GitLab From 3b8095169982ff4ec2a1b4be61b7224bbef23b48 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Date: Mon, 24 Aug 2020 03:32:54 +0300 Subject: [PATCH 0672/1494] drm: panel: Fix bpc for OrtusTech COM43H4M85ULC panel The OrtusTech COM43H4M85ULC panel is a 18-bit RGB panel. Commit f098f168e91c ("drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel") has fixed the bus formats, but forgot to address the bpc value. Set it to 6. Fixes: f098f168e91c ("drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel") Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200824003254.21904-1-laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/panel/panel-simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index a1e5a02c328f7..2be358fb46f7d 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -3078,7 +3078,7 @@ static const struct drm_display_mode ortustech_com43h4m85ulc_mode = { static const struct panel_desc ortustech_com43h4m85ulc = { .modes = &ortustech_com43h4m85ulc_mode, .num_modes = 1, - .bpc = 8, + .bpc = 6, .size = { .width = 56, .height = 93, -- GitLab From 39cba5cf8c2c23c9c1fe3e0a8612d4f2d932d79b Mon Sep 17 00:00:00 2001 From: Melissa Wen <melissa.srw@gmail.com> Date: Tue, 25 Aug 2020 08:45:32 -0300 Subject: [PATCH 0673/1494] drm/vkms: add alpha-premultiplied color blending The VKMS blend function was ignoring the alpha channel and just overwriting vaddr_src with vaddr_dst. This XRGB approach triggers a warning when running the kms_cursor_crc/cursor-alpha-transparent test case. In IGT, cairo_format_argb32 uses premultiplied alpha (according to documentation). Also current DRM assumption is that alpha is premultiplied. Therefore, this patch considers premultiplied alpha blending eq to compose vaddr_src with vaddr_dst. This change removes the following cursor-alpha-transparent warning: "Suspicious CRC: All values are 0." V2: - static for local functions - const for the read-only variable argb_src - replaces variable names - drops unnecessary comment Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Cc: Haneen Mohammed <hamohammed.sa@gmail.com> Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Reviewed-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200825114532.abzdooluny2ekzvm@smtp.gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 55 ++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 4f3b07a32b602..eaecc5a6c5dba 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -32,8 +32,6 @@ static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) src_offset = composer->offset + (i * composer->pitch) + (j * composer->cpp); - /* XRGB format ignores Alpha channel */ - bitmap_clear(vaddr_out + src_offset, 24, 8); crc = crc32_le(crc, vaddr_out + src_offset, sizeof(u32)); } @@ -42,27 +40,51 @@ static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) return crc; } +static u8 blend_channel(u8 src, u8 dst, u8 alpha) +{ + u32 pre_blend; + u8 new_color; + + pre_blend = (src * 255 + dst * (255 - alpha)); + + /* Faster div by 255 */ + new_color = ((pre_blend + ((pre_blend + 257) >> 8)) >> 8); + + return new_color; +} + +static void alpha_blending(const u8 *argb_src, u8 *argb_dst) +{ + u8 alpha; + + alpha = argb_src[3]; + argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], alpha); + argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], alpha); + argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], alpha); + /* Opaque primary */ + argb_dst[3] = 0xFF; +} + /** * blend - blend value at vaddr_src with value at vaddr_dst * @vaddr_dst: destination address * @vaddr_src: source address - * @dest_composer: destination framebuffer's metadata + * @dst_composer: destination framebuffer's metadata * @src_composer: source framebuffer's metadata * - * Blend value at vaddr_src with value at vaddr_dst. - * Currently, this function write value of vaddr_src on value - * at vaddr_dst using buffer's metadata to locate the new values - * from vaddr_src and their destination at vaddr_dst. - * - * TODO: Use the alpha value to blend vaddr_src with vaddr_dst - * instead of overwriting it. + * Blend the vaddr_src value with the vaddr_dst value using the pre-multiplied + * alpha blending equation, since DRM currently assumes that the pixel color + * values have already been pre-multiplied with the alpha channel values. See + * more drm_plane_create_blend_mode_property(). This function uses buffer's + * metadata to locate the new composite values at vaddr_dst. */ static void blend(void *vaddr_dst, void *vaddr_src, - struct vkms_composer *dest_composer, + struct vkms_composer *dst_composer, struct vkms_composer *src_composer) { int i, j, j_dst, i_dst; int offset_src, offset_dst; + u8 *pixel_dst, *pixel_src; int x_src = src_composer->src.x1 >> 16; int y_src = src_composer->src.y1 >> 16; @@ -77,15 +99,16 @@ static void blend(void *vaddr_dst, void *vaddr_src, for (i = y_src, i_dst = y_dst; i < y_limit; ++i) { for (j = x_src, j_dst = x_dst; j < x_limit; ++j) { - offset_dst = dest_composer->offset - + (i_dst * dest_composer->pitch) - + (j_dst++ * dest_composer->cpp); + offset_dst = dst_composer->offset + + (i_dst * dst_composer->pitch) + + (j_dst++ * dst_composer->cpp); offset_src = src_composer->offset + (i * src_composer->pitch) + (j * src_composer->cpp); - memcpy(vaddr_dst + offset_dst, - vaddr_src + offset_src, sizeof(u32)); + pixel_src = (u8 *)(vaddr_src + offset_src); + pixel_dst = (u8 *)(vaddr_dst + offset_dst); + alpha_blending(pixel_src, pixel_dst); } i_dst++; } -- GitLab From 05ca530268a9d0ab3547e7b288635e35990a77c4 Mon Sep 17 00:00:00 2001 From: Sidong Yang <realwakka@gmail.com> Date: Fri, 28 Aug 2020 12:45:53 +0000 Subject: [PATCH 0674/1494] drm/vkms: avoid warning in vkms_get_vblank_timestamp This patch avoid the warning in vkms_get_vblank_timestamp when vblanks aren't enabled. When running igt test kms_cursor_crc just after vkms module, the warning raised like below. Initial value of vblank time is zero and hrtimer.node.expires is also zero if vblank aren't enabled before. vkms module isn't real hardware but just virtual hardware module. so vkms can't generate a resonable timestamp when hrtimer is off. it's best to grab the current time. [106444.464503] [IGT] kms_cursor_crc: starting subtest pipe-A-cursor-size-change [106444.471475] WARNING: CPU: 0 PID: 10109 at vkms_get_vblank_timestamp+0x42/0x50 [vkms] [106444.471511] CPU: 0 PID: 10109 Comm: kms_cursor_crc Tainted: G W OE 5.9.0-rc1+ #6 [106444.471514] RIP: 0010:vkms_get_vblank_timestamp+0x42/0x50 [vkms] [106444.471528] Call Trace: [106444.471551] drm_get_last_vbltimestamp+0xb9/0xd0 [drm] [106444.471566] drm_reset_vblank_timestamp+0x63/0xe0 [drm] [106444.471579] drm_crtc_vblank_on+0x85/0x150 [drm] [106444.471582] vkms_crtc_atomic_enable+0xe/0x10 [vkms] [106444.471592] drm_atomic_helper_commit_modeset_enables+0x1db/0x230 [drm_kms_helper] [106444.471594] vkms_atomic_commit_tail+0x38/0xc0 [vkms] [106444.471601] commit_tail+0x97/0x130 [drm_kms_helper] [106444.471608] drm_atomic_helper_commit+0x117/0x140 [drm_kms_helper] [106444.471622] drm_atomic_commit+0x4a/0x50 [drm] [106444.471629] drm_atomic_helper_set_config+0x63/0xb0 [drm_kms_helper] [106444.471642] drm_mode_setcrtc+0x1d9/0x7b0 [drm] [106444.471654] ? drm_mode_getcrtc+0x1a0/0x1a0 [drm] [106444.471666] drm_ioctl_kernel+0xb6/0x100 [drm] [106444.471677] drm_ioctl+0x3ad/0x470 [drm] [106444.471688] ? drm_mode_getcrtc+0x1a0/0x1a0 [drm] [106444.471692] ? tomoyo_file_ioctl+0x19/0x20 [106444.471694] __x64_sys_ioctl+0x96/0xd0 [106444.471697] do_syscall_64+0x37/0x80 [106444.471699] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Cc: Haneen Mohammed <hamohammed.sa@gmail.com> Cc: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Sidong Yang <realwakka@gmail.com> Reviewed-by: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200828124553.2178-1-realwakka@gmail.com --- drivers/gpu/drm/vkms/vkms_crtc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index ac85e17428f88..09c012d54d58f 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -86,6 +86,11 @@ static bool vkms_get_vblank_timestamp(struct drm_crtc *crtc, struct vkms_output *output = &vkmsdev->output; struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + if (!READ_ONCE(vblank->enabled)) { + *vblank_time = ktime_get(); + return true; + } + *vblank_time = READ_ONCE(output->vblank_hrtimer.node.expires); if (WARN_ON(*vblank_time == vblank->time)) -- GitLab From acad3fe650a55c11c305741ce87b7852f0edbb04 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 26 Aug 2020 15:55:28 +0800 Subject: [PATCH 0675/1494] drm/hisilicon: Removed the dependency on the mmu hibmc can only be used in ARM64 architectures, and mmu defaults to y in arch/arm64/Kconfig, so there is no need to add a dependency on mmu in hibmc's kconfig. Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1598428528-49046-1-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/hisilicon/hibmc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig index dfc5aef62f7ba..43943e9802036 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_HISI_HIBMC tristate "DRM Support for Hisilicon Hibmc" - depends on DRM && PCI && MMU && ARM64 + depends on DRM && PCI && ARM64 select DRM_KMS_HELPER select DRM_VRAM_HELPER select DRM_TTM -- GitLab From 05010c1e2f6b08d623d225305936255d53e34b62 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 25 Aug 2020 16:49:13 +1000 Subject: [PATCH 0676/1494] drm/amdgpu/ttm: remove unused parameter to move blit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826014428.828392-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fc5f7ac53d0ab..46d6208174828 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -473,7 +473,7 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, * help move buffers to and from VRAM. */ static int amdgpu_move_blit(struct ttm_buffer_object *bo, - bool evict, bool no_wait_gpu, + bool evict, struct ttm_resource *new_mem, struct ttm_resource *old_mem) { @@ -571,7 +571,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, } /* blit VRAM to GTT */ - r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, &tmp_mem, old_mem); + r = amdgpu_move_blit(bo, evict, &tmp_mem, old_mem); if (unlikely(r)) { goto out_cleanup; } @@ -621,7 +621,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, } /* copy to VRAM */ - r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, new_mem, old_mem); + r = amdgpu_move_blit(bo, evict, new_mem, old_mem); if (unlikely(r)) { goto out_cleanup; } @@ -710,7 +710,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, new_mem->mem_type == TTM_PL_VRAM) { r = amdgpu_move_ram_vram(bo, evict, ctx, new_mem); } else { - r = amdgpu_move_blit(bo, evict, ctx->no_wait_gpu, + r = amdgpu_move_blit(bo, evict, new_mem, old_mem); } -- GitLab From 8e6c0a2fe75d371cbaa1aea71eac636b07f32533 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 25 Aug 2020 09:08:11 +1000 Subject: [PATCH 0677/1494] drm/radeon/ttm: don't store driver copy of device pointer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This can be gotten back from bdev. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826014428.828392-3-airlied@gmail.com --- drivers/gpu/drm/radeon/radeon_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 3a4372ea74b9d..74ad50c7491c1 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -422,7 +422,6 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso */ struct radeon_ttm_tt { struct ttm_dma_tt ttm; - struct radeon_device *rdev; u64 offset; uint64_t userptr; @@ -525,6 +524,7 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct radeon_ttm_tt *gtt = (void*)ttm; + struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ | RADEON_GART_PAGE_WRITE; int r; @@ -541,7 +541,7 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm, } if (ttm->caching_state == tt_cached) flags |= RADEON_GART_PAGE_SNOOP; - r = radeon_gart_bind(gtt->rdev, gtt->offset, ttm->num_pages, + r = radeon_gart_bind(rdev, gtt->offset, ttm->num_pages, ttm->pages, gtt->ttm.dma_address, flags); if (r) { DRM_ERROR("failed to bind %lu pages at 0x%08X\n", @@ -554,8 +554,9 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm, static void radeon_ttm_backend_unbind(struct ttm_tt *ttm) { struct radeon_ttm_tt *gtt = (void *)ttm; + struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); - radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages); + radeon_gart_unbind(rdev, gtt->offset, ttm->num_pages); if (gtt->userptr) radeon_ttm_tt_unpin_userptr(ttm); @@ -594,7 +595,6 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_buffer_object *bo, return NULL; } gtt->ttm.ttm.func = &radeon_backend_func; - gtt->rdev = rdev; if (ttm_dma_tt_init(>t->ttm, bo, page_flags)) { kfree(gtt); return NULL; -- GitLab From bfacb84993eb173c0ab53ca4dd6180f76f4dc176 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Fri, 28 Aug 2020 07:05:57 -0700 Subject: [PATCH 0678/1494] drm: virtio: fix kconfig dependency warning Fix kconfig dependency warning by using a different Kconfig symbol. WARNING: unmet direct dependencies detected for VIRTIO_DMA_SHARED_BUFFER Depends on [n]: VIRTIO_MENU [=n] && DMA_SHARED_BUFFER [=y] Selected by [y]: - DRM_VIRTIO_GPU [=y] && HAS_IOMEM [=y] && DRM [=y] && VIRTIO [=y] && MMU [=y] Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Link: http://patchwork.freedesktop.org/patch/msgid/7481fb88-6b04-3726-57e0-0f513245c657@infradead.org Cc: David Airlie <airlied@linux.ie> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: dri-devel@lists.freedesktop.org Cc: virtualization@lists.linux-foundation.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig index 67624423013a1..b925b8b1da167 100644 --- a/drivers/gpu/drm/virtio/Kconfig +++ b/drivers/gpu/drm/virtio/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DRM_VIRTIO_GPU tristate "Virtio GPU driver" - depends on DRM && VIRTIO && MMU + depends on DRM && VIRTIO && VIRTIO_MENU && MMU select DRM_KMS_HELPER select DRM_GEM_SHMEM_HELPER select VIRTIO_DMA_SHARED_BUFFER -- GitLab From d452bd091e168f75ec2807c30eec1f7be918c737 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Date: Fri, 28 Aug 2020 16:31:25 +0300 Subject: [PATCH 0679/1494] drm/i915: break TGL pci-ids in GT 1 & 2 I'll need this in IGT to identify the different kind of GTs and apply the right performance query configuration. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200828133125.157171-1-lionel.g.landwerlin@intel.com --- include/drm/i915_pciids.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 8e7ae30ebcbb7..7eeecb07c9a1f 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -594,19 +594,25 @@ INTEL_VGA_DEVICE(0x4E51, info) /* TGL */ -#define INTEL_TGL_12_IDS(info) \ +#define INTEL_TGL_12_GT1_IDS(info) \ + INTEL_VGA_DEVICE(0x9A60, info), \ + INTEL_VGA_DEVICE(0x9A68, info), \ + INTEL_VGA_DEVICE(0x9A70, info) + +#define INTEL_TGL_12_GT2_IDS(info) \ INTEL_VGA_DEVICE(0x9A40, info), \ INTEL_VGA_DEVICE(0x9A49, info), \ INTEL_VGA_DEVICE(0x9A59, info), \ - INTEL_VGA_DEVICE(0x9A60, info), \ - INTEL_VGA_DEVICE(0x9A68, info), \ - INTEL_VGA_DEVICE(0x9A70, info), \ INTEL_VGA_DEVICE(0x9A78, info), \ INTEL_VGA_DEVICE(0x9AC0, info), \ INTEL_VGA_DEVICE(0x9AC9, info), \ INTEL_VGA_DEVICE(0x9AD9, info), \ INTEL_VGA_DEVICE(0x9AF8, info) +#define INTEL_TGL_12_IDS(info) \ + INTEL_TGL_12_GT1_IDS(info), \ + INTEL_TGL_12_GT2_IDS(info) + /* RKL */ #define INTEL_RKL_IDS(info) \ INTEL_VGA_DEVICE(0x4C80, info), \ -- GitLab From 55977744f9d862512a524fea93fc5226b09e76a9 Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Fri, 28 Aug 2020 18:50:42 -0400 Subject: [PATCH 0680/1494] drm/amdkfd: Add GPU reset SMI event Add support for reporting GPU reset events through SMI. KFD would report both pre and post GPU reset events. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 4 +++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 ++ drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 34 +++++++++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h | 1 + include/uapi/linux/kfd_ioctl.h | 2 ++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index e1cd6599529fb..0e71a0543f987 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -812,6 +812,8 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd) if (!kfd->init_complete) return 0; + kfd_smi_event_update_gpu_reset(kfd, false); + kfd->dqm->ops.pre_reset(kfd->dqm); kgd2kfd_suspend(kfd, false); @@ -840,6 +842,8 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd) atomic_set(&kfd->sram_ecc_flag, 0); + kfd_smi_event_update_gpu_reset(kfd, true); + return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f14beb93acb43..023629f284951 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -312,6 +312,8 @@ struct kfd_dev { /* Clients watching SMI events */ struct list_head smi_clients; spinlock_t smi_lock; + + uint32_t reset_seq_num; }; enum kfd_mempool { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 4d4b6e3ab697b..17d1736367ea3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -174,6 +174,36 @@ static void add_event_to_kfifo(struct kfd_dev *dev, unsigned int smi_event, rcu_read_unlock(); } +void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset) +{ + /* + * GpuReset msg = Reset seq number (incremented for + * every reset message sent before GPU reset). + * 1 byte event + 1 byte space + 8 bytes seq num + + * 1 byte \n + 1 byte \0 = 12 + */ + char fifo_in[12]; + int len; + unsigned int event; + + if (list_empty(&dev->smi_clients)) + return; + + memset(fifo_in, 0x0, sizeof(fifo_in)); + + if (post_reset) { + event = KFD_SMI_EVENT_GPU_POST_RESET; + } else { + event = KFD_SMI_EVENT_GPU_PRE_RESET; + ++(dev->reset_seq_num); + } + + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x\n", event, + dev->reset_seq_num); + + add_event_to_kfifo(dev, event, fifo_in, len); +} + void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, uint32_t throttle_bitmask) { @@ -191,7 +221,7 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, if (list_empty(&dev->smi_clients)) return; - len = snprintf(fifo_in, 29, "%x %x:%llx\n", + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%llx\n", KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, atomic64_read(&adev->smu.throttle_int_counter)); @@ -218,7 +248,7 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) if (!task_info.pid) return; - len = snprintf(fifo_in, 29, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, task_info.pid, task_info.task_name); add_event_to_kfifo(dev, KFD_SMI_EVENT_VMFAULT, fifo_in, len); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h index 15537b2cccb58..b9b0438202e21 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h @@ -27,5 +27,6 @@ int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, uint32_t throttle_bitmask); +void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset); #endif diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index cb1f963a84e0a..8b7368bfbd846 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -453,6 +453,8 @@ enum kfd_smi_event { KFD_SMI_EVENT_NONE = 0, /* not used */ KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ KFD_SMI_EVENT_THERMAL_THROTTLE = 2, + KFD_SMI_EVENT_GPU_PRE_RESET = 3, + KFD_SMI_EVENT_GPU_POST_RESET = 4, }; #define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) -- GitLab From 5dc1a0bcb758c343b873e8330ee986417f5a1727 Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Fri, 28 Aug 2020 19:53:08 -0400 Subject: [PATCH 0681/1494] include/uapi/linux: Fix indentation in kfd_smi_event enum Replace spaces with Tabs to fix indentation in kfd_smi_event enum. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- include/uapi/linux/kfd_ioctl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 8b7368bfbd846..695b606da4b15 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -450,9 +450,9 @@ struct kfd_ioctl_import_dmabuf_args { * KFD SMI(System Management Interface) events */ enum kfd_smi_event { - KFD_SMI_EVENT_NONE = 0, /* not used */ - KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ - KFD_SMI_EVENT_THERMAL_THROTTLE = 2, + KFD_SMI_EVENT_NONE = 0, /* not used */ + KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ + KFD_SMI_EVENT_THERMAL_THROTTLE = 2, KFD_SMI_EVENT_GPU_PRE_RESET = 3, KFD_SMI_EVENT_GPU_POST_RESET = 4, }; -- GitLab From bbcd521e1495056e939a37d0ac996d963a5ac32d Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:37 -0400 Subject: [PATCH 0682/1494] drm/nouveau/kms: Fix some indenting in nouveau_dp_detect() Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-2-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 8a0f7994e1aeb..ee778ddc95fae 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -76,10 +76,10 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); NV_DEBUG(drm, "encoder: %dx%d\n", - nv_encoder->dcb->dpconf.link_nr, - nv_encoder->dcb->dpconf.link_bw); + nv_encoder->dcb->dpconf.link_nr, + nv_encoder->dcb->dpconf.link_bw); if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; @@ -87,7 +87,7 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; NV_DEBUG(drm, "maximum: %dx%d\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); nouveau_dp_probe_oui(dev, aux, dpcd); -- GitLab From 6ba1193255ebf7eadf60f79c1555e507d0879ac3 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:38 -0400 Subject: [PATCH 0683/1494] drm/nouveau/kms/nv50-: Remove open-coded drm_dp_read_desc() Noticed this while going through our DP code - we use an open-coded version of drm_dp_read_desc() instead of just using the helper, so change that. This will also let us use quirks in the future if we end up needing them. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-3-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 ++- drivers/gpu/drm/nouveau/nouveau_dp.c | 30 +++++++-------------- drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 ++- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7674025a4bfe8..e12957e6faa7c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -435,7 +435,8 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) switch (nv_encoder->dcb->type) { case DCB_OUTPUT_DP: - ret = nouveau_dp_detect(nv_encoder); + ret = nouveau_dp_detect(nouveau_connector(connector), + nv_encoder); if (ret == NOUVEAU_DP_MST) return NULL; else if (ret == NOUVEAU_DP_SST) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index ee778ddc95fae..c4e9c21d4dd2b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,27 +36,9 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); -static void -nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - u8 buf[3]; - - if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) - return; - - if (!nvkm_rdaux(aux, DP_SINK_OUI, buf, 3)) - NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n", - buf[0], buf[1], buf[2]); - - if (!nvkm_rdaux(aux, DP_BRANCH_OUI, buf, 3)) - NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n", - buf[0], buf[1], buf[2]); - -} - int -nouveau_dp_detect(struct nouveau_encoder *nv_encoder) +nouveau_dp_detect(struct nouveau_connector *nv_connector, + struct nouveau_encoder *nv_encoder) { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -89,7 +71,13 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - nouveau_dp_probe_oui(dev, aux, dpcd); + ret = drm_dp_read_desc(&nv_connector->aux, &nv_encoder->dp.desc, + drm_dp_is_branch(dpcd)); + if (ret) { + NV_ERROR(drm, "Failed to read DP descriptor on %s: %d\n", + nv_connector->base.name, ret); + return ret; + } ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst); if (ret == 1) diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index a72c412ac8b14..6424cdcb4913f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -33,6 +33,7 @@ #include <drm/drm_dp_mst_helper.h> #include "dispnv04/disp.h" struct nv50_head_atom; +struct nouveau_connector; #define NV_DPMS_CLEARED 0x80 @@ -64,6 +65,7 @@ struct nouveau_encoder { struct nv50_mstm *mstm; int link_nr; int link_bw; + struct drm_dp_desc desc; } dp; }; @@ -104,7 +106,7 @@ enum nouveau_dp_status { NOUVEAU_DP_MST, }; -int nouveau_dp_detect(struct nouveau_encoder *); +int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, struct nouveau_encoder *, const struct drm_display_mode *, -- GitLab From 73596dbfde6c827756bd696599989d200f04bf69 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:39 -0400 Subject: [PATCH 0684/1494] drm/nouveau/kms/nv50-: Just use drm_dp_dpcd_read() in nouveau_dp.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this actually logs accesses, we should probably always be using this imho… Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-4-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index c4e9c21d4dd2b..8db9216d52c69 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -42,16 +42,12 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c_aux *aux; - u8 dpcd[8]; + struct drm_dp_aux *aux = &nv_connector->aux; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; int ret; - aux = nv_encoder->aux; - if (!aux) - return -ENODEV; - - ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd)); - if (ret) + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret != sizeof(dpcd)) return ret; nv_encoder->dp.link_bw = 27000 * dpcd[1]; -- GitLab From 57940402b58b0efe70fd276a7a0fbc394bdb587c Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:40 -0400 Subject: [PATCH 0685/1494] drm/nouveau/kms/nv50-: Use macros for DP registers in nouveau_dp.c No functional changes. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-5-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 8db9216d52c69..4030806e3522b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -50,11 +50,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, if (ret != sizeof(dpcd)) return ret; - nv_encoder->dp.link_bw = 27000 * dpcd[1]; - nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + nv_encoder->dp.link_bw = 27000 * dpcd[DP_MAX_LINK_RATE]; + nv_encoder->dp.link_nr = + dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, + dpcd[DP_DPCD_REV]); NV_DEBUG(drm, "encoder: %dx%d\n", nv_encoder->dcb->dpconf.link_nr, nv_encoder->dcb->dpconf.link_bw); -- GitLab From 254e7e3bfcfcae829e120e53e21050e2fe5ce1d7 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:41 -0400 Subject: [PATCH 0686/1494] drm/nouveau/kms: Don't clear DP_MST_CTRL DPCD in nv50_mstm_new() Since commit fa3cdf8d0b09 ("drm/nouveau: Reset MST branching unit before enabling") we've been clearing DP_MST_CTRL before we start enabling MST. Since then clearing DP_MST_CTRL in nv50_mstm_new() has been unnecessary and redundant, so let's remove it. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-6-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index e7874877da858..c4d138f0ca054 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1535,17 +1535,6 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, struct drm_device *dev = outp->base.base.dev; struct nv50_mstm *mstm; int ret; - u8 dpcd; - - /* This is a workaround for some monitors not functioning - * correctly in MST mode on initial module load. I think - * some bad interaction with the VBIOS may be responsible. - * - * A good ol' off and on again seems to work here ;) - */ - ret = drm_dp_dpcd_readb(aux, DP_DPCD_REV, &dpcd); - if (ret >= 0 && dpcd >= 0x12) - drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0); if (!(mstm = *pmstm = kzalloc(sizeof(*mstm), GFP_KERNEL))) return -ENOMEM; -- GitLab From 09838c4efe9afb6fefa889d92c3571d49029af26 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:42 -0400 Subject: [PATCH 0687/1494] drm/nouveau/kms: Search for encoders' connectors properly While the way we find the associated connector for an encoder is just fine for legacy modesetting, it's not correct for nv50+ since that uses atomic modesetting. For reference, see the drm_encoder kdocs. Fix this by removing nouveau_encoder_connector_get(), and replacing it with nv04_encoder_get_connector(), nv50_outp_get_old_connector(), and nv50_outp_get_new_connector(). v2: * Don't line-wrap for_each_(old|new)_connector_in_state in nv50_outp_get_(old|new)_connector() - sravn v3: * Fix potential uninitialized usage of nv_connector (needs to be initialized to NULL at the start). Thanks kernel test robot! v4: * Actually fix uninitialized nv_connector usage in nv50_audio_component_get_eld(). The previous fix wouldn't have worked since we would have started out with nv_connector == NULL, but wouldn't clear it after a single drm_for_each_encoder() iteration. Thanks again Kernel bot! Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-7-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv04/dac.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 7 +- drivers/gpu/drm/nouveau/dispnv04/disp.c | 18 +++++ drivers/gpu/drm/nouveau/dispnv04/disp.h | 4 + drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 88 +++++++++++++++++---- drivers/gpu/drm/nouveau/nouveau_connector.c | 14 ---- drivers/gpu/drm/nouveau/nouveau_encoder.h | 6 +- 9 files changed, 105 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index ffdd447d87068..22d10f3285597 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -419,7 +419,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index f9f4482c79b54..42687ea2a4ca3 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -184,7 +184,8 @@ static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); + struct nouveau_connector *nv_connector = + nv04_encoder_get_connector(nv_encoder); if (!nv_connector->native_mode || nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || @@ -478,7 +479,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -591,7 +592,7 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) { struct nouveau_connector *connector = - nouveau_encoder_connector_get(nv_encoder); + nv04_encoder_get_connector(nv_encoder); if (connector && connector->native_mode) call_lvds_script(dev, nv_encoder->dcb, head, diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 900ab69df7e8f..3f046b917c85c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -35,6 +35,24 @@ #include <nvif/if0004.h> +struct nouveau_connector * +nv04_encoder_get_connector(struct nouveau_encoder *encoder) +{ + struct drm_device *dev = to_drm_encoder(encoder)->dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + struct nouveau_connector *nv_connector = NULL; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->encoder == to_drm_encoder(encoder)) + nv_connector = nouveau_connector(connector); + } + drm_connector_list_iter_end(&conn_iter); + + return nv_connector; +} + static void nv04_display_fini(struct drm_device *dev, bool suspend) { diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index 495d3284e8766..5ace5e906949a 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -6,6 +6,8 @@ #include "nouveau_display.h" +struct nouveau_encoder; + enum nv04_fp_display_regs { FP_DISPLAY_END, FP_TOTAL, @@ -93,6 +95,8 @@ nv04_display(struct drm_device *dev) /* nv04_display.c */ int nv04_display_create(struct drm_device *); +struct nouveau_connector * +nv04_encoder_get_connector(struct nouveau_encoder *nv_encoder); /* nv04_crtc.c */ int nv04_crtc_create(struct drm_device *, int index); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index b701a4d8fe760..3ba7b59580d59 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -172,7 +172,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 3a9489ed6544f..be28e7bd74903 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -599,7 +599,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c4d138f0ca054..255a281249bc8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -411,6 +411,40 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, return 0; } +struct nouveau_connector * +nv50_outp_get_new_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *connector_state; + struct drm_encoder *encoder = to_drm_encoder(outp); + int i; + + for_each_new_connector_in_state(state, connector, connector_state, i) { + if (connector_state->best_encoder == encoder) + return nouveau_connector(connector); + } + + return NULL; +} + +struct nouveau_connector * +nv50_outp_get_old_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *connector_state; + struct drm_encoder *encoder = to_drm_encoder(outp); + int i; + + for_each_old_connector_in_state(state, connector, connector_state, i) { + if (connector_state->best_encoder == encoder) + return nouveau_connector(connector); + } + + return NULL; +} + /****************************************************************************** * DAC *****************************************************************************/ @@ -552,16 +586,31 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, struct nouveau_drm *drm = nouveau_drm(drm_dev); struct drm_encoder *encoder; struct nouveau_encoder *nv_encoder; - struct nouveau_connector *nv_connector; + struct drm_connector *connector; struct nouveau_crtc *nv_crtc; + struct drm_connector_list_iter conn_iter; int ret = 0; *enabled = false; + drm_for_each_encoder(encoder, drm->dev) { + struct nouveau_connector *nv_connector = NULL; + nv_encoder = nouveau_encoder(encoder); - nv_connector = nouveau_encoder_connector_get(nv_encoder); + + drm_connector_list_iter_begin(drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->state->best_encoder == encoder) { + nv_connector = nouveau_connector(connector); + break; + } + } + drm_connector_list_iter_end(&conn_iter); + if (!nv_connector) + continue; + nv_crtc = nouveau_crtc(encoder->crtc); - if (!nv_connector || !nv_crtc || nv_encoder->or != port || + if (!nv_crtc || nv_encoder->or != port || nv_crtc->index != dev_id) continue; *enabled = nv_encoder->audio; @@ -572,6 +621,7 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, } break; } + return ret; } @@ -665,7 +715,8 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) } static void -nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_audio_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, + struct drm_display_mode *mode) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -686,7 +737,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) (0x0100 << nv_crtc->index), }; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); if (!drm_detect_monitor_audio(nv_connector->edid)) return; @@ -723,7 +774,8 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) } static void -nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, + struct drm_display_mode *mode) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -752,7 +804,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) int ret; int size; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); if (!drm_detect_hdmi_monitor(nv_connector->edid)) return; @@ -798,7 +850,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) + args.pwr.vendor_infoframe_length; nvif_mthd(&disp->disp->object, 0, &args, size); - nv50_audio_enable(encoder, mode); + nv50_audio_enable(encoder, state, mode); /* If SCDC is supported by the downstream monitor, update * divider / scrambling settings to what we programmed above. @@ -1573,7 +1625,8 @@ nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head, } static void -nv50_sor_disable(struct drm_encoder *encoder) +nv50_sor_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); @@ -1601,7 +1654,8 @@ nv50_sor_disable(struct drm_encoder *encoder) } static void -nv50_sor_enable(struct drm_encoder *encoder) +nv50_sor_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -1625,7 +1679,7 @@ nv50_sor_enable(struct drm_encoder *encoder) u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM; u8 depth = NV837D_SOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); nv_encoder->crtc = encoder->crtc; if ((disp->disp->object.oclass == GT214_DISP || @@ -1652,7 +1706,7 @@ nv50_sor_enable(struct drm_encoder *encoder) proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B; } - nv50_hdmi_enable(&nv_encoder->base.base, mode); + nv50_hdmi_enable(&nv_encoder->base.base, state, mode); break; case DCB_OUTPUT_LVDS: proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM; @@ -1693,7 +1747,7 @@ nv50_sor_enable(struct drm_encoder *encoder) else proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B; - nv50_audio_enable(encoder, mode); + nv50_audio_enable(encoder, state, mode); break; default: BUG(); @@ -1706,8 +1760,8 @@ nv50_sor_enable(struct drm_encoder *encoder) static const struct drm_encoder_helper_funcs nv50_sor_help = { .atomic_check = nv50_outp_atomic_check, - .enable = nv50_sor_enable, - .disable = nv50_sor_disable, + .atomic_enable = nv50_sor_enable, + .atomic_disable = nv50_sor_disable, }; static void @@ -2066,7 +2120,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) outp->clr.mask, outp->set.mask); if (outp->clr.mask) { - help->disable(encoder); + help->atomic_disable(encoder, state); interlock[NV50_DISP_INTERLOCK_CORE] |= 1; if (outp->flush_disable) { nv50_disp_atomic_commit_wndw(state, interlock); @@ -2105,7 +2159,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) outp->set.mask, outp->clr.mask); if (outp->set.mask) { - help->enable(encoder); + help->atomic_enable(encoder, state); interlock[NV50_DISP_INTERLOCK_CORE] = 1; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index e12957e6faa7c..1d5696c39792a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -391,20 +391,6 @@ find_encoder(struct drm_connector *connector, int type) return NULL; } -struct nouveau_connector * -nouveau_encoder_connector_get(struct nouveau_encoder *encoder) -{ - struct drm_device *dev = to_drm_encoder(encoder)->dev; - struct drm_connector *drm_connector; - - list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { - if (drm_connector->encoder == to_drm_encoder(encoder)) - return nouveau_connector(drm_connector); - } - - return NULL; -} - static void nouveau_connector_destroy(struct drm_connector *connector) { diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 6424cdcb4913f..b0e1dad2367d6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -113,7 +113,11 @@ enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, unsigned *clock); struct nouveau_connector * -nouveau_encoder_connector_get(struct nouveau_encoder *encoder); +nv50_outp_get_new_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state); +struct nouveau_connector * +nv50_outp_get_old_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state); int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow); void nv50_mstm_remove(struct nv50_mstm *); -- GitLab From 4944245cebb9daaf740d388fb61e2a824befbdb5 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:43 -0400 Subject: [PATCH 0688/1494] drm/nouveau/kms/nv50-: Use drm_dp_dpcd_(readb|writeb)() in nv50_sor_disable() Just use drm_dp_dpcd_(readb|writeb)() so we get automatic DPCD logging Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-8-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 255a281249bc8..612d98fa0a2dc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1630,19 +1630,22 @@ nv50_sor_disable(struct drm_encoder *encoder, { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); + struct nouveau_connector *nv_connector = + nv50_outp_get_old_connector(nv_encoder, state); nv_encoder->crtc = NULL; if (nv_crtc) { - struct nvkm_i2c_aux *aux = nv_encoder->aux; + struct drm_dp_aux *aux = &nv_connector->aux; u8 pwr; - if (aux) { - int ret = nvkm_rdaux(aux, DP_SET_POWER, &pwr, 1); + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { + int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr); + if (ret == 0) { pwr &= ~DP_SET_POWER_MASK; pwr |= DP_SET_POWER_D3; - nvkm_wraux(aux, DP_SET_POWER, &pwr, 1); + drm_dp_dpcd_writeb(aux, DP_SET_POWER, pwr); } } -- GitLab From a0922278f83eae085fdf73d06f71bbdfb9d6789e Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:44 -0400 Subject: [PATCH 0689/1494] drm/nouveau/kms/nv50-: Refactor and cleanup DP HPD handling First some backstory here: Currently, we keep track of whether or not we've enabled MST or not by trying to piggy-back off the MST helpers. This means that in order to check whether MST is enabled or not, we actually need to grab drm_dp_mst_topology_mgr.lock. Back when I originally wrote this, I did this piggy-backing with the intention that I'd eventually be teaching our MST helpers how to recover when an MST device has stopped responding, which in turn would require the MST helpers having a way of disabling MST independently of the driver. Note that this was before I reworked locking in the MST helpers, so at the time we were sticking random things under &mgr->lock - which grabbing this lock was meant to protect against. This never came to fruition because doing such a reset safely turned out to be a lot more painful and impossible then it sounds, and also just risks us working around issues with our MST handlers that should be properly fixed instead. Even if it did though, simply calling drm_dp_mst_topology_mgr_set_mst() from the MST helpers (with the exception of when we're tearing down our MST managers, that's always OK) wouldn't have been a bad idea, since drivers like nouveau and i915 need to do their own book keeping immediately after disabling MST. So-implementing that would likely require adding a hook for helper-triggered MST disables anyway. So, fast forward to now - we want to start adding support for all of the miscellaneous bits of the DP protocol (for both SST and MST) we're missing before moving on to supporting more complicated features like supporting different BPP values on MST, DSC, etc. Since many of these features only exist on SST and make use of DP HPD IRQs, we want to be able to atomically check whether we're servicing an MST IRQ or SST IRQ in nouveau_connector_hotplug(). Currently we literally don't do this at all, and just handle any kind of possible DP IRQ we could get including ESIs - even if MST isn't actually enabled. This would be very complicated and difficult to fix if we need to hold &mgr->lock while handling SST IRQs to ensure that the MST topology state doesn't change under us. What we really want here is to do our own tracking of whether MST is enabled or not, similar to drivers like i915, and define our own locking order to decomplicate things and avoid hitting locking issues in the future. So, let's do this by refactoring our MST probing/enabling code to use our own MST bookkeeping, along with adding a lock for protecting DP state that needs to be checked outside of our connector probing functions. While we're at it, we also remove a bunch of unneeded steps we perform when probing/enabling MST: * Enabling bits in MSTM_CTRL before calling drm_dp_mst_topology_mgr_set_mst(). I don't think these ever actually did anything, since the nvif methods for enabling MST don't actually do anything DPCD related and merely indicate to nvkm that we've turned on MST. * Checking the MSTM_CTRL bit is intact when checking the state of an enabled MST topology in nv50_mstm_detect(). I just added this to be safe originally, but now that we try reading the DPCD when probing DP connectors it shouldn't be needed as that will abort our hotplug probing if the device was removed well before we start checking for MST.. * All of the duplicate DPCD version checks. This leaves us with much nicer looking code, a much more sensible locking scheme, and an easy way of checking whether MST is enabled or not for handling DP HPD IRQs. v2: * Get rid of accidental newlines v4: * Fix uninitialized usage of mstm in nv50_mstm_detect() - thanks kernel bot! Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-9-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv04/disp.c | 6 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 192 +++++++++----------- drivers/gpu/drm/nouveau/nouveau_connector.c | 14 +- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.h | 2 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 132 ++++++++++++-- drivers/gpu/drm/nouveau/nouveau_encoder.h | 33 +++- 7 files changed, 244 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 3f046b917c85c..3ee836dc5058f 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -54,8 +54,9 @@ nv04_encoder_get_connector(struct nouveau_encoder *encoder) } static void -nv04_display_fini(struct drm_device *dev, bool suspend) +nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend) { + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_display *disp = nv04_display(dev); struct drm_crtc *crtc; @@ -67,6 +68,9 @@ nv04_display_fini(struct drm_device *dev, bool suspend) if (nv_two_heads(dev)) NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); + if (!runtime) + cancel_work_sync(&drm->hpd_work); + if (!suspend) return; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 612d98fa0a2dc..8e1effb10425d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -879,16 +879,6 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, #define nv50_mstc(p) container_of((p), struct nv50_mstc, connector) #define nv50_msto(p) container_of((p), struct nv50_msto, encoder) -struct nv50_mstm { - struct nouveau_encoder *outp; - - struct drm_dp_mst_topology_mgr mgr; - - bool modified; - bool disabled; - int links; -}; - struct nv50_mstc { struct nv50_mstm *mstm; struct drm_dp_mst_port *port; @@ -1417,41 +1407,51 @@ nv50_mstm = { .add_connector = nv50_mstm_add_connector, }; -void -nv50_mstm_service(struct nv50_mstm *mstm) +bool +nv50_mstm_service(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector, + struct nv50_mstm *mstm) { - struct drm_dp_aux *aux = mstm ? mstm->mgr.aux : NULL; - bool handled = true; - int ret; + struct drm_dp_aux *aux = &nv_connector->aux; + bool handled = true, ret = true; + int rc; u8 esi[8] = {}; - if (!aux) - return; - while (handled) { - ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8); - if (ret != 8) { - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); - return; + rc = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8); + if (rc != 8) { + ret = false; + break; } drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled); if (!handled) break; - drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], 3); + rc = drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], + 3); + if (rc != 3) { + ret = false; + break; + } } + + if (!ret) + NV_DEBUG(drm, "Failed to handle ESI on %s: %d\n", + nv_connector->base.name, rc); + + return ret; } void nv50_mstm_remove(struct nv50_mstm *mstm) { - if (mstm) - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); + mstm->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); } static int -nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state) +nv50_mstm_enable(struct nv50_mstm *mstm, int state) { struct nouveau_encoder *outp = mstm->outp; struct { @@ -1466,106 +1466,85 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state) }; struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev); struct nvif_object *disp = &drm->display->disp.object; - int ret; - - if (dpcd >= 0x12) { - /* Even if we're enabling MST, start with disabling the - * branching unit to clear any sink-side MST topology state - * that wasn't set by us - */ - ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, 0); - if (ret < 0) - return ret; - - if (state) { - /* Now, start initializing */ - ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, - DP_MST_EN); - if (ret < 0) - return ret; - } - } return nvif_mthd(disp, 0, &args, sizeof(args)); } int -nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow) +nv50_mstm_detect(struct nouveau_encoder *outp) { + struct nv50_mstm *mstm = outp->dp.mstm; struct drm_dp_aux *aux; int ret; - bool old_state, new_state; - u8 mstm_ctrl; - if (!mstm) + if (!mstm || !mstm->can_mst) return 0; - mutex_lock(&mstm->mgr.lock); - - old_state = mstm->mgr.mst_state; - new_state = old_state; aux = mstm->mgr.aux; - if (old_state) { - /* Just check that the MST hub is still as we expect it */ - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CTRL, &mstm_ctrl); - if (ret < 0 || !(mstm_ctrl & DP_MST_EN)) { - DRM_DEBUG_KMS("Hub gone, disabling MST topology\n"); - new_state = false; - } - } else if (dpcd[0] >= 0x12) { - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &dpcd[1]); - if (ret < 0) - goto probe_error; - - if (!(dpcd[1] & DP_MST_CAP)) - dpcd[0] = 0x11; - else - new_state = allow; - } - - if (new_state == old_state) { - mutex_unlock(&mstm->mgr.lock); - return new_state; - } - - ret = nv50_mstm_enable(mstm, dpcd[0], new_state); - if (ret) - goto probe_error; - - mutex_unlock(&mstm->mgr.lock); + /* Clear any leftover MST state we didn't set ourselves by first + * disabling MST if it was already enabled + */ + ret = drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0); + if (ret < 0) + return ret; - ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, new_state); + /* And start enabling */ + ret = nv50_mstm_enable(mstm, true); if (ret) - return nv50_mstm_enable(mstm, dpcd[0], 0); + return ret; - return new_state; + ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, true); + if (ret) { + nv50_mstm_enable(mstm, false); + return ret; + } -probe_error: - mutex_unlock(&mstm->mgr.lock); - return ret; + mstm->is_mst = true; + return 1; } static void -nv50_mstm_fini(struct nv50_mstm *mstm) +nv50_mstm_fini(struct nouveau_encoder *outp) { - if (mstm && mstm->mgr.mst_state) + struct nv50_mstm *mstm = outp->dp.mstm; + + if (!mstm) + return; + + /* Don't change the MST state of this connector until we've finished + * resuming, since we can't safely grab hpd_irq_lock in our resume + * path to protect mstm->is_mst without potentially deadlocking + */ + mutex_lock(&outp->dp.hpd_irq_lock); + mstm->suspended = true; + mutex_unlock(&outp->dp.hpd_irq_lock); + + if (mstm->is_mst) drm_dp_mst_topology_mgr_suspend(&mstm->mgr); } static void -nv50_mstm_init(struct nv50_mstm *mstm, bool runtime) +nv50_mstm_init(struct nouveau_encoder *outp, bool runtime) { - int ret; + struct nv50_mstm *mstm = outp->dp.mstm; + int ret = 0; - if (!mstm || !mstm->mgr.mst_state) + if (!mstm) return; - ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr, !runtime); - if (ret == -1) { - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); - drm_kms_helper_hotplug_event(mstm->mgr.dev); + if (mstm->is_mst) { + ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr, !runtime); + if (ret == -1) + nv50_mstm_remove(mstm); } + + mutex_lock(&outp->dp.hpd_irq_lock); + mstm->suspended = false; + mutex_unlock(&outp->dp.hpd_irq_lock); + + if (ret == -1) + drm_kms_helper_hotplug_event(mstm->mgr.dev); } static void @@ -1773,6 +1752,10 @@ nv50_sor_destroy(struct drm_encoder *encoder) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); nv50_mstm_del(&nv_encoder->dp.mstm); drm_encoder_cleanup(encoder); + + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) + mutex_destroy(&nv_encoder->dp.hpd_irq_lock); + kfree(encoder); } @@ -1832,6 +1815,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, dcbe->i2c_index); + mutex_init(&nv_encoder->dp.hpd_irq_lock); + if (aux) { if (disp->disp->object.oclass < GF110_DISP) { /* HW has no support for address-only @@ -2530,9 +2515,9 @@ nv50_disp_func = { *****************************************************************************/ static void -nv50_display_fini(struct drm_device *dev, bool suspend) +nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) { - struct nouveau_encoder *nv_encoder; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder *encoder; struct drm_plane *plane; @@ -2544,11 +2529,12 @@ nv50_display_fini(struct drm_device *dev, bool suspend) } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { - nv_encoder = nouveau_encoder(encoder); - nv50_mstm_fini(nv_encoder->dp.mstm); - } + if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) + nv50_mstm_fini(nouveau_encoder(encoder)); } + + if (!runtime) + cancel_work_sync(&drm->hpd_work); } static int @@ -2565,7 +2551,7 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv50_mstm_init(nv_encoder->dp.mstm, runtime); + nv50_mstm_init(nv_encoder, runtime); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1d5696c39792a..b90591114faaf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1143,19 +1143,15 @@ nouveau_connector_hotplug(struct nvif_notify *notify) struct nouveau_connector *nv_connector = container_of(notify, typeof(*nv_connector), hpd); struct drm_connector *connector = &nv_connector->base; - struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); const struct nvif_notify_conn_rep_v0 *rep = notify->data; const char *name = connector->name; - struct nouveau_encoder *nv_encoder; int ret; bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { - NV_DEBUG(drm, "service %s\n", name); - drm_dp_cec_irq(&nv_connector->aux); - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) - nv50_mstm_service(nv_encoder->dp.mstm); - + nouveau_dp_irq(drm, nv_connector); return NVIF_NOTIFY_KEEP; } @@ -1181,10 +1177,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) if (!plugged) drm_dp_cec_unset_edid(&nv_connector->aux); NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) { - if (!plugged) - nv50_mstm_remove(nv_encoder->dp.mstm); - } drm_helper_hpd_irq_event(connector->dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 5f31b11ac2e7e..13016769a194b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -569,7 +569,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) cancel_work_sync(&drm->hpd_work); drm_kms_helper_poll_disable(dev); - disp->fini(dev, suspend); + disp->fini(dev, runtime, suspend); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 6e0d900441d69..76ba93e01aff4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -18,7 +18,7 @@ struct nouveau_display { void *priv; void (*dtor)(struct drm_device *); int (*init)(struct drm_device *, bool resume, bool runtime); - void (*fini)(struct drm_device *, bool suspend); + void (*fini)(struct drm_device *, bool suspend, bool runtime); struct nvif_disp disp; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 4030806e3522b..032afc73e2a33 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,19 +36,89 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); +static enum drm_connector_status +nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, + struct nouveau_encoder *outp) +{ + struct drm_dp_aux *aux = &nv_connector->aux; + struct nv50_mstm *mstm = NULL; + int ret; + u8 *dpcd = outp->dp.dpcd; + u8 tmp; + + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { + ret = drm_dp_read_desc(aux, &outp->dp.desc, + drm_dp_is_branch(dpcd)); + if (ret < 0) + return connector_status_disconnected; + } else { + return connector_status_disconnected; + } + + if (nouveau_mst) + mstm = outp->dp.mstm; + + if (mstm) { + if (dpcd[DP_DPCD_REV] >= DP_DPCD_REV_12) { + ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &tmp); + if (ret < 0) + return connector_status_disconnected; + + mstm->can_mst = !!(tmp & DP_MST_CAP); + } else { + mstm->can_mst = false; + } + } + + return connector_status_connected; +} + int nouveau_dp_detect(struct nouveau_connector *nv_connector, struct nouveau_encoder *nv_encoder) { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct drm_dp_aux *aux = &nv_connector->aux; - u8 dpcd[DP_RECEIVER_CAP_SIZE]; - int ret; + struct drm_connector *connector = &nv_connector->base; + struct nv50_mstm *mstm = nv_encoder->dp.mstm; + enum drm_connector_status status; + u8 *dpcd = nv_encoder->dp.dpcd; + int ret = NOUVEAU_DP_NONE; + + /* If we've already read the DPCD on an eDP device, we don't need to + * reread it as it won't change + */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && + dpcd[DP_DPCD_REV] != 0) + return NOUVEAU_DP_SST; - ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); - if (ret != sizeof(dpcd)) - return ret; + mutex_lock(&nv_encoder->dp.hpd_irq_lock); + if (mstm) { + /* If we're not ready to handle MST state changes yet, just + * report the last status of the connector. We'll reprobe it + * once we've resumed. + */ + if (mstm->suspended) { + if (mstm->is_mst) + ret = NOUVEAU_DP_MST; + else if (connector->status == + connector_status_connected) + ret = NOUVEAU_DP_SST; + + goto out; + } + } + + status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder); + if (status == connector_status_disconnected) + goto out; + + /* If we're in MST mode, we're done here */ + if (mstm && mstm->can_mst && mstm->is_mst) { + ret = NOUVEAU_DP_MST; + goto out; + } nv_encoder->dp.link_bw = 27000 * dpcd[DP_MAX_LINK_RATE]; nv_encoder->dp.link_nr = @@ -69,22 +139,50 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - ret = drm_dp_read_desc(&nv_connector->aux, &nv_encoder->dp.desc, - drm_dp_is_branch(dpcd)); - if (ret) { - NV_ERROR(drm, "Failed to read DP descriptor on %s: %d\n", - nv_connector->base.name, ret); - return ret; + if (mstm && mstm->can_mst) { + ret = nv50_mstm_detect(nv_encoder); + if (ret == 1) { + ret = NOUVEAU_DP_MST; + goto out; + } else if (ret != 0) { + goto out; + } } + ret = NOUVEAU_DP_SST; - ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst); - if (ret == 1) - return NOUVEAU_DP_MST; - if (ret == 0) - return NOUVEAU_DP_SST; +out: + if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST) + nv50_mstm_remove(mstm); + + mutex_unlock(&nv_encoder->dp.hpd_irq_lock); return ret; } +void nouveau_dp_irq(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector) +{ + struct drm_connector *connector = &nv_connector->base; + struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); + struct nv50_mstm *mstm; + + if (!outp) + return; + + mstm = outp->dp.mstm; + NV_DEBUG(drm, "service %s\n", connector->name); + + mutex_lock(&outp->dp.hpd_irq_lock); + + if (mstm && mstm->is_mst) { + if (!nv50_mstm_service(drm, nv_connector, mstm)) + schedule_work(&drm->hpd_work); + } else { + drm_dp_cec_irq(&nv_connector->aux); + } + + mutex_unlock(&outp->dp.hpd_irq_lock); +} + /* TODO: * - Use the minimum possible BPC here, once we add support for the max bpc * property. diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index b0e1dad2367d6..eef4643f5f982 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -65,6 +65,13 @@ struct nouveau_encoder { struct nv50_mstm *mstm; int link_nr; int link_bw; + + /* Protects DP state that needs to be accessed outside + * connector reprobing contexts + */ + struct mutex hpd_irq_lock; + + u8 dpcd[DP_RECEIVER_CAP_SIZE]; struct drm_dp_desc desc; } dp; }; @@ -79,6 +86,21 @@ struct nouveau_encoder { struct nv50_head_atom *, u8 proto, u8 depth); }; +struct nv50_mstm { + struct nouveau_encoder *outp; + + struct drm_dp_mst_topology_mgr mgr; + + /* Protected under nouveau_encoder->dp.hpd_irq_lock */ + bool can_mst; + bool is_mst; + bool suspended; + + bool modified; + bool disabled; + int links; +}; + struct nouveau_encoder * find_encoder(struct drm_connector *connector, int type); @@ -102,11 +124,14 @@ get_slave_funcs(struct drm_encoder *enc) /* nouveau_dp.c */ enum nouveau_dp_status { + NOUVEAU_DP_NONE, NOUVEAU_DP_SST, NOUVEAU_DP_MST, }; int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); +void nouveau_dp_irq(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, struct nouveau_encoder *, const struct drm_display_mode *, @@ -119,7 +144,9 @@ struct nouveau_connector * nv50_outp_get_old_connector(struct nouveau_encoder *outp, struct drm_atomic_state *state); -int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow); -void nv50_mstm_remove(struct nv50_mstm *); -void nv50_mstm_service(struct nv50_mstm *); +int nv50_mstm_detect(struct nouveau_encoder *encoder); +void nv50_mstm_remove(struct nv50_mstm *mstm); +bool nv50_mstm_service(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector, + struct nv50_mstm *mstm); #endif /* __NOUVEAU_ENCODER_H__ */ -- GitLab From 4b4659128e634ce65dc02acf297d623f5bc97497 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:45 -0400 Subject: [PATCH 0690/1494] drm/i915/dp: Extract drm_dp_read_mst_cap() Just a tiny drive-by cleanup, we can consolidate i915's code for checking for MST support into a helper to be shared across drivers. v5: * Drop !!() * Move drm_dp_has_mst() out of header * Change name from drm_dp_has_mst() to drm_dp_read_mst_cap() Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Sean Paul <sean@poorly.run> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-10-lyude@redhat.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 18 ++---------------- include/drm/drm_dp_mst_helper.h | 3 +-- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b23cb2fec3f35..61755c26fac03 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3486,6 +3486,28 @@ static int drm_dp_get_vc_payload_bw(u8 dp_link_bw, u8 dp_link_count) return dp_link_bw * dp_link_count / 2; } +/** + * drm_dp_read_mst_cap() - check whether or not a sink supports MST + * @aux: The DP AUX channel to use + * @dpcd: A cached copy of the DPCD capabilities for this sink + * + * Returns: %True if the sink supports MST, %false otherwise + */ +bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 mstm_cap; + + if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) + return false; + + if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1) + return false; + + return mstm_cap & DP_MST_CAP; +} +EXPORT_SYMBOL(drm_dp_read_mst_cap); + /** * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager * @mgr: manager to set state for diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 79c27f91f42c0..4c7314b7a84e4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4699,20 +4699,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return true; } -static bool -intel_dp_sink_can_mst(struct intel_dp *intel_dp) -{ - u8 mstm_cap; - - if (intel_dp->dpcd[DP_DPCD_REV] < 0x12) - return false; - - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_MSTM_CAP, &mstm_cap) != 1) - return false; - - return mstm_cap & DP_MST_CAP; -} - static bool intel_dp_can_mst(struct intel_dp *intel_dp) { @@ -4720,7 +4706,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) return i915->params.enable_dp_mst && intel_dp->can_mst && - intel_dp_sink_can_mst(intel_dp); + drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); } static void @@ -4729,7 +4715,7 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - bool sink_can_mst = intel_dp_sink_can_mst(intel_dp); + bool sink_can_mst = drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n", diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 8b9eb4db3381c..6ae5860d8644e 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -728,10 +728,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); - +bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); - int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); -- GitLab From 8b75e83e9c94dbf619cf2499ec85656eed9d0320 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:46 -0400 Subject: [PATCH 0691/1494] drm/nouveau/kms: Use new drm_dp_read_mst_cap() helper for checking MST caps Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-11-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 032afc73e2a33..a5934064a75ea 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -44,7 +44,6 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, struct nv50_mstm *mstm = NULL; int ret; u8 *dpcd = outp->dp.dpcd; - u8 tmp; ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { @@ -56,19 +55,10 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, return connector_status_disconnected; } - if (nouveau_mst) + if (nouveau_mst) { mstm = outp->dp.mstm; - - if (mstm) { - if (dpcd[DP_DPCD_REV] >= DP_DPCD_REV_12) { - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &tmp); - if (ret < 0) - return connector_status_disconnected; - - mstm->can_mst = !!(tmp & DP_MST_CAP); - } else { - mstm->can_mst = false; - } + if (mstm) + mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } return connector_status_connected; -- GitLab From 02bb7fe2d3eacb5ca1cec597ad16eff93ae8d769 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:47 -0400 Subject: [PATCH 0692/1494] drm/nouveau/kms: Move drm_dp_cec_unset_edid() into nouveau_connector_detect() For whatever reason we currently unset the EDID for DP CEC support when responding to the connector being unplugged, instead of just doing it in nouveau_connector_detect() where we set the CEC EDID. This isn't really needed and could even potentially cause us to forget to unset the EDID if the connector is removed without a corresponding hpd event, so let's fix that. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-12-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index b90591114faaf..4a29f691c08e4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -633,10 +633,11 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) conn_status = connector_status_connected; goto out; } - } out: + if (!nv_connector->edid) + drm_dp_cec_unset_edid(&nv_connector->aux); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1174,8 +1175,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) return NVIF_NOTIFY_DROP; } - if (!plugged) - drm_dp_cec_unset_edid(&nv_connector->aux); NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); drm_helper_hpd_irq_event(connector->dev); -- GitLab From d297ce4b5d490eab60bede36bfd5da6fbcd416cf Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:48 -0400 Subject: [PATCH 0693/1494] drm/nouveau/kms: Only use hpd_work for reprobing in HPD paths Currently we perform both short IRQ handling for DP, and connector reprobing in the HPD IRQ handler. However since we need to grab connection_mutex in order to reprobe a connector, in theory we could accidentally block ourselves from handling any short IRQs until after a modeset completes if a connector hotplug happens to occur in parallel with a modeset. I haven't seen this actually happen yet, but since we're cleaning up nouveau's hotplug handling code anyway and we already have a hpd worker, we can simply fix this by only relying on the HPD worker to actually reprobe connectors when we receive a HPD IRQ. We also add a mask to nouveau_drm to keep track of which connectors are waiting to be reprobed in response to an HPD IRQ. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-13-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 42 +++++-------- drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 70 ++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_display.h | 1 + drivers/gpu/drm/nouveau/nouveau_dp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 4 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 + 7 files changed, 86 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 4a29f691c08e4..637e91594fbe8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1138,6 +1138,20 @@ nouveau_connector_funcs_lvds = { .early_unregister = nouveau_connector_early_unregister, }; +void +nouveau_connector_hpd(struct drm_connector *connector) +{ + struct nouveau_drm *drm = nouveau_drm(connector->dev); + u32 mask = drm_connector_mask(connector); + + mutex_lock(&drm->hpd_lock); + if (!(drm->hpd_pending & mask)) { + drm->hpd_pending |= mask; + schedule_work(&drm->hpd_work); + } + mutex_unlock(&drm->hpd_lock); +} + static int nouveau_connector_hotplug(struct nvif_notify *notify) { @@ -1147,8 +1161,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); const struct nvif_notify_conn_rep_v0 *rep = notify->data; - const char *name = connector->name; - int ret; bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { @@ -1156,31 +1168,9 @@ nouveau_connector_hotplug(struct nvif_notify *notify) return NVIF_NOTIFY_KEEP; } - ret = pm_runtime_get(drm->dev->dev); - if (ret == 0) { - /* We can't block here if there's a pending PM request - * running, as we'll deadlock nouveau_display_fini() when it - * calls nvif_put() on our nvif_notify struct. So, simply - * defer the hotplug event until the device finishes resuming - */ - NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n", - name); - schedule_work(&drm->hpd_work); - - pm_runtime_put_noidle(drm->dev->dev); - return NVIF_NOTIFY_KEEP; - } else if (ret != 1 && ret != -EACCES) { - NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n", - name, ret); - return NVIF_NOTIFY_DROP; - } - - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); - - drm_helper_hpd_irq_event(connector->dev); + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name); + nouveau_connector_hpd(connector); - pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_autosuspend(drm->dev->dev); return NVIF_NOTIFY_KEEP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index d6de5cb8e2238..d0b859c4a80ea 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -187,6 +187,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) struct drm_connector * nouveau_connector_create(struct drm_device *, const struct dcb_output *); +void nouveau_connector_hpd(struct drm_connector *connector); extern int nouveau_tv_disable; extern int nouveau_ignorelid; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 13016769a194b..bceb48a2dfca6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -457,16 +457,70 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = { } \ } while(0) +void +nouveau_display_hpd_resume(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + + mutex_lock(&drm->hpd_lock); + drm->hpd_pending = ~0; + mutex_unlock(&drm->hpd_lock); + + schedule_work(&drm->hpd_work); +} + static void nouveau_display_hpd_work(struct work_struct *work) { struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work); + struct drm_device *dev = drm->dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + u32 pending; + bool changed = false; + + pm_runtime_get_sync(dev->dev); - pm_runtime_get_sync(drm->dev->dev); + mutex_lock(&drm->hpd_lock); + pending = drm->hpd_pending; + drm->hpd_pending = 0; + mutex_unlock(&drm->hpd_lock); - drm_helper_hpd_irq_event(drm->dev); + /* Nothing to do, exit early without updating the last busy counter */ + if (!pending) + goto noop; + + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + + nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { + enum drm_connector_status old_status = connector->status; + u64 old_epoch_counter = connector->epoch_counter; + + if (!(pending & drm_connector_mask(connector))) + continue; + + connector->status = drm_helper_probe_detect(connector, NULL, + false); + if (old_epoch_counter == connector->epoch_counter) + continue; + + changed = true; + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n", + connector->base.id, connector->name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status), + old_epoch_counter, connector->epoch_counter); + } + + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); pm_runtime_mark_last_busy(drm->dev->dev); +noop: pm_runtime_put_sync(drm->dev->dev); } @@ -490,12 +544,11 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, */ pm_runtime_put_autosuspend(drm->dev->dev); } else if (ret == 0) { - /* This may be the only indication we receive - * of a connector hotplug on a runtime - * suspended GPU, schedule hpd_work to check. + /* We've started resuming the GPU already, so + * it will handle scheduling a full reprobe + * itself */ NV_DEBUG(drm, "ACPI requested connector reprobe\n"); - schedule_work(&drm->hpd_work); pm_runtime_put_noidle(drm->dev->dev); } else { NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n", @@ -686,6 +739,7 @@ nouveau_display_create(struct drm_device *dev) } INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work); + mutex_init(&drm->hpd_lock); #ifdef CONFIG_ACPI drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy; register_acpi_notifier(&drm->acpi_nb); @@ -705,9 +759,10 @@ void nouveau_display_destroy(struct drm_device *dev) { struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_drm *drm = nouveau_drm(dev); #ifdef CONFIG_ACPI - unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb); + unregister_acpi_notifier(&drm->acpi_nb); #endif drm_kms_helper_poll_fini(dev); @@ -719,6 +774,7 @@ nouveau_display_destroy(struct drm_device *dev) nvif_disp_dtor(&disp->disp); nouveau_drm(dev)->display = NULL; + mutex_destroy(&drm->hpd_lock); kfree(disp); } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 76ba93e01aff4..616c434270594 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -45,6 +45,7 @@ nouveau_display(struct drm_device *dev) int nouveau_display_create(struct drm_device *dev); void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev, bool resume, bool runtime); +void nouveau_display_hpd_resume(struct drm_device *dev); void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index a5934064a75ea..005750aeb6d4f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -165,7 +165,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - schedule_work(&drm->hpd_work); + nouveau_connector_hpd(connector); } else { drm_dp_cec_irq(&nv_connector->aux); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 22d246acc5e52..42fc5c813a9bb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -953,7 +953,7 @@ nouveau_pmops_resume(struct device *dev) ret = nouveau_do_resume(drm_dev, false); /* Monitors may have been connected / disconnected during suspend */ - schedule_work(&nouveau_drm(drm_dev)->hpd_work); + nouveau_display_hpd_resume(drm_dev); return ret; } @@ -1036,7 +1036,7 @@ nouveau_pmops_runtime_resume(struct device *dev) drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; /* Monitors may have been connected / disconnected during suspend */ - schedule_work(&nouveau_drm(drm_dev)->hpd_work); + nouveau_display_hpd_resume(drm_dev); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index f63ac72aa556f..73ebf5fba2fcd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -198,6 +198,8 @@ struct nouveau_drm { struct nvbios vbios; struct nouveau_display *display; struct work_struct hpd_work; + struct mutex hpd_lock; + u32 hpd_pending; struct work_struct fbcon_work; int fbcon_new_state; #ifdef CONFIG_ACPI -- GitLab From 3d3721ccb18a3dcec874c44120e2df7ec1c1db99 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:49 -0400 Subject: [PATCH 0694/1494] drm/i915/dp: Extract drm_dp_read_downstream_info() We're going to be doing the same probing process in nouveau for determining downstream DP port capabilities, so let's deduplicate the work by moving i915's code for handling this into a shared helper: drm_dp_read_downstream_info(). Note that when we do this, we also do make some functional changes while we're at it: * We always clear the downstream port info before trying to read it, just to make things easier for the caller * We skip reading downstream port info if the DPCD indicates that we don't support downstream port info * We only read as many bytes as needed for the reported number of downstream ports, no sense in reading the whole thing every time v2: * Fixup logic for calculating the downstream port length to account for the fact that downstream port caps can be either 1 byte or 4 bytes long. We can actually skip fixing the max_clock/max_bpc helpers here since they all check for DP_DETAILED_CAP_INFO_AVAILABLE anyway. * Fix ret code check for drm_dp_dpcd_read v5: * Change name from drm_dp_downstream_read_info() to drm_dp_read_downstream_info() * Also, add "See Also" sections for the various downstream info functions (drm_dp_read_downstream_info(), drm_dp_downstream_max_clock(), drm_dp_downstream_max_bpc()) Reviewed-by: Sean Paul <sean@poorly.run> Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-14-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 62 ++++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_dp.c | 14 +----- include/drm/drm_dp_helper.h | 3 ++ 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 4c21cf69dad5a..f3643894ad951 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -423,6 +423,56 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_send_real_edid_checksum); +static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 port_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_PORT_COUNT_MASK; + + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE && port_count > 4) + port_count = 4; + + return port_count; +} + +/** + * drm_dp_read_downstream_info() - read DPCD downstream port info if available + * @aux: DisplayPort AUX channel + * @dpcd: A cached copy of the port's DPCD + * @downstream_ports: buffer to store the downstream port info in + * + * See also: + * drm_dp_downstream_max_clock() + * drm_dp_downstream_max_bpc() + * + * Returns: 0 if either the downstream port info was read successfully or + * there was no downstream info to read, or a negative error code otherwise. + */ +int drm_dp_read_downstream_info(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]) +{ + int ret; + u8 len; + + memset(downstream_ports, 0, DP_MAX_DOWNSTREAM_PORTS); + + /* No downstream info to read */ + if (!drm_dp_is_branch(dpcd) || + dpcd[DP_DPCD_REV] < DP_DPCD_REV_10 || + !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) + return 0; + + len = drm_dp_downstream_port_count(dpcd); + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) + len *= 4; + + ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len); + if (ret < 0) + return ret; + + return ret == len ? 0 : -EIO; +} +EXPORT_SYMBOL(drm_dp_read_downstream_info); + /** * drm_dp_downstream_max_clock() - extract branch device max * pixel rate for legacy VGA @@ -431,7 +481,11 @@ EXPORT_SYMBOL(drm_dp_send_real_edid_checksum); * @dpcd: DisplayPort configuration data * @port_cap: port capabilities * - * Returns max clock in kHz on success or 0 if max clock not defined + * See also: + * drm_dp_read_downstream_info() + * drm_dp_downstream_max_bpc() + * + * Returns: Max clock in kHz on success or 0 if max clock not defined */ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]) @@ -462,7 +516,11 @@ EXPORT_SYMBOL(drm_dp_downstream_max_clock); * @dpcd: DisplayPort configuration data * @port_cap: port capabilities * - * Returns max bpc on success or 0 if max bpc not defined + * See also: + * drm_dp_read_downstream_info() + * drm_dp_downstream_max_clock() + * + * Returns: Max bpc on success or 0 if max bpc not defined */ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4c7314b7a84e4..9c4b806af8c79 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4685,18 +4685,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return false; } - if (!drm_dp_is_branch(intel_dp->dpcd)) - return true; /* native DP sink */ - - if (intel_dp->dpcd[DP_DPCD_REV] == 0x10) - return true; /* no per-port downstream info */ - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_DOWNSTREAM_PORT_0, - intel_dp->downstream_ports, - DP_MAX_DOWNSTREAM_PORTS) < 0) - return false; /* downstream port status fetch failed */ - - return true; + return drm_dp_read_downstream_info(&intel_dp->aux, intel_dp->dpcd, + intel_dp->downstream_ports) == 0; } static bool diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5c28199248626..b8716b200666f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1613,6 +1613,9 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, u8 real_edid_checksum); +int drm_dp_read_downstream_info(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], -- GitLab From 409d38139b42f2c3d3e6012a060c498fbb5067fc Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:50 -0400 Subject: [PATCH 0695/1494] drm/nouveau/kms/nv50-: Use downstream DP clock limits for mode validation This adds support for querying the maximum clock rate of a downstream port on a DisplayPort connection. Generally, downstream ports refer to active dongles which can have their own pixel clock limits. Note as well, we also start marking the connector as disconnected if we can't read the DPCD, since we wouldn't be able to do anything without DPCD access anyway. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-15-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 3 +++ drivers/gpu/drm/nouveau/nouveau_dp.c | 15 +++++++++++---- drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 8e1effb10425d..d2141ca16107b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1258,7 +1258,10 @@ nv50_mstc_detect(struct drm_connector *connector, ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr, mstc->port); + if (ret != connector_status_connected) + goto out; +out: pm_runtime_mark_last_busy(connector->dev->dev); pm_runtime_put_autosuspend(connector->dev->dev); return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 005750aeb6d4f..ad852e572cfec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -61,6 +61,11 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } + ret = drm_dp_read_downstream_info(aux, dpcd, + outp->dp.downstream_ports); + if (ret < 0) + return connector_status_disconnected; + return connector_status_connected; } @@ -176,8 +181,6 @@ void nouveau_dp_irq(struct nouveau_drm *drm, /* TODO: * - Use the minimum possible BPC here, once we add support for the max bpc * property. - * - Validate the mode against downstream port caps (see - * drm_dp_downstream_max_clock()) * - Validate against the DP caps advertised by the GPU (we don't check these * yet) */ @@ -188,15 +191,19 @@ nv50_dp_mode_valid(struct drm_connector *connector, unsigned *out_clock) { const unsigned min_clock = 25000; - unsigned max_clock, clock; + unsigned max_clock, ds_clock, clock; enum drm_mode_status ret; if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) return MODE_NO_INTERLACE; max_clock = outp->dp.link_nr * outp->dp.link_bw; - clock = mode->clock * (connector->display_info.bpc * 3) / 10; + ds_clock = drm_dp_downstream_max_clock(outp->dp.dpcd, + outp->dp.downstream_ports); + if (ds_clock) + max_clock = min(max_clock, ds_clock); + clock = mode->clock * (connector->display_info.bpc * 3) / 10; ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock, &clock); if (out_clock) diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index eef4643f5f982..c1924a4529a7b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -72,6 +72,7 @@ struct nouveau_encoder { struct mutex hpd_irq_lock; u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct drm_dp_desc desc; } dp; }; -- GitLab From 693c3ec5976eb4b66cbd4f3f1c701a6f0ae1c9b9 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:51 -0400 Subject: [PATCH 0696/1494] drm/i915/dp: Extract drm_dp_read_sink_count_cap() Since other drivers are also going to need to be aware of the sink count in order to do proper dongle detection, we might as well steal i915's DP_SINK_COUNT helpers and move them into DRM helpers so that other dirvers can use them as well. Note that this also starts using intel_dp_has_sink_count() in intel_dp_detect_dpcd(), which is a functional change. v5: * Change name from drm_dp_has_sink_count() to drm_dp_read_sink_count_cap() Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-16-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 21 ++++++++++++--------- include/drm/drm_dp_helper.h | 8 +++++++- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f3643894ad951..65ff21ae0c271 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -726,6 +726,28 @@ void drm_dp_set_subconnector_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_dp_set_subconnector_property); +/** + * drm_dp_read_sink_count_cap() - Check whether a given connector has a valid sink + * count + * @connector: The DRM connector to check + * @dpcd: A cached copy of the connector's DPCD RX capabilities + * @desc: A cached copy of the connector's DP descriptor + * + * Returns: %True if the (e)DP connector has a valid sink count that should + * be probed, %false otherwise. + */ +bool drm_dp_read_sink_count_cap(struct drm_connector *connector, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const struct drm_dp_desc *desc) +{ + /* Some eDP panels don't set a valid value for the sink count */ + return connector->connector_type != DRM_MODE_CONNECTOR_eDP && + dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 && + dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT && + !drm_dp_has_quirk(desc, 0, DP_DPCD_QUIRK_NO_SINK_COUNT); +} +EXPORT_SYMBOL(drm_dp_read_sink_count_cap); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9c4b806af8c79..38318ae935f88 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4634,6 +4634,16 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) return true; } +static bool +intel_dp_has_sink_count(struct intel_dp *intel_dp) +{ + if (!intel_dp->attached_connector) + return false; + + return drm_dp_read_sink_count_cap(&intel_dp->attached_connector->base, + intel_dp->dpcd, + &intel_dp->desc); +} static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) @@ -4653,13 +4663,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) intel_dp_set_common_rates(intel_dp); } - /* - * Some eDP panels do not set a valid value for sink count, that is why - * it don't care about read it here and in intel_edp_init_dpcd(). - */ - if (!intel_dp_is_edp(intel_dp) && - !drm_dp_has_quirk(&intel_dp->desc, 0, - DP_DPCD_QUIRK_NO_SINK_COUNT)) { + if (intel_dp_has_sink_count(intel_dp)) { u8 count; ssize_t r; @@ -5939,9 +5943,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* If we're HPD-aware, SINK_COUNT changes dynamically */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + if (intel_dp_has_sink_count(intel_dp) && intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) { - return intel_dp->sink_count ? connector_status_connected : connector_status_disconnected; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b8716b200666f..4c56ce4dc54fc 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1631,6 +1631,11 @@ void drm_dp_set_subconnector_property(struct drm_connector *connector, const u8 *dpcd, const u8 port_cap[4]); +struct drm_dp_desc; +bool drm_dp_read_sink_count_cap(struct drm_connector *connector, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const struct drm_dp_desc *desc); + void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); @@ -1689,7 +1694,8 @@ enum drm_dp_quirk { * @DP_DPCD_QUIRK_NO_SINK_COUNT: * * The device does not set SINK_COUNT to a non-zero value. - * The driver should ignore SINK_COUNT during detection. + * The driver should ignore SINK_COUNT during detection. Note that + * drm_dp_read_sink_count_cap() automatically checks for this quirk. */ DP_DPCD_QUIRK_NO_SINK_COUNT, /** -- GitLab From 4778ff052812029bc076f5e78eff3ba1851cbea7 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:52 -0400 Subject: [PATCH 0697/1494] drm/i915/dp: Extract drm_dp_read_sink_count() And of course, we'll also need to read the sink count from other drivers as well if we're checking whether or not it's supported. So, let's extract the code for this into another helper. v2: * Fix drm_dp_dpcd_readb() ret check * Add back comment and move back sink_count assignment in intel_dp_get_dpcd() v5: * Change name from drm_dp_get_sink_count() to drm_dp_read_sink_count() * Also, add "See also:" section to kdocs Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-17-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 26 +++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++------ include/drm/drm_dp_helper.h | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 65ff21ae0c271..46d88ef4f59ac 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -733,6 +733,8 @@ EXPORT_SYMBOL(drm_dp_set_subconnector_property); * @dpcd: A cached copy of the connector's DPCD RX capabilities * @desc: A cached copy of the connector's DP descriptor * + * See also: drm_dp_read_sink_count() + * * Returns: %True if the (e)DP connector has a valid sink count that should * be probed, %false otherwise. */ @@ -748,6 +750,30 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector, } EXPORT_SYMBOL(drm_dp_read_sink_count_cap); +/** + * drm_dp_read_sink_count() - Retrieve the sink count for a given sink + * @aux: The DP AUX channel to use + * + * See also: drm_dp_read_sink_count_cap() + * + * Returns: The current sink count reported by @aux, or a negative error code + * otherwise. + */ +int drm_dp_read_sink_count(struct drm_dp_aux *aux) +{ + u8 count; + int ret; + + ret = drm_dp_dpcd_readb(aux, DP_SINK_COUNT, &count); + if (ret < 0) + return ret; + if (ret != 1) + return -EIO; + + return DP_GET_SINK_COUNT(count); +} +EXPORT_SYMBOL(drm_dp_read_sink_count); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 38318ae935f88..0de94fc6289be 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4648,6 +4648,8 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp) static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) { + int ret; + if (!intel_dp_read_dpcd(intel_dp)) return false; @@ -4664,11 +4666,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } if (intel_dp_has_sink_count(intel_dp)) { - u8 count; - ssize_t r; - - r = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_COUNT, &count); - if (r < 1) + ret = drm_dp_read_sink_count(&intel_dp->aux); + if (ret < 0) return false; /* @@ -4676,7 +4675,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) * a member variable in intel_dp will track any changes * between short pulse interrupts. */ - intel_dp->sink_count = DP_GET_SINK_COUNT(count); + intel_dp->sink_count = ret; /* * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 4c56ce4dc54fc..bc5cb8c503fbc 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1635,6 +1635,7 @@ struct drm_dp_desc; bool drm_dp_read_sink_count_cap(struct drm_connector *connector, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const struct drm_dp_desc *desc); +int drm_dp_read_sink_count(struct drm_dp_aux *aux); void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); -- GitLab From a4efad354cf1b9d5275adc85f67fcaaa1c2912d8 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:53 -0400 Subject: [PATCH 0698/1494] drm/nouveau/kms/nv50-: Add support for DP_SINK_COUNT This is another bit that we never implemented for nouveau: dongle detection. When a "dongle", e.g. an active display adaptor, is hooked up to the system and causes an HPD to be fired, we don't actually know whether or not there's anything plugged into the dongle without checking the sink count. As a result, plugging in a dongle without anything plugged into it currently results in a bogus EDID retrieval error in the kernel log. Additionally, most dongles won't send another long HPD signal if the user suddenly plugs something in, they'll only send a short HPD IRQ with the expectation that the source will check the sink count and reprobe the connector if it's changed - something we don't actually do. As a result, nothing will happen if the user plugs the dongle in before plugging something into the dongle. So, let's fix this by checking the sink count in both nouveau_dp_probe_dpcd() and nouveau_dp_irq(), and reprobing the connector if things change. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-18-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 53 ++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_encoder.h | 2 + 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index ad852e572cfec..59be357b17e00 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,12 +36,21 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); +static bool +nouveau_dp_has_sink_count(struct drm_connector *connector, + struct nouveau_encoder *outp) +{ + return drm_dp_read_sink_count_cap(connector, outp->dp.dpcd, &outp->dp.desc); +} + static enum drm_connector_status nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, struct nouveau_encoder *outp) { + struct drm_connector *connector = &nv_connector->base; struct drm_dp_aux *aux = &nv_connector->aux; struct nv50_mstm *mstm = NULL; + enum drm_connector_status status = connector_status_disconnected; int ret; u8 *dpcd = outp->dp.dpcd; @@ -50,9 +59,9 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd)); if (ret < 0) - return connector_status_disconnected; + goto out; } else { - return connector_status_disconnected; + goto out; } if (nouveau_mst) { @@ -61,12 +70,33 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } + if (nouveau_dp_has_sink_count(connector, outp)) { + ret = drm_dp_read_sink_count(aux); + if (ret < 0) + goto out; + + outp->dp.sink_count = ret; + + /* + * Dongle connected, but no display. Don't bother reading + * downstream port info + */ + if (!outp->dp.sink_count) + return connector_status_disconnected; + } + ret = drm_dp_read_downstream_info(aux, dpcd, outp->dp.downstream_ports); if (ret < 0) - return connector_status_disconnected; + goto out; - return connector_status_connected; + status = connector_status_connected; +out: + if (status != connector_status_connected) { + /* Clear any cached info */ + outp->dp.sink_count = 0; + } + return status; } int @@ -159,6 +189,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm, struct drm_connector *connector = &nv_connector->base; struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); struct nv50_mstm *mstm; + int ret; + bool send_hpd = false; if (!outp) return; @@ -170,12 +202,23 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - nouveau_connector_hpd(connector); + send_hpd = true; } else { drm_dp_cec_irq(&nv_connector->aux); + + if (nouveau_dp_has_sink_count(connector, outp)) { + ret = drm_dp_read_sink_count(&nv_connector->aux); + if (ret != outp->dp.sink_count) + send_hpd = true; + if (ret >= 0) + outp->dp.sink_count = ret; + } } mutex_unlock(&outp->dp.hpd_irq_lock); + + if (send_hpd) + nouveau_connector_hpd(connector); } /* TODO: diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index c1924a4529a7b..21937f1c7dd90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -74,6 +74,8 @@ struct nouveau_encoder { u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct drm_dp_desc desc; + + u8 sink_count; } dp; }; -- GitLab From f28e32d3906eac2e1cb3291b448f0d528ec93996 Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:54 -0400 Subject: [PATCH 0699/1494] drm/nouveau/kms: Don't change EDID when it hasn't actually changed Currently in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds(), we start the connector probing process by releasing the previous EDID and informing DRM of the change. However, since commit 5186421cbfe2 ("drm: Introduce epoch counter to drm_connector") drm_connector_update_edid_property() actually checks whether the new EDID we've specified is different from the previous one, and updates the connector's epoch accordingly if it is. But, because we always set the EDID to NULL first in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds() we end up making DRM think that the EDID changes every single time we do a connector probe - which isn't needed. So, let's fix this by not clearing the EDID at the start of the connector probing process, and instead simply changing or removing it once near the end of the probing process. This will help prevent us from sending unneeded hotplug events to userspace when nothing has actually changed. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-19-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 54 ++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 637e91594fbe8..49dd0cbc332ff 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -528,6 +528,17 @@ nouveau_connector_set_encoder(struct drm_connector *connector, } } +static void +nouveau_connector_set_edid(struct nouveau_connector *nv_connector, + struct edid *edid) +{ + struct edid *old_edid = nv_connector->edid; + + drm_connector_update_edid_property(&nv_connector->base, edid); + kfree(old_edid); + nv_connector->edid = edid; +} + static enum drm_connector_status nouveau_connector_detect(struct drm_connector *connector, bool force) { @@ -541,13 +552,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) int ret; enum drm_connector_status conn_status = connector_status_disconnected; - /* Cleanup the previous EDID block. */ - if (nv_connector->edid) { - drm_connector_update_edid_property(connector, NULL); - kfree(nv_connector->edid); - nv_connector->edid = NULL; - } - /* Outputs are only polled while runtime active, so resuming the * device here is unnecessary (and would deadlock upon runtime suspend * because it waits for polling to finish). We do however, want to @@ -560,22 +564,23 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ret = pm_runtime_get_sync(dev->dev); if (ret < 0 && ret != -EACCES) { pm_runtime_put_autosuspend(dev->dev); + nouveau_connector_set_edid(nv_connector, NULL); return conn_status; } } nv_encoder = nouveau_connector_ddc_detect(connector); if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { + struct edid *new_edid; + if ((vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) && nv_connector->type == DCB_CONNECTOR_LVDS) - nv_connector->edid = drm_get_edid_switcheroo(connector, - i2c); + new_edid = drm_get_edid_switcheroo(connector, i2c); else - nv_connector->edid = drm_get_edid(connector, i2c); + new_edid = drm_get_edid(connector, i2c); - drm_connector_update_edid_property(connector, - nv_connector->edid); + nouveau_connector_set_edid(nv_connector, new_edid); if (!nv_connector->edid) { NV_ERROR(drm, "DDC responded, but no EDID for %s\n", connector->name); @@ -609,6 +614,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) conn_status = connector_status_connected; drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid); goto out; + } else { + nouveau_connector_set_edid(nv_connector, NULL); } nv_encoder = nouveau_connector_of_detect(connector); @@ -652,18 +659,12 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; + struct edid *edid = NULL; enum drm_connector_status status = connector_status_disconnected; - /* Cleanup the previous EDID block. */ - if (nv_connector->edid) { - drm_connector_update_edid_property(connector, NULL); - kfree(nv_connector->edid); - nv_connector->edid = NULL; - } - nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) - return connector_status_disconnected; + goto out; /* Try retrieving EDID via DDC */ if (!drm->vbios.fp_no_ddc) { @@ -682,7 +683,8 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * valid - it's not (rh#613284) */ if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { + edid = nouveau_acpi_edid(dev, connector); + if (edid) { status = connector_status_connected; goto out; } @@ -702,12 +704,10 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * stored for the panel stored in them. */ if (!drm->vbios.fp_no_ddc) { - struct edid *edid = - (struct edid *)nouveau_bios_embedded_edid(dev); + edid = (struct edid *)nouveau_bios_embedded_edid(dev); if (edid) { - nv_connector->edid = - kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - if (nv_connector->edid) + edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + if (edid) status = connector_status_connected; } } @@ -720,7 +720,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) status = connector_status_unknown; #endif - drm_connector_update_edid_property(connector, nv_connector->edid); + nouveau_connector_set_edid(nv_connector, edid); nouveau_connector_set_encoder(connector, nv_encoder); return status; } -- GitLab From b9936121d95b0127d34fa6c25678994582d1b17c Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:55 -0400 Subject: [PATCH 0700/1494] drm/i915/dp: Extract drm_dp_read_dpcd_caps() Since DP 1.3, it's been possible for DP receivers to specify an additional set of DPCD capabilities, which can take precedence over the capabilities reported at DP_DPCD_REV. Basically any device supporting DP is going to need to read these in an identical manner, in particular nouveau, so let's go ahead and just move this code out of i915 into a shared DRM DP helper that we can use in other drivers. v2: * Remove redundant dpcd[DP_DPCD_REV] == 0 check * Fix drm_dp_dpcd_read() ret checks Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-20-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 60 +--------------- drivers/gpu/drm/i915/display/intel_dp.h | 1 - drivers/gpu/drm/i915/display/intel_lspcon.c | 2 +- include/drm/drm_dp_helper.h | 3 + 5 files changed, 83 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 46d88ef4f59ac..9ca88e6c78820 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -433,6 +433,83 @@ static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) return port_count; } +static int drm_dp_read_extended_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 dpcd_ext[6]; + int ret; + + /* + * Prior to DP1.3 the bit represented by + * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. + * If it is set DP_DPCD_REV at 0000h could be at a value less than + * the true capability of the panel. The only way to check is to + * then compare 0000h and 2200h. + */ + if (!(dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) + return 0; + + ret = drm_dp_dpcd_read(aux, DP_DP13_DPCD_REV, &dpcd_ext, + sizeof(dpcd_ext)); + if (ret < 0) + return ret; + if (ret != sizeof(dpcd_ext)) + return -EIO; + + if (dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { + DRM_DEBUG_KMS("%s: Extended DPCD rev less than base DPCD rev (%d > %d)\n", + aux->name, dpcd[DP_DPCD_REV], + dpcd_ext[DP_DPCD_REV]); + return 0; + } + + if (!memcmp(dpcd, dpcd_ext, sizeof(dpcd_ext))) + return 0; + + DRM_DEBUG_KMS("%s: Base DPCD: %*ph\n", + aux->name, DP_RECEIVER_CAP_SIZE, dpcd); + + memcpy(dpcd, dpcd_ext, sizeof(dpcd_ext)); + + return 0; +} + +/** + * drm_dp_read_dpcd_caps() - read DPCD caps and extended DPCD caps if + * available + * @aux: DisplayPort AUX channel + * @dpcd: Buffer to store the resulting DPCD in + * + * Attempts to read the base DPCD caps for @aux. Additionally, this function + * checks for and reads the extended DPRX caps (%DP_DP13_DPCD_REV) if + * present. + * + * Returns: %0 if the DPCD was read successfully, negative error code + * otherwise. + */ +int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + int ret; + + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret < 0) + return ret; + if (ret != DP_RECEIVER_CAP_SIZE || dpcd[DP_DPCD_REV] == 0) + return -EIO; + + ret = drm_dp_read_extended_dpcd_caps(aux, dpcd); + if (ret < 0) + return ret; + + DRM_DEBUG_KMS("%s: DPCD: %*ph\n", + aux->name, DP_RECEIVER_CAP_SIZE, dpcd); + + return ret; +} +EXPORT_SYMBOL(drm_dp_read_dpcd_caps); + /** * drm_dp_read_downstream_info() - read DPCD downstream port info if available * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0de94fc6289be..284b15f845926 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4449,62 +4449,6 @@ intel_dp_link_down(struct intel_encoder *encoder, } } -static void -intel_dp_extended_receiver_capabilities(struct intel_dp *intel_dp) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - u8 dpcd_ext[6]; - - /* - * Prior to DP1.3 the bit represented by - * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. - * if it is set DP_DPCD_REV at 0000h could be at a value less than - * the true capability of the panel. The only way to check is to - * then compare 0000h and 2200h. - */ - if (!(intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] & - DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) - return; - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_DP13_DPCD_REV, - &dpcd_ext, sizeof(dpcd_ext)) != sizeof(dpcd_ext)) { - drm_err(&i915->drm, - "DPCD failed read at extended capabilities\n"); - return; - } - - if (intel_dp->dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { - drm_dbg_kms(&i915->drm, - "DPCD extended DPCD rev less than base DPCD rev\n"); - return; - } - - if (!memcmp(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext))) - return; - - drm_dbg_kms(&i915->drm, "Base DPCD: %*ph\n", - (int)sizeof(intel_dp->dpcd), intel_dp->dpcd); - - memcpy(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext)); -} - -bool -intel_dp_read_dpcd(struct intel_dp *intel_dp) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - - if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd, - sizeof(intel_dp->dpcd)) < 0) - return false; /* aux transfer failed */ - - intel_dp_extended_receiver_capabilities(intel_dp); - - drm_dbg_kms(&i915->drm, "DPCD: %*ph\n", (int)sizeof(intel_dp->dpcd), - intel_dp->dpcd); - - return intel_dp->dpcd[DP_DPCD_REV] != 0; -} - bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp) { u8 dprx = 0; @@ -4563,7 +4507,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) /* this function is meant to be called only once */ drm_WARN_ON(&dev_priv->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); - if (!intel_dp_read_dpcd(intel_dp)) + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) return false; drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, @@ -4650,7 +4594,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) { int ret; - if (!intel_dp_read_dpcd(intel_dp)) + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) return false; /* diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index b901ab850cbd9..0a3af3410d52e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -99,7 +99,6 @@ bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); bool intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status); -bool intel_dp_read_dpcd(struct intel_dp *intel_dp); bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp); int intel_dp_link_required(int pixel_clock, int bpp); int intel_dp_max_data_rate(int max_link_clock, int max_lanes); diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index b781bf4696443..dc1b35559afdf 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -571,7 +571,7 @@ bool lspcon_init(struct intel_digital_port *dig_port) return false; } - if (!intel_dp_read_dpcd(dp)) { + if (drm_dp_read_dpcd_caps(&dp->aux, dp->dpcd) != 0) { DRM_ERROR("LSPCON DPCD read failed\n"); return false; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index bc5cb8c503fbc..85513eeb21966 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1607,6 +1607,9 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, return drm_dp_dpcd_write(aux, offset, &value, 1); } +int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]); + int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, u8 status[DP_LINK_STATUS_SIZE]); -- GitLab From 79416e97dda0118b137302575a70a14259a27d7d Mon Sep 17 00:00:00 2001 From: Lyude Paul <lyude@redhat.com> Date: Wed, 26 Aug 2020 14:24:56 -0400 Subject: [PATCH 0701/1494] drm/nouveau/kms: Start using drm_dp_read_dpcd_caps() Now that we've extracted i915's code for reading both the normal DPCD caps and extended DPCD caps into a shared helper, let's start using this in nouveau to enable us to start checking extended DPCD caps for free. Signed-off-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-21-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 59be357b17e00..810bf69565683 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -54,15 +54,13 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, int ret; u8 *dpcd = outp->dp.dpcd; - ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); - if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { - ret = drm_dp_read_desc(aux, &outp->dp.desc, - drm_dp_is_branch(dpcd)); - if (ret < 0) - goto out; - } else { + ret = drm_dp_read_dpcd_caps(aux, dpcd); + if (ret < 0) + goto out; + + ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd)); + if (ret < 0) goto out; - } if (nouveau_mst) { mstm = outp->dp.mstm; -- GitLab From 1f0882214fd0037b74f245d9be75c31516fed040 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:49 -0400 Subject: [PATCH 0702/1494] drm/i915: Fix sha_text population code This patch fixes a few bugs: 1- We weren't taking into account sha_leftovers when adding multiple ksvs to sha_text. As such, we were or'ing the end of ksv[j - 1] with the beginning of ksv[j] 2- In the sha_leftovers == 2 and sha_leftovers == 3 case, bstatus was being placed on the wrong half of sha_text, overlapping the leftover ksv value 3- In the sha_leftovers == 2 case, we need to manually terminate the byte stream with 0x80 since the hardware doesn't have enough room to add it after writing M0 The upside is that all of the HDCP supported HDMI repeaters I could find on Amazon just strip HDCP anyways, so it turns out to be _really_ hard to hit any of these cases without an MST hub, which is not (yet) supported. Oh, and the sha_leftovers == 1 case works perfectly! Fixes: ee5e5e7a5e0f ("drm/i915: Add HDCP framework + base implementation") Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ramalingam C <ramalingam.c@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <seanpaul@chromium.org> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v4.17+ Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-2-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-2-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-2-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-2-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-2-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-2-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-2-sean@poorly.run #v7 Changes in v2: -None Changes in v3: -None Changes in v4: -Rebased on intel_de_write changes Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-2-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_hdcp.c | 26 +++++++++++++++++------ include/drm/drm_hdcp.h | 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index e76b049618dbd..63e0a1e9ac715 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -327,8 +327,10 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Fill up the empty slots in sha_text and write it out */ sha_empty = sizeof(sha_text) - sha_leftovers; - for (j = 0; j < sha_empty; j++) - sha_text |= ksv[j] << ((sizeof(sha_text) - j - 1) * 8); + for (j = 0; j < sha_empty; j++) { + u8 off = ((sizeof(sha_text) - j - 1 - sha_leftovers) * 8); + sha_text |= ksv[j] << off; + } ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) @@ -426,7 +428,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Write 32 bits of text */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24 | bstatus[1] << 16; + sha_text |= bstatus[0] << 8 | bstatus[1]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; @@ -441,17 +443,29 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, return ret; sha_idx += sizeof(sha_text); } + + /* + * Terminate the SHA-1 stream by hand. For the other leftover + * cases this is appended by the hardware. + */ + intel_de_write(dev_priv, HDCP_REP_CTL, + rep_ctl | HDCP_SHA1_TEXT_32); + sha_text = DRM_HDCP_SHA1_TERMINATOR << 24; + ret = intel_write_sha_text(dev_priv, sha_text); + if (ret < 0) + return ret; + sha_idx += sizeof(sha_text); } else if (sha_leftovers == 3) { - /* Write 32 bits of text */ + /* Write 32 bits of text (filled from LSB) */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24; + sha_text |= bstatus[0]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; sha_idx += sizeof(sha_text); - /* Write 8 bits of text, 24 bits of M0 */ + /* Write 8 bits of text (filled from LSB), 24 bits of M0 */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_8); ret = intel_write_sha_text(dev_priv, bstatus[1]); diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index c6bab4986a658..fe58dbb46962a 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -29,6 +29,9 @@ /* Slave address for the HDCP registers in the receiver */ #define DRM_HDCP_DDC_ADDR 0x3A +/* Value to use at the end of the SHA-1 bytestream used for repeaters */ +#define DRM_HDCP_SHA1_TERMINATOR 0x80 + /* HDCP register offsets for HDMI/DVI devices */ #define DRM_HDCP_DDC_BKSV 0x00 #define DRM_HDCP_DDC_RI_PRIME 0x08 -- GitLab From 2cc0c7b520bf8ea20ec42285d4e3d37b467eb7f9 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:50 -0400 Subject: [PATCH 0703/1494] drm/i915: Clear the repeater bit on HDCP disable On HDCP disable, clear the repeater bit. This ensures if we connect a non-repeater sink after a repeater, the bit is in the state we expect. Fixes: ee5e5e7a5e0f ("drm/i915: Add HDCP framework + base implementation") Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ramalingam C <ramalingam.c@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Sean Paul <seanpaul@chromium.org> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v4.17+ Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-3-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-3-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-3-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-3-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-3-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-3-sean@poorly.run #v7 Changes in v2: -Added to the set Changes in v3: -None I had previously agreed that clearing the rep_ctl bits on enable would also be a good idea. However when I committed that idea to code, it didn't look right. So let's rely on enables and disables being paired and everything outside of that will be considered a bug Changes in v4: -s/I915_(READ|WRITE)/intel_de_(read|write)/ Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-3-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_hdcp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 63e0a1e9ac715..245202567aa59 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -786,6 +786,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector) struct intel_hdcp *hdcp = &connector->hdcp; enum port port = dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; + u32 repeater_ctl; int ret; drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP is being disabled...\n", @@ -801,6 +802,11 @@ static int _intel_hdcp_disable(struct intel_connector *connector) return -ETIMEDOUT; } + repeater_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, + port); + intel_de_write(dev_priv, HDCP_REP_CTL, + intel_de_read(dev_priv, HDCP_REP_CTL) & ~repeater_ctl); + ret = hdcp->shim->toggle_signalling(dig_port, false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling\n"); -- GitLab From 1cfcdbf3be31f78080effcbb1050a254c3132a08 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:51 -0400 Subject: [PATCH 0704/1494] drm/i915: WARN if HDCP signalling is enabled upon disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDCP signalling should not be left on, WARN if it is Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-4-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-4-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-4-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-4-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-4-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-4-sean@poorly.run #v7 Changes in v2: -Added to the set in lieu of just clearing the bit Changes in v3: -None Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None Changes in v7: -Rebased, variable name changed from 'ctl' to 'val' Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-4-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index d6f84bc3b8fdb..531b309c22a4f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1821,6 +1821,8 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); + drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING); + ctl &= ~TRANS_DDI_FUNC_ENABLE; if (IS_GEN_RANGE(dev_priv, 8, 10)) -- GitLab From 58418f0c0f7099afe8f656fe022dbc38c9645e3a Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:52 -0400 Subject: [PATCH 0705/1494] drm/i915: Intercept Aksv writes in the aux hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hand rolling the transfer ourselves in the hdcp hook, inspect aux messages and add the aksv flag in the aux transfer hook. IIRC, this was the original implementation and folks wanted this hack to be isolated to the hdcp code, which makes sense. However in testing an LG monitor on my desk, I noticed it was passing back a DEFER reply. This wasn't handled in our hand-rolled code and HDCP auth was failing as a result. Instead of copy/pasting all of the retry logic and delays from drm dp helpers, let's just use the helpers and hide the aksv select as best as we can. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-3-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-5-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-5-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-5-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-5-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-5-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-5-sean@poorly.run #v7 Changes in v2: -Remove 'generate' in intel_dp_aux_generate_xfer_flags, make arg const (Ville) -Bundle Aksv if statement together (Ville) -Rename 'txbuf' to 'aksv' (Ville) Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-5-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_dp.c | 62 ++++++++++++------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e6caeaf179260..ce0a75f604d9a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1563,6 +1563,20 @@ intel_dp_aux_header(u8 txbuf[HEADER_SIZE], txbuf[3] = msg->size - 1; } +static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) +{ + /* + * If we're trying to send the HDCP Aksv, we need to set a the Aksv + * select bit to inform the hardware to send the Aksv after our header + * since we can't access that data from software. + */ + if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE && + msg->address == DP_AUX_HDCP_AKSV) + return DP_AUX_CH_CTL_AUX_AKSV_SELECT; + + return 0; +} + static ssize_t intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { @@ -1570,6 +1584,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) struct drm_i915_private *i915 = dp_to_i915(intel_dp); u8 txbuf[20], rxbuf[20]; size_t txsize, rxsize; + u32 flags = intel_dp_aux_xfer_flags(msg); int ret; intel_dp_aux_header(txbuf, msg); @@ -1590,7 +1605,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size); ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, - rxbuf, rxsize, 0); + rxbuf, rxsize, flags); if (ret > 0) { msg->reply = rxbuf[0] >> 4; @@ -1613,7 +1628,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) return -E2BIG; ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize, - rxbuf, rxsize, 0); + rxbuf, rxsize, flags); if (ret > 0) { msg->reply = rxbuf[0] >> 4; /* @@ -6416,15 +6431,8 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, u8 *an) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(&dig_port->base.base)); - static const struct drm_dp_aux_msg msg = { - .request = DP_AUX_NATIVE_WRITE, - .address = DP_AUX_HDCP_AKSV, - .size = DRM_HDCP_KSV_LEN, - }; - u8 txbuf[HEADER_SIZE + DRM_HDCP_KSV_LEN] = {}, rxbuf[2], reply = 0; + u8 aksv[DRM_HDCP_KSV_LEN] = {}; ssize_t dpcd_ret; - int ret; /* Output An first, that's easy */ dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, @@ -6437,31 +6445,19 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, } /* - * Since Aksv is Oh-So-Secret, we can't access it in software. So in - * order to get it on the wire, we need to create the AUX header as if - * we were writing the data, and then tickle the hardware to output the - * data once the header is sent out. + * Since Aksv is Oh-So-Secret, we can't access it in software. So we + * send an empty buffer of the correct length through the DP helpers. On + * the other side, in the transfer hook, we'll generate a flag based on + * the destination address which will tickle the hardware to output the + * Aksv on our behalf after the header is sent. */ - intel_dp_aux_header(txbuf, &msg); - - ret = intel_dp_aux_xfer(intel_dp, txbuf, HEADER_SIZE + msg.size, - rxbuf, sizeof(rxbuf), - DP_AUX_CH_CTL_AUX_AKSV_SELECT); - if (ret < 0) { - drm_dbg_kms(&i915->drm, - "Write Aksv over DP/AUX failed (%d)\n", ret); - return ret; - } else if (ret == 0) { - drm_dbg_kms(&i915->drm, "Aksv write over DP/AUX was empty\n"); - return -EIO; - } - - reply = (rxbuf[0] >> 4) & DP_AUX_NATIVE_REPLY_MASK; - if (reply != DP_AUX_NATIVE_REPLY_ACK) { + dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, + aksv, DRM_HDCP_KSV_LEN); + if (dpcd_ret != DRM_HDCP_KSV_LEN) { drm_dbg_kms(&i915->drm, - "Aksv write: no DP_AUX_NATIVE_REPLY_ACK %x\n", - reply); - return -EIO; + "Failed to write Aksv over DP/AUX (%zd)\n", + dpcd_ret); + return dpcd_ret >= 0 ? -EIO : dpcd_ret; } return 0; } -- GitLab From 0b9c9290d1d182c1659610df92f4aa7a397728d7 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:53 -0400 Subject: [PATCH 0706/1494] drm/i915: Use the cpu_transcoder in intel_hdcp to toggle HDCP signalling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using intel_dig_port's encoder pipe to determine which transcoder to toggle signalling on, use the cpu_transcoder field already stored in intel_hdmi. This is particularly important for MST. Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-6-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-6-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-6-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-6-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-6-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-6-sean@poorly.run #v7 Changes in v2: -Added to the set Changes in v3: -s/hdcp/hdmi/ in commit msg (Ram) Changes in v4: -Rebased on intel_de_(read|write) change Changes in v5: -Update hdcp->cpu_transcoder in intel_hdcp_enable so it works with pipe != 0 Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-6-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_ddi.c | 13 +++---------- drivers/gpu/drm/i915/display/intel_ddi.h | 2 ++ .../gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 1 + drivers/gpu/drm/i915/display/intel_hdcp.c | 15 ++++++++------- drivers/gpu/drm/i915/display/intel_hdmi.c | 16 +++++++++++----- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 531b309c22a4f..f186214150e28 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1850,12 +1850,12 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state } int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, + enum transcoder cpu_transcoder, bool enable) { struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); intel_wakeref_t wakeref; - enum pipe pipe = 0; int ret = 0; u32 tmp; @@ -1864,19 +1864,12 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, if (drm_WARN_ON(dev, !wakeref)) return -ENXIO; - if (drm_WARN_ON(dev, - !intel_encoder->get_hw_state(intel_encoder, &pipe))) { - ret = -EIO; - goto out; - } - - tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(pipe)); + tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (enable) tmp |= TRANS_DDI_HDCP_SIGNALLING; else tmp &= ~TRANS_DDI_HDCP_SIGNALLING; - intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(pipe), tmp); -out: + intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), tmp); intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref); return ret; } diff --git a/drivers/gpu/drm/i915/display/intel_ddi.h b/drivers/gpu/drm/i915/display/intel_ddi.h index 077e9dbbe367d..f5fb62fc94004 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.h +++ b/drivers/gpu/drm/i915/display/intel_ddi.h @@ -16,6 +16,7 @@ struct intel_crtc_state; struct intel_dp; struct intel_dpll_hw_state; struct intel_encoder; +enum transcoder; void intel_ddi_fdi_post_disable(struct intel_atomic_state *state, struct intel_encoder *intel_encoder, @@ -43,6 +44,7 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, u32 bxt_signal_levels(struct intel_dp *intel_dp); u32 ddi_signal_levels(struct intel_dp *intel_dp); int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, + enum transcoder cpu_transcoder, bool enable); void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9349b15afff67..d30ec7728a995 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -314,6 +314,7 @@ struct intel_hdcp_shim { /* Enables HDCP signalling on the port */ int (*toggle_signalling)(struct intel_digital_port *dig_port, + enum transcoder cpu_transcoder, bool enable); /* Ensures the link is still protected */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ce0a75f604d9a..c771fa72c2fb5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6616,6 +6616,7 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, static int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *dig_port, + enum transcoder cpu_transcoder, bool enable) { /* Not used for single stream DisplayPort setups */ diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 245202567aa59..321d67f79ebc5 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -704,7 +704,7 @@ static int intel_hdcp_auth(struct intel_connector *connector) intel_de_write(dev_priv, HDCP_REP_CTL, intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, port)); - ret = shim->toggle_signalling(dig_port, true); + ret = shim->toggle_signalling(dig_port, cpu_transcoder, true); if (ret) return ret; @@ -807,7 +807,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector) intel_de_write(dev_priv, HDCP_REP_CTL, intel_de_read(dev_priv, HDCP_REP_CTL) & ~repeater_ctl); - ret = hdcp->shim->toggle_signalling(dig_port, false); + ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder, false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling\n"); return ret; @@ -1591,7 +1591,8 @@ static int hdcp2_enable_encryption(struct intel_connector *connector) intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port)) & LINK_ENCRYPTION_STATUS); if (hdcp->shim->toggle_signalling) { - ret = hdcp->shim->toggle_signalling(dig_port, true); + ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder, + true); if (ret) { drm_err(&dev_priv->drm, "Failed to enable HDCP signalling. %d\n", @@ -1641,7 +1642,8 @@ static int hdcp2_disable_encryption(struct intel_connector *connector) drm_dbg_kms(&dev_priv->drm, "Disable Encryption Timedout"); if (hdcp->shim->toggle_signalling) { - ret = hdcp->shim->toggle_signalling(dig_port, false); + ret = hdcp->shim->toggle_signalling(dig_port, cpu_transcoder, + false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling. %d\n", @@ -2027,11 +2029,10 @@ int intel_hdcp_enable(struct intel_connector *connector, drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); hdcp->content_type = content_type; + hdcp->cpu_transcoder = cpu_transcoder; - if (INTEL_GEN(dev_priv) >= 12) { - hdcp->cpu_transcoder = cpu_transcoder; + if (INTEL_GEN(dev_priv) >= 12) hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder); - } /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index de2ce5632b947..3966fcfb7d3a6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1477,7 +1477,8 @@ int intel_hdmi_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, return ret; } -static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) +static int kbl_repositioning_enc_en_signal(struct intel_connector *connector, + enum transcoder cpu_transcoder) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_digital_port *dig_port = intel_attached_dig_port(connector); @@ -1494,13 +1495,15 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) usleep_range(25, 50); } - ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, false); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, cpu_transcoder, + false); if (ret) { drm_err(&dev_priv->drm, "Disable HDCP signalling failed (%d)\n", ret); return ret; } - ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, true); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, cpu_transcoder, + true); if (ret) { drm_err(&dev_priv->drm, "Enable HDCP signalling failed (%d)\n", ret); @@ -1512,6 +1515,7 @@ static int kbl_repositioning_enc_en_signal(struct intel_connector *connector) static int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, + enum transcoder cpu_transcoder, bool enable) { struct intel_hdmi *hdmi = &dig_port->hdmi; @@ -1522,7 +1526,8 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, if (!enable) usleep_range(6, 60); /* Bspec says >= 6us */ - ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, enable); + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, cpu_transcoder, + enable); if (ret) { drm_err(&dev_priv->drm, "%s HDCP signalling failed (%d)\n", enable ? "Enable" : "Disable", ret); @@ -1534,7 +1539,8 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, * opportunity and enc_en signalling in KABYLAKE. */ if (IS_KABYLAKE(dev_priv) && enable) - return kbl_repositioning_enc_en_signal(connector); + return kbl_repositioning_enc_en_signal(connector, + cpu_transcoder); return 0; } -- GitLab From a72394e4de6d500cc8af104ff50c941dc969fbea Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:54 -0400 Subject: [PATCH 0707/1494] drm/i915: Factor out hdcp->value assignments This is a bit of housecleaning for a future patch. Instead of sprinkling hdcp->value assignments and prop_work scheduling everywhere, introduce a function to do it for us. Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-7-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-7-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-7-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-7-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-7-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-7-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-7-sean@poorly.run #v7 Changes in v2: -None Changes in v3: -None Changes in v4: -Rebased on top of drm_* logging changes Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-7-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_hdcp.c | 67 ++++++++++++++++------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 321d67f79ebc5..b8608602773c9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -867,6 +867,21 @@ static struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp) return container_of(hdcp, struct intel_connector, hdcp); } +static void intel_hdcp_update_value(struct intel_connector *connector, + u64 value, bool update_property) +{ + struct intel_hdcp *hdcp = &connector->hdcp; + + drm_WARN_ON(connector->base.dev, !mutex_is_locked(&hdcp->mutex)); + + if (hdcp->value == value) + return; + + hdcp->value = value; + if (update_property) + schedule_work(&hdcp->prop_work); +} + /* Implements Part 3 of the HDCP authorization procedure */ static int intel_hdcp_check_link(struct intel_connector *connector) { @@ -894,15 +909,16 @@ static int intel_hdcp_check_link(struct intel_connector *connector) connector->base.name, connector->base.base.id, intel_de_read(dev_priv, HDCP_STATUS(dev_priv, cpu_transcoder, port))); ret = -ENXIO; - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } if (hdcp->shim->check_link(dig_port)) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, true); } goto out; } @@ -914,16 +930,18 @@ static int intel_hdcp_check_link(struct intel_connector *connector) ret = _intel_hdcp_disable(connector); if (ret) { drm_err(&dev_priv->drm, "Failed to disable hdcp (%d)\n", ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } ret = _intel_hdcp_enable(connector); if (ret) { drm_err(&dev_priv->drm, "Failed to enable hdcp (%d)\n", ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } @@ -1759,16 +1777,18 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) "HDCP2.2 link stopped the encryption, %x\n", intel_de_read(dev_priv, HDCP2_STATUS(dev_priv, cpu_transcoder, port))); ret = -ENXIO; - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } ret = hdcp->shim->check_2_2_link(dig_port); if (ret == HDCP_LINK_PROTECTED) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, + true); } goto out; } @@ -1781,8 +1801,9 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) "HDCP2.2 Downstream topology change\n"); ret = hdcp2_authenticate_repeater_topology(connector); if (!ret) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, + true); goto out; } drm_dbg_kms(&dev_priv->drm, @@ -1800,8 +1821,8 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) drm_err(&dev_priv->drm, "[%s:%d] Failed to disable hdcp2.2 (%d)\n", connector->base.name, connector->base.base.id, ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, true); goto out; } @@ -1811,8 +1832,9 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) "[%s:%d] Failed to enable hdcp2.2 (%d)\n", connector->base.name, connector->base.base.id, ret); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); goto out; } @@ -2055,8 +2077,9 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!ret) { schedule_delayed_work(&hdcp->check_work, check_link_interval); - hdcp->value = DRM_MODE_CONTENT_PROTECTION_ENABLED; - schedule_work(&hdcp->prop_work); + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_ENABLED, + true); } mutex_unlock(&hdcp->mutex); @@ -2074,7 +2097,9 @@ int intel_hdcp_disable(struct intel_connector *connector) mutex_lock(&hdcp->mutex); if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - hdcp->value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_UNDESIRED, + false); if (hdcp->hdcp2_encrypted) ret = _intel_hdcp2_disable(connector); else if (hdcp->hdcp_encrypted) -- GitLab From a6597faa2d59b0c76633b034a1cceff9a7201d34 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:55 -0400 Subject: [PATCH 0708/1494] drm/i915: Protect workers against disappearing connectors This patch adds some protection against connectors being destroyed before the HDCP workers are finished. For check_work, we do a synchronous cancel after the connector is unregistered which will ensure that it is finished before destruction. In the case of prop_work, we can't do a synchronous wait since it needs to take connection_mutex which could cause deadlock. Instead, we'll take a reference on the connector when scheduling prop_work and give it up once we're done. Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-8-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-8-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-8-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-8-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-8-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-8-sean@poorly.run #v7 Changes in v2: -Added to the set Changes in v3: -Change the WARN_ON condition in intel_hdcp_cleanup to allow for initializing connectors as well Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-8-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_hdcp.c | 44 ++++++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index b8608602773c9..22d42a323ae8e 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -878,8 +878,10 @@ static void intel_hdcp_update_value(struct intel_connector *connector, return; hdcp->value = value; - if (update_property) + if (update_property) { + drm_connector_get(&connector->base); schedule_work(&hdcp->prop_work); + } } /* Implements Part 3 of the HDCP authorization procedure */ @@ -971,6 +973,8 @@ static void intel_hdcp_prop_work(struct work_struct *work) mutex_unlock(&hdcp->mutex); drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex); + + drm_connector_put(&connector->base); } bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port) @@ -1850,6 +1854,9 @@ static void intel_hdcp_check_work(struct work_struct *work) check_work); struct intel_connector *connector = intel_hdcp_to_connector(hdcp); + if (drm_connector_is_unregistered(&connector->base)) + return; + if (!intel_hdcp2_check_link(connector)) schedule_delayed_work(&hdcp->check_work, DRM_HDCP2_CHECK_PERIOD_MS); @@ -2180,12 +2187,39 @@ void intel_hdcp_component_fini(struct drm_i915_private *dev_priv) void intel_hdcp_cleanup(struct intel_connector *connector) { - if (!connector->hdcp.shim) + struct intel_hdcp *hdcp = &connector->hdcp; + + if (!hdcp->shim) return; - mutex_lock(&connector->hdcp.mutex); - kfree(connector->hdcp.port_data.streams); - mutex_unlock(&connector->hdcp.mutex); + /* + * If the connector is registered, it's possible userspace could kick + * off another HDCP enable, which would re-spawn the workers. + */ + drm_WARN_ON(connector->base.dev, + connector->base.registration_state == DRM_CONNECTOR_REGISTERED); + + /* + * Now that the connector is not registered, check_work won't be run, + * but cancel any outstanding instances of it + */ + cancel_delayed_work_sync(&hdcp->check_work); + + /* + * We don't cancel prop_work in the same way as check_work since it + * requires connection_mutex which could be held while calling this + * function. Instead, we rely on the connector references grabbed before + * scheduling prop_work to ensure the connector is alive when prop_work + * is run. So if we're in the destroy path (which is where this + * function should be called), we're "guaranteed" that prop_work is not + * active (tl;dr This Should Never Happen). + */ + drm_WARN_ON(connector->base.dev, work_pending(&hdcp->prop_work)); + + mutex_lock(&hdcp->mutex); + kfree(hdcp->port_data.streams); + hdcp->shim = NULL; + mutex_unlock(&hdcp->mutex); } void intel_hdcp_atomic_check(struct drm_connector *connector, -- GitLab From a1de8685d65c25a48cf24f508e8b39c5cc25c42d Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:56 -0400 Subject: [PATCH 0709/1494] drm/i915: Clean up intel_hdcp_disable Add an out label and un-indent hdcp disable in preparation for hdcp_mutex. No functional changes Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-9-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-9-sean@poorly.run #v7 Changes in v7: -Split into separate patch (Ramalingam) Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-9-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_hdcp.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 22d42a323ae8e..f4939f63d8dd1 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2103,16 +2103,17 @@ int intel_hdcp_disable(struct intel_connector *connector) mutex_lock(&hdcp->mutex); - if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_UNDESIRED, - false); - if (hdcp->hdcp2_encrypted) - ret = _intel_hdcp2_disable(connector); - else if (hdcp->hdcp_encrypted) - ret = _intel_hdcp_disable(connector); - } + if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) + goto out; + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_UNDESIRED, false); + if (hdcp->hdcp2_encrypted) + ret = _intel_hdcp2_disable(connector); + else if (hdcp->hdcp_encrypted) + ret = _intel_hdcp_disable(connector); + +out: mutex_unlock(&hdcp->mutex); cancel_delayed_work_sync(&hdcp->check_work); return ret; -- GitLab From 36e5e7042b202025f8643538c2d591cab1f24b72 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:57 -0400 Subject: [PATCH 0710/1494] drm/i915: Don't fully disable HDCP on a port if multiple pipes are using it This patch is required for HDCP over MST. If a port is being used for multiple HDCP streams, we don't want to fully disable HDCP on a port if one of them is disabled. Instead, we just disable the HDCP signalling on that particular pipe and exit early. The last pipe to disable HDCP will also bring down HDCP on the port. In order to achieve this, we need to keep a refcount in intel_digital_port and protect it using a new hdcp_mutex. Cc: Ramalingam C <ramalingam.c@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-8-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-9-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-9-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-9-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-9-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-9-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-10-sean@poorly.run #v7 Changes in v2: -Move the toggle_signalling call into _intel_hdcp_disable so it's called from check_work Changes in v3: -None Changes in v4: -None Changes in v5: -Change WARN_ON to drm_WARN_ON Changes in v6: -None Changes in v7: -Split minor intel_hdcp_disable refactor into separate patch (Ramalingam) Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-10-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_ddi.c | 3 ++ .../drm/i915/display/intel_display_types.h | 5 +++ drivers/gpu/drm/i915/display/intel_dp.c | 2 ++ drivers/gpu/drm/i915/display/intel_hdcp.c | 33 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_hdmi.c | 2 ++ 5 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index f186214150e28..81af56409a221 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -5026,6 +5026,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port)); + mutex_init(&dig_port->hdcp_mutex); + dig_port->num_hdcp_streams = 0; + encoder->hotplug = intel_ddi_hotplug; encoder->compute_output_type = intel_ddi_compute_output_type; encoder->compute_config = intel_ddi_compute_config; diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index d30ec7728a995..b6d0ad1714320 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1416,6 +1416,11 @@ struct intel_digital_port { enum phy_fia tc_phy_fia; u8 tc_phy_fia_idx; + /* protects num_hdcp_streams reference count */ + struct mutex hdcp_mutex; + /* the number of pipes using HDCP signalling out of this port */ + unsigned int num_hdcp_streams; + void (*write_infoframe)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, unsigned int type, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c771fa72c2fb5..a8f00788217a4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -8342,6 +8342,8 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder = &dig_port->base; encoder = &intel_encoder->base; + mutex_init(&dig_port->hdcp_mutex); + if (drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS, "DP %c", port_name(port))) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index f4939f63d8dd1..7bc8c06f3132b 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -792,6 +792,19 @@ static int _intel_hdcp_disable(struct intel_connector *connector) drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP is being disabled...\n", connector->base.name, connector->base.base.id); + /* + * If there are other connectors on this port using HDCP, don't disable + * it. Instead, toggle the HDCP signalling off on that particular + * connector/pipe and exit. + */ + if (dig_port->num_hdcp_streams > 0) { + ret = hdcp->shim->toggle_signalling(dig_port, + cpu_transcoder, false); + if (ret) + DRM_ERROR("Failed to disable HDCP signalling\n"); + return ret; + } + hdcp->hdcp_encrypted = false; intel_de_write(dev_priv, HDCP_CONF(dev_priv, cpu_transcoder, port), 0); if (intel_de_wait_for_clear(dev_priv, @@ -870,6 +883,8 @@ static struct intel_connector *intel_hdcp_to_connector(struct intel_hdcp *hdcp) static void intel_hdcp_update_value(struct intel_connector *connector, u64 value, bool update_property) { + struct drm_device *dev = connector->base.dev; + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; drm_WARN_ON(connector->base.dev, !mutex_is_locked(&hdcp->mutex)); @@ -877,6 +892,15 @@ static void intel_hdcp_update_value(struct intel_connector *connector, if (hdcp->value == value) return; + drm_WARN_ON(dev, !mutex_is_locked(&dig_port->hdcp_mutex)); + + if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + if (!drm_WARN_ON(dev, dig_port->num_hdcp_streams == 0)) + dig_port->num_hdcp_streams--; + } else if (value == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + dig_port->num_hdcp_streams++; + } + hdcp->value = value; if (update_property) { drm_connector_get(&connector->base); @@ -895,6 +919,8 @@ static int intel_hdcp_check_link(struct intel_connector *connector) int ret = 0; mutex_lock(&hdcp->mutex); + mutex_lock(&dig_port->hdcp_mutex); + cpu_transcoder = hdcp->cpu_transcoder; /* Check_link valid only when HDCP1.4 is enabled */ @@ -948,6 +974,7 @@ static int intel_hdcp_check_link(struct intel_connector *connector) } out: + mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; } @@ -2047,6 +2074,7 @@ int intel_hdcp_enable(struct intel_connector *connector, enum transcoder cpu_transcoder, u8 content_type) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; int ret = -EINVAL; @@ -2055,6 +2083,7 @@ int intel_hdcp_enable(struct intel_connector *connector, return -ENOENT; mutex_lock(&hdcp->mutex); + mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); hdcp->content_type = content_type; @@ -2089,12 +2118,14 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } + mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; } int intel_hdcp_disable(struct intel_connector *connector) { + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; int ret = 0; @@ -2102,6 +2133,7 @@ int intel_hdcp_disable(struct intel_connector *connector) return -ENOENT; mutex_lock(&hdcp->mutex); + mutex_lock(&dig_port->hdcp_mutex); if (hdcp->value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) goto out; @@ -2114,6 +2146,7 @@ int intel_hdcp_disable(struct intel_connector *connector) ret = _intel_hdcp_disable(connector); out: + mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); cancel_delayed_work_sync(&hdcp->check_work); return ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 3966fcfb7d3a6..9c3b1ae2cd2bc 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3341,6 +3341,8 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, intel_encoder = &dig_port->base; + mutex_init(&dig_port->hdcp_mutex); + drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port)); -- GitLab From 515d5755ee5ac6d8dce86ddb9d097ab9fe4ca16b Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:58 -0400 Subject: [PATCH 0711/1494] drm/i915: Support DP MST in enc_to_dig_port() function Although DP_MST fake encoders are not subclassed from digital ports, they are associated with them. Support these encoders. Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-9-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-10-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-10-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-10-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-10-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-10-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-11-sean@poorly.run #v7 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-11-sean@poorly.run --- .../drm/i915/display/intel_display_types.h | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b6d0ad1714320..5e01f2f840c97 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1531,6 +1531,18 @@ static inline bool intel_encoder_is_dig_port(struct intel_encoder *encoder) } } +static inline bool intel_encoder_is_mst(struct intel_encoder *encoder) +{ + return encoder->type == INTEL_OUTPUT_DP_MST; +} + +static inline struct intel_dp_mst_encoder * +enc_to_mst(struct intel_encoder *encoder) +{ + return container_of(&encoder->base, struct intel_dp_mst_encoder, + base.base); +} + static inline struct intel_digital_port * enc_to_dig_port(struct intel_encoder *encoder) { @@ -1539,6 +1551,8 @@ enc_to_dig_port(struct intel_encoder *encoder) if (intel_encoder_is_dig_port(intel_encoder)) return container_of(&encoder->base, struct intel_digital_port, base.base); + else if (intel_encoder_is_mst(intel_encoder)) + return enc_to_mst(encoder)->primary; else return NULL; } @@ -1549,13 +1563,6 @@ intel_attached_dig_port(struct intel_connector *connector) return enc_to_dig_port(intel_attached_encoder(connector)); } -static inline struct intel_dp_mst_encoder * -enc_to_mst(struct intel_encoder *encoder) -{ - return container_of(&encoder->base, struct intel_dp_mst_encoder, - base.base); -} - static inline struct intel_dp *enc_to_intel_dp(struct intel_encoder *encoder) { return &enc_to_dig_port(encoder)->dp; -- GitLab From f1c7a36b05edd99d9899c8b2adc0e53f93c7c3d7 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:38:59 -0400 Subject: [PATCH 0712/1494] drm/i915: Use ddi_update_pipe in intel_dp_mst In order to act upon content_protection property changes, we'll need to implement the .update_pipe() hook. We can re-use intel_ddi_update_pipe for this Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-10-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-11-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-11-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-11-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-11-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-11-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-12-sean@poorly.run #v7 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-12-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_ddi.c | 11 ++++++----- drivers/gpu/drm/i915/display/intel_dp.h | 6 ++++++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 81af56409a221..a2b7dcf844302 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4042,13 +4042,14 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, intel_panel_update_backlight(state, encoder, crtc_state, conn_state); } -static void intel_ddi_update_pipe(struct intel_atomic_state *state, - struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state) +void intel_ddi_update_pipe(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { - if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && + !intel_encoder_is_mst(encoder)) intel_ddi_update_pipe_dp(state, encoder, crtc_state, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 057b2c152cbdc..d2dbd2a5cd1e7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -17,6 +17,7 @@ struct drm_encoder; struct drm_i915_private; struct drm_modeset_acquire_ctx; struct drm_dp_vsc_sdp; +struct intel_atomic_state; struct intel_connector; struct intel_crtc_state; struct intel_digital_port; @@ -130,4 +131,9 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) u32 intel_dp_mode_to_fec_clock(u32 mode_clock); +void intel_ddi_update_pipe(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index a2d91a4997001..b97b2918d8029 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -865,6 +865,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe intel_encoder->compute_config_late = intel_dp_mst_compute_config_late; intel_encoder->disable = intel_mst_disable_dp; intel_encoder->post_disable = intel_mst_post_disable_dp; + intel_encoder->update_pipe = intel_ddi_update_pipe; intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; intel_encoder->pre_enable = intel_mst_pre_enable_dp; intel_encoder->enable = intel_mst_enable_dp; -- GitLab From d079b7e4b6389e36c50730985100bb528f0d3883 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:39:00 -0400 Subject: [PATCH 0713/1494] drm/i915: Factor out HDCP shim functions from dp for use by dp_mst These functions are all the same for dp and dp_mst, so move them into a dedicated file for both sst and mst to use. Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-11-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-12-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-12-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-12-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-12-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-12-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-13-sean@poorly.run #v7 Changes in v2: -None Changes in v3: -Created intel_dp_hdcp.c for the shared functions to live (Ville) Changes in v4: -Rebased on new drm logging change Changes in v5: -None Changes in v6: -None Changes in v7: -Rebased patch Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-13-sean@poorly.run --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 607 +----------------- drivers/gpu/drm/i915/display/intel_dp.h | 3 + drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 637 +++++++++++++++++++ 4 files changed, 642 insertions(+), 606 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dp_hdcp.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index bda4c0e408f8b..e5574e506a5cc 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -234,6 +234,7 @@ i915-y += \ display/intel_ddi.o \ display/intel_dp.o \ display/intel_dp_aux_backlight.o \ + display/intel_dp_hdcp.o \ display/intel_dp_link_training.o \ display/intel_dp_mst.o \ display/intel_dsi.o \ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a8f00788217a4..04231ca5643b3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -38,7 +38,6 @@ #include <drm/drm_crtc.h> #include <drm/drm_dp_helper.h> #include <drm/drm_edid.h> -#include <drm/drm_hdcp.h> #include <drm/drm_probe_helper.h> #include "i915_debugfs.h" @@ -6414,610 +6413,6 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) edp_panel_vdd_off_sync(intel_dp); } -static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) -{ - long ret; - -#define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count)) - ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C, - msecs_to_jiffies(timeout)); - - if (!ret) - DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n"); -} - -static -int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, - u8 *an) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - u8 aksv[DRM_HDCP_KSV_LEN] = {}; - ssize_t dpcd_ret; - - /* Output An first, that's easy */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, - an, DRM_HDCP_AN_LEN); - if (dpcd_ret != DRM_HDCP_AN_LEN) { - drm_dbg_kms(&i915->drm, - "Failed to write An over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; - } - - /* - * Since Aksv is Oh-So-Secret, we can't access it in software. So we - * send an empty buffer of the correct length through the DP helpers. On - * the other side, in the transfer hook, we'll generate a flag based on - * the destination address which will tickle the hardware to output the - * Aksv on our behalf after the header is sent. - */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, - aksv, DRM_HDCP_KSV_LEN); - if (dpcd_ret != DRM_HDCP_KSV_LEN) { - drm_dbg_kms(&i915->drm, - "Failed to write Aksv over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; - } - return 0; -} - -static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port, - u8 *bksv) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, - DRM_HDCP_KSV_LEN); - if (ret != DRM_HDCP_KSV_LEN) { - drm_dbg_kms(&i915->drm, - "Read Bksv from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - return 0; -} - -static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, - u8 *bstatus) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - /* - * For some reason the HDMI and DP HDCP specs call this register - * definition by different names. In the HDMI spec, it's called BSTATUS, - * but in DP it's called BINFO. - */ - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, - bstatus, DRM_HDCP_BSTATUS_LEN); - if (ret != DRM_HDCP_BSTATUS_LEN) { - drm_dbg_kms(&i915->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - return 0; -} - -static -int intel_dp_hdcp_read_bcaps(struct intel_digital_port *dig_port, - u8 *bcaps) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BCAPS, - bcaps, 1); - if (ret != 1) { - drm_dbg_kms(&i915->drm, - "Read bcaps from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - - return 0; -} - -static -int intel_dp_hdcp_repeater_present(struct intel_digital_port *dig_port, - bool *repeater_present) -{ - ssize_t ret; - u8 bcaps; - - ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); - if (ret) - return ret; - - *repeater_present = bcaps & DP_BCAPS_REPEATER_PRESENT; - return 0; -} - -static -int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port, - u8 *ri_prime) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, - ri_prime, DRM_HDCP_RI_LEN); - if (ret != DRM_HDCP_RI_LEN) { - drm_dbg_kms(&i915->drm, "Read Ri' from DP/AUX failed (%zd)\n", - ret); - return ret >= 0 ? -EIO : ret; - } - return 0; -} - -static -int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, - bool *ksv_ready) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - u8 bstatus; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { - drm_dbg_kms(&i915->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - *ksv_ready = bstatus & DP_BSTATUS_READY; - return 0; -} - -static -int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, - int num_downstream, u8 *ksv_fifo) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - int i; - - /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */ - for (i = 0; i < num_downstream; i += 3) { - size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_KSV_FIFO, - ksv_fifo + i * DRM_HDCP_KSV_LEN, - len); - if (ret != len) { - drm_dbg_kms(&i915->drm, - "Read ksv[%d] from DP/AUX failed (%zd)\n", - i, ret); - return ret >= 0 ? -EIO : ret; - } - } - return 0; -} - -static -int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, - int i, u32 *part) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) - return -EINVAL; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_V_PRIME(i), part, - DRM_HDCP_V_PRIME_PART_LEN); - if (ret != DRM_HDCP_V_PRIME_PART_LEN) { - drm_dbg_kms(&i915->drm, - "Read v'[%d] from DP/AUX failed (%zd)\n", i, ret); - return ret >= 0 ? -EIO : ret; - } - return 0; -} - -static -int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *dig_port, - enum transcoder cpu_transcoder, - bool enable) -{ - /* Not used for single stream DisplayPort setups */ - return 0; -} - -static -bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - u8 bstatus; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { - drm_dbg_kms(&i915->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return false; - } - - return !(bstatus & (DP_BSTATUS_LINK_FAILURE | DP_BSTATUS_REAUTH_REQ)); -} - -static -int intel_dp_hdcp_capable(struct intel_digital_port *dig_port, - bool *hdcp_capable) -{ - ssize_t ret; - u8 bcaps; - - ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); - if (ret) - return ret; - - *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE; - return 0; -} - -struct hdcp2_dp_errata_stream_type { - u8 msg_id; - u8 stream_type; -} __packed; - -struct hdcp2_dp_msg_data { - u8 msg_id; - u32 offset; - bool msg_detectable; - u32 timeout; - u32 timeout2; /* Added for non_paired situation */ -}; - -static const struct hdcp2_dp_msg_data hdcp2_dp_msg_data[] = { - { HDCP_2_2_AKE_INIT, DP_HDCP_2_2_AKE_INIT_OFFSET, false, 0, 0 }, - { HDCP_2_2_AKE_SEND_CERT, DP_HDCP_2_2_AKE_SEND_CERT_OFFSET, - false, HDCP_2_2_CERT_TIMEOUT_MS, 0 }, - { HDCP_2_2_AKE_NO_STORED_KM, DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET, - false, 0, 0 }, - { HDCP_2_2_AKE_STORED_KM, DP_HDCP_2_2_AKE_STORED_KM_OFFSET, - false, 0, 0 }, - { HDCP_2_2_AKE_SEND_HPRIME, DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET, - true, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS, - HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS }, - { HDCP_2_2_AKE_SEND_PAIRING_INFO, - DP_HDCP_2_2_AKE_SEND_PAIRING_INFO_OFFSET, true, - HDCP_2_2_PAIRING_TIMEOUT_MS, 0 }, - { HDCP_2_2_LC_INIT, DP_HDCP_2_2_LC_INIT_OFFSET, false, 0, 0 }, - { HDCP_2_2_LC_SEND_LPRIME, DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET, - false, HDCP_2_2_DP_LPRIME_TIMEOUT_MS, 0 }, - { HDCP_2_2_SKE_SEND_EKS, DP_HDCP_2_2_SKE_SEND_EKS_OFFSET, false, - 0, 0 }, - { HDCP_2_2_REP_SEND_RECVID_LIST, - DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET, true, - HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0 }, - { HDCP_2_2_REP_SEND_ACK, DP_HDCP_2_2_REP_SEND_ACK_OFFSET, false, - 0, 0 }, - { HDCP_2_2_REP_STREAM_MANAGE, - DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET, false, - 0, 0 }, - { HDCP_2_2_REP_STREAM_READY, DP_HDCP_2_2_REP_STREAM_READY_OFFSET, - false, HDCP_2_2_STREAM_READY_TIMEOUT_MS, 0 }, -/* local define to shovel this through the write_2_2 interface */ -#define HDCP_2_2_ERRATA_DP_STREAM_TYPE 50 - { HDCP_2_2_ERRATA_DP_STREAM_TYPE, - DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET, false, - 0, 0 }, -}; - -static int -intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port, - u8 *rx_status) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - ssize_t ret; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, - HDCP_2_2_DP_RXSTATUS_LEN); - if (ret != HDCP_2_2_DP_RXSTATUS_LEN) { - drm_dbg_kms(&i915->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; - } - - return 0; -} - -static -int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port, - u8 msg_id, bool *msg_ready) -{ - u8 rx_status; - int ret; - - *msg_ready = false; - ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); - if (ret < 0) - return ret; - - switch (msg_id) { - case HDCP_2_2_AKE_SEND_HPRIME: - if (HDCP_2_2_DP_RXSTATUS_H_PRIME(rx_status)) - *msg_ready = true; - break; - case HDCP_2_2_AKE_SEND_PAIRING_INFO: - if (HDCP_2_2_DP_RXSTATUS_PAIRING(rx_status)) - *msg_ready = true; - break; - case HDCP_2_2_REP_SEND_RECVID_LIST: - if (HDCP_2_2_DP_RXSTATUS_READY(rx_status)) - *msg_ready = true; - break; - default: - DRM_ERROR("Unidentified msg_id: %d\n", msg_id); - return -EINVAL; - } - - return 0; -} - -static ssize_t -intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port, - const struct hdcp2_dp_msg_data *hdcp2_msg_data) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_dp *dp = &dig_port->dp; - struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; - u8 msg_id = hdcp2_msg_data->msg_id; - int ret, timeout; - bool msg_ready = false; - - if (msg_id == HDCP_2_2_AKE_SEND_HPRIME && !hdcp->is_paired) - timeout = hdcp2_msg_data->timeout2; - else - timeout = hdcp2_msg_data->timeout; - - /* - * There is no way to detect the CERT, LPRIME and STREAM_READY - * availability. So Wait for timeout and read the msg. - */ - if (!hdcp2_msg_data->msg_detectable) { - mdelay(timeout); - ret = 0; - } else { - /* - * As we want to check the msg availability at timeout, Ignoring - * the timeout at wait for CP_IRQ. - */ - intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout); - ret = hdcp2_detect_msg_availability(dig_port, - msg_id, &msg_ready); - if (!msg_ready) - ret = -ETIMEDOUT; - } - - if (ret) - drm_dbg_kms(&i915->drm, - "msg_id %d, ret %d, timeout(mSec): %d\n", - hdcp2_msg_data->msg_id, ret, timeout); - - return ret; -} - -static const struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdcp2_dp_msg_data); i++) - if (hdcp2_dp_msg_data[i].msg_id == msg_id) - return &hdcp2_dp_msg_data[i]; - - return NULL; -} - -static -int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port, - void *buf, size_t size) -{ - struct intel_dp *dp = &dig_port->dp; - struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; - unsigned int offset; - u8 *byte = buf; - ssize_t ret, bytes_to_write, len; - const struct hdcp2_dp_msg_data *hdcp2_msg_data; - - hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte); - if (!hdcp2_msg_data) - return -EINVAL; - - offset = hdcp2_msg_data->offset; - - /* No msg_id in DP HDCP2.2 msgs */ - bytes_to_write = size - 1; - byte++; - - hdcp->cp_irq_count_cached = atomic_read(&hdcp->cp_irq_count); - - while (bytes_to_write) { - len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ? - DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write; - - ret = drm_dp_dpcd_write(&dig_port->dp.aux, - offset, (void *)byte, len); - if (ret < 0) - return ret; - - bytes_to_write -= ret; - byte += ret; - offset += ret; - } - - return size; -} - -static -ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port) -{ - u8 rx_info[HDCP_2_2_RXINFO_LEN]; - u32 dev_cnt; - ssize_t ret; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_HDCP_2_2_REG_RXINFO_OFFSET, - (void *)rx_info, HDCP_2_2_RXINFO_LEN); - if (ret != HDCP_2_2_RXINFO_LEN) - return ret >= 0 ? -EIO : ret; - - dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 | - HDCP_2_2_DEV_COUNT_LO(rx_info[1])); - - if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT) - dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT; - - ret = sizeof(struct hdcp2_rep_send_receiverid_list) - - HDCP_2_2_RECEIVER_IDS_MAX_LEN + - (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN); - - return ret; -} - -static -int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port, - u8 msg_id, void *buf, size_t size) -{ - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - unsigned int offset; - u8 *byte = buf; - ssize_t ret, bytes_to_recv, len; - const struct hdcp2_dp_msg_data *hdcp2_msg_data; - - hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id); - if (!hdcp2_msg_data) - return -EINVAL; - offset = hdcp2_msg_data->offset; - - ret = intel_dp_hdcp2_wait_for_msg(dig_port, hdcp2_msg_data); - if (ret < 0) - return ret; - - if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) { - ret = get_receiver_id_list_size(dig_port); - if (ret < 0) - return ret; - - size = ret; - } - bytes_to_recv = size - 1; - - /* DP adaptation msgs has no msg_id */ - byte++; - - while (bytes_to_recv) { - len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ? - DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv; - - ret = drm_dp_dpcd_read(&dig_port->dp.aux, offset, - (void *)byte, len); - if (ret < 0) { - drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n", - msg_id, ret); - return ret; - } - - bytes_to_recv -= ret; - byte += ret; - offset += ret; - } - byte = buf; - *byte = msg_id; - - return size; -} - -static -int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port, - bool is_repeater, u8 content_type) -{ - int ret; - struct hdcp2_dp_errata_stream_type stream_type_msg; - - if (is_repeater) - return 0; - - /* - * Errata for DP: As Stream type is used for encryption, Receiver - * should be communicated with stream type for the decryption of the - * content. - * Repeater will be communicated with stream type as a part of it's - * auth later in time. - */ - stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE; - stream_type_msg.stream_type = content_type; - - ret = intel_dp_hdcp2_write_msg(dig_port, &stream_type_msg, - sizeof(stream_type_msg)); - - return ret < 0 ? ret : 0; - -} - -static -int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port) -{ - u8 rx_status; - int ret; - - ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); - if (ret) - return ret; - - if (HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(rx_status)) - ret = HDCP_REAUTH_REQUEST; - else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status)) - ret = HDCP_LINK_INTEGRITY_FAILURE; - else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status)) - ret = HDCP_TOPOLOGY_CHANGE; - - return ret; -} - -static -int intel_dp_hdcp2_capable(struct intel_digital_port *dig_port, - bool *capable) -{ - u8 rx_caps[3]; - int ret; - - *capable = false; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_HDCP_2_2_REG_RX_CAPS_OFFSET, - rx_caps, HDCP_2_2_RXCAPS_LEN); - if (ret != HDCP_2_2_RXCAPS_LEN) - return ret >= 0 ? -EIO : ret; - - if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && - HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) - *capable = true; - - return 0; -} - -static const struct intel_hdcp_shim intel_dp_hdcp_shim = { - .write_an_aksv = intel_dp_hdcp_write_an_aksv, - .read_bksv = intel_dp_hdcp_read_bksv, - .read_bstatus = intel_dp_hdcp_read_bstatus, - .repeater_present = intel_dp_hdcp_repeater_present, - .read_ri_prime = intel_dp_hdcp_read_ri_prime, - .read_ksv_ready = intel_dp_hdcp_read_ksv_ready, - .read_ksv_fifo = intel_dp_hdcp_read_ksv_fifo, - .read_v_prime_part = intel_dp_hdcp_read_v_prime_part, - .toggle_signalling = intel_dp_hdcp_toggle_signalling, - .check_link = intel_dp_hdcp_check_link, - .hdcp_capable = intel_dp_hdcp_capable, - .write_2_2_msg = intel_dp_hdcp2_write_msg, - .read_2_2_msg = intel_dp_hdcp2_read_msg, - .config_stream_type = intel_dp_hdcp2_config_stream_type, - .check_2_2_link = intel_dp_hdcp2_check_link, - .hdcp_2_2_capable = intel_dp_hdcp2_capable, - .protocol = HDCP_PROTOCOL_DP, -}; - static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -8298,7 +7693,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_dp_add_properties(intel_dp, connector); if (is_hdcp_supported(dev_priv, port) && !intel_dp_is_edp(intel_dp)) { - int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim); + int ret = intel_dp_init_hdcp(dig_port, intel_connector); if (ret) drm_dbg_kms(&dev_priv->drm, "HDCP init failed, skipping.\n"); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index d2dbd2a5cd1e7..9bb50c39174e5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -136,4 +136,7 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); +int intel_dp_init_hdcp(struct intel_digital_port *dig_port, + struct intel_connector *intel_connector); + #endif /* __INTEL_DP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c new file mode 100644 index 0000000000000..0b8200bed0610 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -0,0 +1,637 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2020 Google, Inc. + * + * Authors: + * Sean Paul <seanpaul@chromium.org> + */ + +#include <drm/drm_dp_helper.h> +#include <drm/drm_hdcp.h> +#include <drm/drm_print.h> + +#include "intel_display_types.h" +#include "intel_dp.h" +#include "intel_hdcp.h" + +static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout) +{ + long ret; + +#define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count)) + ret = wait_event_interruptible_timeout(hdcp->cp_irq_queue, C, + msecs_to_jiffies(timeout)); + + if (!ret) + DRM_DEBUG_KMS("Timedout at waiting for CP_IRQ\n"); +} + +static +int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, + u8 *an) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + u8 aksv[DRM_HDCP_KSV_LEN] = {}; + ssize_t dpcd_ret; + + /* Output An first, that's easy */ + dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, + an, DRM_HDCP_AN_LEN); + if (dpcd_ret != DRM_HDCP_AN_LEN) { + drm_dbg_kms(&i915->drm, + "Failed to write An over DP/AUX (%zd)\n", + dpcd_ret); + return dpcd_ret >= 0 ? -EIO : dpcd_ret; + } + + /* + * Since Aksv is Oh-So-Secret, we can't access it in software. So we + * send an empty buffer of the correct length through the DP helpers. On + * the other side, in the transfer hook, we'll generate a flag based on + * the destination address which will tickle the hardware to output the + * Aksv on our behalf after the header is sent. + */ + dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, + aksv, DRM_HDCP_KSV_LEN); + if (dpcd_ret != DRM_HDCP_KSV_LEN) { + drm_dbg_kms(&i915->drm, + "Failed to write Aksv over DP/AUX (%zd)\n", + dpcd_ret); + return dpcd_ret >= 0 ? -EIO : dpcd_ret; + } + return 0; +} + +static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port, + u8 *bksv) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, + DRM_HDCP_KSV_LEN); + if (ret != DRM_HDCP_KSV_LEN) { + drm_dbg_kms(&i915->drm, + "Read Bksv from DP/AUX failed (%zd)\n", ret); + return ret >= 0 ? -EIO : ret; + } + return 0; +} + +static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, + u8 *bstatus) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + /* + * For some reason the HDMI and DP HDCP specs call this register + * definition by different names. In the HDMI spec, it's called BSTATUS, + * but in DP it's called BINFO. + */ + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, + bstatus, DRM_HDCP_BSTATUS_LEN); + if (ret != DRM_HDCP_BSTATUS_LEN) { + drm_dbg_kms(&i915->drm, + "Read bstatus from DP/AUX failed (%zd)\n", ret); + return ret >= 0 ? -EIO : ret; + } + return 0; +} + +static +int intel_dp_hdcp_read_bcaps(struct intel_digital_port *dig_port, + u8 *bcaps) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BCAPS, + bcaps, 1); + if (ret != 1) { + drm_dbg_kms(&i915->drm, + "Read bcaps from DP/AUX failed (%zd)\n", ret); + return ret >= 0 ? -EIO : ret; + } + + return 0; +} + +static +int intel_dp_hdcp_repeater_present(struct intel_digital_port *dig_port, + bool *repeater_present) +{ + ssize_t ret; + u8 bcaps; + + ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); + if (ret) + return ret; + + *repeater_present = bcaps & DP_BCAPS_REPEATER_PRESENT; + return 0; +} + +static +int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port, + u8 *ri_prime) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, + ri_prime, DRM_HDCP_RI_LEN); + if (ret != DRM_HDCP_RI_LEN) { + drm_dbg_kms(&i915->drm, "Read Ri' from DP/AUX failed (%zd)\n", + ret); + return ret >= 0 ? -EIO : ret; + } + return 0; +} + +static +int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, + bool *ksv_ready) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + u8 bstatus; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + &bstatus, 1); + if (ret != 1) { + drm_dbg_kms(&i915->drm, + "Read bstatus from DP/AUX failed (%zd)\n", ret); + return ret >= 0 ? -EIO : ret; + } + *ksv_ready = bstatus & DP_BSTATUS_READY; + return 0; +} + +static +int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, + int num_downstream, u8 *ksv_fifo) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + int i; + + /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */ + for (i = 0; i < num_downstream; i += 3) { + size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN; + ret = drm_dp_dpcd_read(&dig_port->dp.aux, + DP_AUX_HDCP_KSV_FIFO, + ksv_fifo + i * DRM_HDCP_KSV_LEN, + len); + if (ret != len) { + drm_dbg_kms(&i915->drm, + "Read ksv[%d] from DP/AUX failed (%zd)\n", + i, ret); + return ret >= 0 ? -EIO : ret; + } + } + return 0; +} + +static +int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, + int i, u32 *part) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) + return -EINVAL; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, + DP_AUX_HDCP_V_PRIME(i), part, + DRM_HDCP_V_PRIME_PART_LEN); + if (ret != DRM_HDCP_V_PRIME_PART_LEN) { + drm_dbg_kms(&i915->drm, + "Read v'[%d] from DP/AUX failed (%zd)\n", i, ret); + return ret >= 0 ? -EIO : ret; + } + return 0; +} + +static +int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *dig_port, + enum transcoder cpu_transcoder, + bool enable) +{ + /* Not used for single stream DisplayPort setups */ + return 0; +} + +static +bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + u8 bstatus; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + &bstatus, 1); + if (ret != 1) { + drm_dbg_kms(&i915->drm, + "Read bstatus from DP/AUX failed (%zd)\n", ret); + return false; + } + + return !(bstatus & (DP_BSTATUS_LINK_FAILURE | DP_BSTATUS_REAUTH_REQ)); +} + +static +int intel_dp_hdcp_capable(struct intel_digital_port *dig_port, + bool *hdcp_capable) +{ + ssize_t ret; + u8 bcaps; + + ret = intel_dp_hdcp_read_bcaps(dig_port, &bcaps); + if (ret) + return ret; + + *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE; + return 0; +} + +struct hdcp2_dp_errata_stream_type { + u8 msg_id; + u8 stream_type; +} __packed; + +struct hdcp2_dp_msg_data { + u8 msg_id; + u32 offset; + bool msg_detectable; + u32 timeout; + u32 timeout2; /* Added for non_paired situation */ +}; + +static const struct hdcp2_dp_msg_data hdcp2_dp_msg_data[] = { + { HDCP_2_2_AKE_INIT, DP_HDCP_2_2_AKE_INIT_OFFSET, false, 0, 0 }, + { HDCP_2_2_AKE_SEND_CERT, DP_HDCP_2_2_AKE_SEND_CERT_OFFSET, + false, HDCP_2_2_CERT_TIMEOUT_MS, 0 }, + { HDCP_2_2_AKE_NO_STORED_KM, DP_HDCP_2_2_AKE_NO_STORED_KM_OFFSET, + false, 0, 0 }, + { HDCP_2_2_AKE_STORED_KM, DP_HDCP_2_2_AKE_STORED_KM_OFFSET, + false, 0, 0 }, + { HDCP_2_2_AKE_SEND_HPRIME, DP_HDCP_2_2_AKE_SEND_HPRIME_OFFSET, + true, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS, + HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS }, + { HDCP_2_2_AKE_SEND_PAIRING_INFO, + DP_HDCP_2_2_AKE_SEND_PAIRING_INFO_OFFSET, true, + HDCP_2_2_PAIRING_TIMEOUT_MS, 0 }, + { HDCP_2_2_LC_INIT, DP_HDCP_2_2_LC_INIT_OFFSET, false, 0, 0 }, + { HDCP_2_2_LC_SEND_LPRIME, DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET, + false, HDCP_2_2_DP_LPRIME_TIMEOUT_MS, 0 }, + { HDCP_2_2_SKE_SEND_EKS, DP_HDCP_2_2_SKE_SEND_EKS_OFFSET, false, + 0, 0 }, + { HDCP_2_2_REP_SEND_RECVID_LIST, + DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET, true, + HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0 }, + { HDCP_2_2_REP_SEND_ACK, DP_HDCP_2_2_REP_SEND_ACK_OFFSET, false, + 0, 0 }, + { HDCP_2_2_REP_STREAM_MANAGE, + DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET, false, + 0, 0 }, + { HDCP_2_2_REP_STREAM_READY, DP_HDCP_2_2_REP_STREAM_READY_OFFSET, + false, HDCP_2_2_STREAM_READY_TIMEOUT_MS, 0 }, +/* local define to shovel this through the write_2_2 interface */ +#define HDCP_2_2_ERRATA_DP_STREAM_TYPE 50 + { HDCP_2_2_ERRATA_DP_STREAM_TYPE, + DP_HDCP_2_2_REG_STREAM_TYPE_OFFSET, false, + 0, 0 }, +}; + +static int +intel_dp_hdcp2_read_rx_status(struct intel_digital_port *dig_port, + u8 *rx_status) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + ssize_t ret; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, + DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, + HDCP_2_2_DP_RXSTATUS_LEN); + if (ret != HDCP_2_2_DP_RXSTATUS_LEN) { + drm_dbg_kms(&i915->drm, + "Read bstatus from DP/AUX failed (%zd)\n", ret); + return ret >= 0 ? -EIO : ret; + } + + return 0; +} + +static +int hdcp2_detect_msg_availability(struct intel_digital_port *dig_port, + u8 msg_id, bool *msg_ready) +{ + u8 rx_status; + int ret; + + *msg_ready = false; + ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); + if (ret < 0) + return ret; + + switch (msg_id) { + case HDCP_2_2_AKE_SEND_HPRIME: + if (HDCP_2_2_DP_RXSTATUS_H_PRIME(rx_status)) + *msg_ready = true; + break; + case HDCP_2_2_AKE_SEND_PAIRING_INFO: + if (HDCP_2_2_DP_RXSTATUS_PAIRING(rx_status)) + *msg_ready = true; + break; + case HDCP_2_2_REP_SEND_RECVID_LIST: + if (HDCP_2_2_DP_RXSTATUS_READY(rx_status)) + *msg_ready = true; + break; + default: + DRM_ERROR("Unidentified msg_id: %d\n", msg_id); + return -EINVAL; + } + + return 0; +} + +static ssize_t +intel_dp_hdcp2_wait_for_msg(struct intel_digital_port *dig_port, + const struct hdcp2_dp_msg_data *hdcp2_msg_data) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *dp = &dig_port->dp; + struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; + u8 msg_id = hdcp2_msg_data->msg_id; + int ret, timeout; + bool msg_ready = false; + + if (msg_id == HDCP_2_2_AKE_SEND_HPRIME && !hdcp->is_paired) + timeout = hdcp2_msg_data->timeout2; + else + timeout = hdcp2_msg_data->timeout; + + /* + * There is no way to detect the CERT, LPRIME and STREAM_READY + * availability. So Wait for timeout and read the msg. + */ + if (!hdcp2_msg_data->msg_detectable) { + mdelay(timeout); + ret = 0; + } else { + /* + * As we want to check the msg availability at timeout, Ignoring + * the timeout at wait for CP_IRQ. + */ + intel_dp_hdcp_wait_for_cp_irq(hdcp, timeout); + ret = hdcp2_detect_msg_availability(dig_port, + msg_id, &msg_ready); + if (!msg_ready) + ret = -ETIMEDOUT; + } + + if (ret) + drm_dbg_kms(&i915->drm, + "msg_id %d, ret %d, timeout(mSec): %d\n", + hdcp2_msg_data->msg_id, ret, timeout); + + return ret; +} + +static const struct hdcp2_dp_msg_data *get_hdcp2_dp_msg_data(u8 msg_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hdcp2_dp_msg_data); i++) + if (hdcp2_dp_msg_data[i].msg_id == msg_id) + return &hdcp2_dp_msg_data[i]; + + return NULL; +} + +static +int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port, + void *buf, size_t size) +{ + struct intel_dp *dp = &dig_port->dp; + struct intel_hdcp *hdcp = &dp->attached_connector->hdcp; + unsigned int offset; + u8 *byte = buf; + ssize_t ret, bytes_to_write, len; + const struct hdcp2_dp_msg_data *hdcp2_msg_data; + + hdcp2_msg_data = get_hdcp2_dp_msg_data(*byte); + if (!hdcp2_msg_data) + return -EINVAL; + + offset = hdcp2_msg_data->offset; + + /* No msg_id in DP HDCP2.2 msgs */ + bytes_to_write = size - 1; + byte++; + + hdcp->cp_irq_count_cached = atomic_read(&hdcp->cp_irq_count); + + while (bytes_to_write) { + len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ? + DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write; + + ret = drm_dp_dpcd_write(&dig_port->dp.aux, + offset, (void *)byte, len); + if (ret < 0) + return ret; + + bytes_to_write -= ret; + byte += ret; + offset += ret; + } + + return size; +} + +static +ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port) +{ + u8 rx_info[HDCP_2_2_RXINFO_LEN]; + u32 dev_cnt; + ssize_t ret; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, + DP_HDCP_2_2_REG_RXINFO_OFFSET, + (void *)rx_info, HDCP_2_2_RXINFO_LEN); + if (ret != HDCP_2_2_RXINFO_LEN) + return ret >= 0 ? -EIO : ret; + + dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 | + HDCP_2_2_DEV_COUNT_LO(rx_info[1])); + + if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT) + dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT; + + ret = sizeof(struct hdcp2_rep_send_receiverid_list) - + HDCP_2_2_RECEIVER_IDS_MAX_LEN + + (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN); + + return ret; +} + +static +int intel_dp_hdcp2_read_msg(struct intel_digital_port *dig_port, + u8 msg_id, void *buf, size_t size) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + unsigned int offset; + u8 *byte = buf; + ssize_t ret, bytes_to_recv, len; + const struct hdcp2_dp_msg_data *hdcp2_msg_data; + + hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id); + if (!hdcp2_msg_data) + return -EINVAL; + offset = hdcp2_msg_data->offset; + + ret = intel_dp_hdcp2_wait_for_msg(dig_port, hdcp2_msg_data); + if (ret < 0) + return ret; + + if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) { + ret = get_receiver_id_list_size(dig_port); + if (ret < 0) + return ret; + + size = ret; + } + bytes_to_recv = size - 1; + + /* DP adaptation msgs has no msg_id */ + byte++; + + while (bytes_to_recv) { + len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ? + DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_recv; + + ret = drm_dp_dpcd_read(&dig_port->dp.aux, offset, + (void *)byte, len); + if (ret < 0) { + drm_dbg_kms(&i915->drm, "msg_id %d, ret %zd\n", + msg_id, ret); + return ret; + } + + bytes_to_recv -= ret; + byte += ret; + offset += ret; + } + byte = buf; + *byte = msg_id; + + return size; +} + +static +int intel_dp_hdcp2_config_stream_type(struct intel_digital_port *dig_port, + bool is_repeater, u8 content_type) +{ + int ret; + struct hdcp2_dp_errata_stream_type stream_type_msg; + + if (is_repeater) + return 0; + + /* + * Errata for DP: As Stream type is used for encryption, Receiver + * should be communicated with stream type for the decryption of the + * content. + * Repeater will be communicated with stream type as a part of it's + * auth later in time. + */ + stream_type_msg.msg_id = HDCP_2_2_ERRATA_DP_STREAM_TYPE; + stream_type_msg.stream_type = content_type; + + ret = intel_dp_hdcp2_write_msg(dig_port, &stream_type_msg, + sizeof(stream_type_msg)); + + return ret < 0 ? ret : 0; + +} + +static +int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port) +{ + u8 rx_status; + int ret; + + ret = intel_dp_hdcp2_read_rx_status(dig_port, &rx_status); + if (ret) + return ret; + + if (HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(rx_status)) + ret = HDCP_REAUTH_REQUEST; + else if (HDCP_2_2_DP_RXSTATUS_LINK_FAILED(rx_status)) + ret = HDCP_LINK_INTEGRITY_FAILURE; + else if (HDCP_2_2_DP_RXSTATUS_READY(rx_status)) + ret = HDCP_TOPOLOGY_CHANGE; + + return ret; +} + +static +int intel_dp_hdcp2_capable(struct intel_digital_port *dig_port, + bool *capable) +{ + u8 rx_caps[3]; + int ret; + + *capable = false; + ret = drm_dp_dpcd_read(&dig_port->dp.aux, + DP_HDCP_2_2_REG_RX_CAPS_OFFSET, + rx_caps, HDCP_2_2_RXCAPS_LEN); + if (ret != HDCP_2_2_RXCAPS_LEN) + return ret >= 0 ? -EIO : ret; + + if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && + HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) + *capable = true; + + return 0; +} + +static const struct intel_hdcp_shim intel_dp_hdcp_shim = { + .write_an_aksv = intel_dp_hdcp_write_an_aksv, + .read_bksv = intel_dp_hdcp_read_bksv, + .read_bstatus = intel_dp_hdcp_read_bstatus, + .repeater_present = intel_dp_hdcp_repeater_present, + .read_ri_prime = intel_dp_hdcp_read_ri_prime, + .read_ksv_ready = intel_dp_hdcp_read_ksv_ready, + .read_ksv_fifo = intel_dp_hdcp_read_ksv_fifo, + .read_v_prime_part = intel_dp_hdcp_read_v_prime_part, + .toggle_signalling = intel_dp_hdcp_toggle_signalling, + .check_link = intel_dp_hdcp_check_link, + .hdcp_capable = intel_dp_hdcp_capable, + .write_2_2_msg = intel_dp_hdcp2_write_msg, + .read_2_2_msg = intel_dp_hdcp2_read_msg, + .config_stream_type = intel_dp_hdcp2_config_stream_type, + .check_2_2_link = intel_dp_hdcp2_check_link, + .hdcp_2_2_capable = intel_dp_hdcp2_capable, + .protocol = HDCP_PROTOCOL_DP, +}; + +int intel_dp_init_hdcp(struct intel_digital_port *dig_port, + struct intel_connector *intel_connector) +{ + struct drm_device *dev = intel_connector->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_encoder *intel_encoder = &dig_port->base; + enum port port = intel_encoder->port; + struct intel_dp *intel_dp = &dig_port->dp; + + if (!is_hdcp_supported(dev_priv, port)) + return 0; + + if (!intel_dp_is_edp(intel_dp)) + return intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim); + + return 0; +} -- GitLab From bf3657dad00b77fef993ea4fc985de3951f5abc0 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:39:01 -0400 Subject: [PATCH 0714/1494] drm/i915: Plumb port through hdcp init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch plumbs port through hdcp init instead of relying on intel_attached_encoder() to return a non-NULL encoder which won't work for MST connectors. Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-13-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-13-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-14-sean@poorly.run #v7 Changes in v5: -Added to the set Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-14-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- drivers/gpu/drm/i915/display/intel_hdcp.c | 11 ++++++----- drivers/gpu/drm/i915/display/intel_hdcp.h | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 0b8200bed0610..c164ad11e617e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -631,7 +631,8 @@ int intel_dp_init_hdcp(struct intel_digital_port *dig_port, return 0; if (!intel_dp_is_edp(intel_dp)) - return intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim); + return intel_hdcp_init(intel_connector, port, + &intel_dp_hdcp_shim); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 7bc8c06f3132b..d0c922f84d53e 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1945,6 +1945,7 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } static int initialize_hdcp_port_data(struct intel_connector *connector, + enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -1952,8 +1953,7 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, struct hdcp_port_data *data = &hdcp->port_data; if (INTEL_GEN(dev_priv) < 12) - data->fw_ddi = - intel_get_mei_fw_ddi_index(intel_attached_encoder(connector)->port); + data->fw_ddi = intel_get_mei_fw_ddi_index(port); else /* * As per ME FW API expectation, for GEN 12+, fw_ddi is filled @@ -2023,14 +2023,14 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv) } } -static void intel_hdcp2_init(struct intel_connector *connector, +static void intel_hdcp2_init(struct intel_connector *connector, enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; int ret; - ret = initialize_hdcp_port_data(connector, shim); + ret = initialize_hdcp_port_data(connector, port, shim); if (ret) { drm_dbg_kms(&i915->drm, "Mei hdcp data init failed\n"); return; @@ -2040,6 +2040,7 @@ static void intel_hdcp2_init(struct intel_connector *connector, } int intel_hdcp_init(struct intel_connector *connector, + enum port port, const struct intel_hdcp_shim *shim) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); @@ -2050,7 +2051,7 @@ int intel_hdcp_init(struct intel_connector *connector, return -EINVAL; if (is_hdcp2_supported(dev_priv)) - intel_hdcp2_init(connector, shim); + intel_hdcp2_init(connector, port, shim); ret = drm_connector_attach_content_protection_property(&connector->base, diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index 86bbaec120cc3..1bbf5b67ed0af 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -22,7 +22,7 @@ enum transcoder; void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); -int intel_hdcp_init(struct intel_connector *connector, +int intel_hdcp_init(struct intel_connector *connector, enum port port, const struct intel_hdcp_shim *hdcp_shim); int intel_hdcp_enable(struct intel_connector *connector, enum transcoder cpu_transcoder, u8 content_type); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 9c3b1ae2cd2bc..c0ea16dae3b3a 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3270,7 +3270,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, intel_hdmi->attached_connector = intel_connector; if (is_hdcp_supported(dev_priv, port)) { - int ret = intel_hdcp_init(intel_connector, + int ret = intel_hdcp_init(intel_connector, port, &intel_hdmi_hdcp_shim); if (ret) drm_dbg_kms(&dev_priv->drm, -- GitLab From 038bac8970ac1c9815eba2914c4cff2b7807ab09 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:39:02 -0400 Subject: [PATCH 0715/1494] drm/i915: Add connector to hdcp_shim->check_link() Currently we derive the connector from digital port in check_link(). For MST, this isn't sufficient since the digital port passed into the function can have multiple connectors downstream. This patch adds connector to the check_link() arguments so we have it when we need it. Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-13-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-14-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-14-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-15-sean@poorly.run #v7 Changes in v4: -Added to the set Changes in v5: -None Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-15-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_display_types.h | 3 ++- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 10 +++++----- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5e01f2f840c97..413b60337a0b7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -318,7 +318,8 @@ struct intel_hdcp_shim { bool enable); /* Ensures the link is still protected */ - bool (*check_link)(struct intel_digital_port *dig_port); + bool (*check_link)(struct intel_digital_port *dig_port, + struct intel_connector *connector); /* Detects panel's hdcp capability. This is optional for HDMI. */ int (*hdcp_capable)(struct intel_digital_port *dig_port, diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index c164ad11e617e..b744253a59246 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -224,7 +224,8 @@ int intel_dp_hdcp_toggle_signalling(struct intel_digital_port *dig_port, } static -bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port) +bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d0c922f84d53e..cd0b24a2ee66f 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -943,7 +943,7 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - if (hdcp->shim->check_link(dig_port)) { + if (hdcp->shim->check_link(dig_port, connector)) { if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { intel_hdcp_update_value(connector, DRM_MODE_CONTENT_PROTECTION_ENABLED, true); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index c0ea16dae3b3a..0978b0d8f4c67 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1546,11 +1546,10 @@ int intel_hdmi_hdcp_toggle_signalling(struct intel_digital_port *dig_port, } static -bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port) +bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_connector *connector = - dig_port->hdmi.attached_connector; enum port port = dig_port->base.port; enum transcoder cpu_transcoder = connector->hdcp.cpu_transcoder; int ret; @@ -1578,13 +1577,14 @@ bool intel_hdmi_hdcp_check_link_once(struct intel_digital_port *dig_port) } static -bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port) +bool intel_hdmi_hdcp_check_link(struct intel_digital_port *dig_port, + struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); int retry; for (retry = 0; retry < 3; retry++) - if (intel_hdmi_hdcp_check_link_once(dig_port)) + if (intel_hdmi_hdcp_check_link_once(dig_port, connector)) return true; drm_err(&i915->drm, "Link check failed\n"); -- GitLab From e38c298fcd19149d337f91640f037a9265bd8c3f Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Wed, 19 Aug 2020 10:31:24 -0400 Subject: [PATCH 0716/1494] drm/mst: Add support for QUERY_STREAM_ENCRYPTION_STATUS MST sideband message Used to query whether an MST stream is encrypted or not. Cc: Lyude Paul <lyude@redhat.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-14-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-15-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-15-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-16-sean@poorly.run #v7 Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-16-sean@poorly.run #v8 Changes in v4: -Added to the set Changes in v5: -None Changes in v6: -Use FIELD_PREP to generate request buffer bitfields (Lyude) -Add mst selftest and dump/decode_sideband_req for QSES (Lyude) Changes in v7: -None Changes in v8: -Reverse the parsing on the hdcp_*x_device_present bits and leave breadcrumb in case this is incorrect (Anshuman) Changes in v8.5: -s/DRM_DEBUG_KMS/drm_dbg_kms/ (Lyude) Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Acked-by: Daniel Vetter <daniel@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819143133.46232-1-sean@poorly.run --- drivers/gpu/drm/drm_dp_mst_topology.c | 150 ++++++++++++++++++ .../drm/selftests/test-drm_dp_mst_helper.c | 17 ++ include/drm/drm_dp_helper.h | 3 + include/drm/drm_dp_mst_helper.h | 44 +++++ 4 files changed, 214 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b23cb2fec3f35..b273d9ba7cbfa 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -20,11 +20,13 @@ * OF THIS SOFTWARE. */ +#include <linux/bitfield.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/random.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/iopoll.h> @@ -423,6 +425,22 @@ drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req, memcpy(&buf[idx], req->u.i2c_write.bytes, req->u.i2c_write.num_bytes); idx += req->u.i2c_write.num_bytes; break; + case DP_QUERY_STREAM_ENC_STATUS: { + const struct drm_dp_query_stream_enc_status *msg; + + msg = &req->u.enc_status; + buf[idx] = msg->stream_id; + idx++; + memcpy(&buf[idx], msg->client_id, sizeof(msg->client_id)); + idx += sizeof(msg->client_id); + buf[idx] = 0; + buf[idx] |= FIELD_PREP(GENMASK(1, 0), msg->stream_event); + buf[idx] |= msg->valid_stream_event ? BIT(2) : 0; + buf[idx] |= FIELD_PREP(GENMASK(4, 3), msg->stream_behavior); + buf[idx] |= msg->valid_stream_behavior ? BIT(5) : 0; + idx++; + } + break; } raw->cur_len = idx; } @@ -551,6 +569,20 @@ drm_dp_decode_sideband_req(const struct drm_dp_sideband_msg_tx *raw, return -ENOMEM; } break; + case DP_QUERY_STREAM_ENC_STATUS: + req->u.enc_status.stream_id = buf[idx++]; + for (i = 0; i < sizeof(req->u.enc_status.client_id); i++) + req->u.enc_status.client_id[i] = buf[idx++]; + + req->u.enc_status.stream_event = FIELD_GET(GENMASK(1, 0), + buf[idx]); + req->u.enc_status.valid_stream_event = FIELD_GET(BIT(2), + buf[idx]); + req->u.enc_status.stream_behavior = FIELD_GET(GENMASK(4, 3), + buf[idx]); + req->u.enc_status.valid_stream_behavior = FIELD_GET(BIT(5), + buf[idx]); + break; } return 0; @@ -629,6 +661,16 @@ drm_dp_dump_sideband_msg_req_body(const struct drm_dp_sideband_msg_req_body *req req->u.i2c_write.num_bytes, req->u.i2c_write.num_bytes, req->u.i2c_write.bytes); break; + case DP_QUERY_STREAM_ENC_STATUS: + P("stream_id=%u client_id=%*ph stream_event=%x " + "valid_event=%d stream_behavior=%x valid_behavior=%d", + req->u.enc_status.stream_id, + (int)ARRAY_SIZE(req->u.enc_status.client_id), + req->u.enc_status.client_id, req->u.enc_status.stream_event, + req->u.enc_status.valid_stream_event, + req->u.enc_status.stream_behavior, + req->u.enc_status.valid_stream_behavior); + break; default: P("???\n"); break; @@ -936,6 +978,42 @@ static bool drm_dp_sideband_parse_power_updown_phy_ack(struct drm_dp_sideband_ms return true; } +static bool +drm_dp_sideband_parse_query_stream_enc_status( + struct drm_dp_sideband_msg_rx *raw, + struct drm_dp_sideband_msg_reply_body *repmsg) +{ + struct drm_dp_query_stream_enc_status_ack_reply *reply; + + reply = &repmsg->u.enc_status; + + reply->stream_id = raw->msg[3]; + + reply->reply_signed = raw->msg[2] & BIT(0); + + /* + * NOTE: It's my impression from reading the spec that the below parsing + * is correct. However I noticed while testing with an HDCP 1.4 display + * through an HDCP 2.2 hub that only bit 3 was set. In that case, I + * would expect both bits to be set. So keep the parsing following the + * spec, but beware reality might not match the spec (at least for some + * configurations). + */ + reply->hdcp_1x_device_present = raw->msg[2] & BIT(4); + reply->hdcp_2x_device_present = raw->msg[2] & BIT(3); + + reply->query_capable_device_present = raw->msg[2] & BIT(5); + reply->legacy_device_present = raw->msg[2] & BIT(6); + reply->unauthorizable_device_present = raw->msg[2] & BIT(7); + + reply->auth_completed = !!(raw->msg[1] & BIT(3)); + reply->encryption_enabled = !!(raw->msg[1] & BIT(4)); + reply->repeater_present = !!(raw->msg[1] & BIT(5)); + reply->state = (raw->msg[1] & GENMASK(7, 6)) >> 6; + + return true; +} + static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, struct drm_dp_sideband_msg_reply_body *msg) { @@ -970,6 +1048,8 @@ static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, return drm_dp_sideband_parse_power_updown_phy_ack(raw, msg); case DP_CLEAR_PAYLOAD_ID_TABLE: return true; /* since there's nothing to parse */ + case DP_QUERY_STREAM_ENC_STATUS: + return drm_dp_sideband_parse_query_stream_enc_status(raw, msg); default: DRM_ERROR("Got unknown reply 0x%02x (%s)\n", msg->req_type, drm_dp_mst_req_type_str(msg->req_type)); @@ -1121,6 +1201,25 @@ static void build_power_updown_phy(struct drm_dp_sideband_msg_tx *msg, msg->path_msg = true; } +static int +build_query_stream_enc_status(struct drm_dp_sideband_msg_tx *msg, u8 stream_id, + u8 *q_id) +{ + struct drm_dp_sideband_msg_req_body req; + + req.req_type = DP_QUERY_STREAM_ENC_STATUS; + req.u.enc_status.stream_id = stream_id; + memcpy(req.u.enc_status.client_id, q_id, + sizeof(req.u.enc_status.client_id)); + req.u.enc_status.stream_event = 0; + req.u.enc_status.valid_stream_event = false; + req.u.enc_status.stream_behavior = 0; + req.u.enc_status.valid_stream_behavior = false; + + drm_dp_encode_sideband_req(&req, msg); + return 0; +} + static int drm_dp_mst_assign_payload_id(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_vcpi *vcpi) { @@ -3153,6 +3252,57 @@ int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, } EXPORT_SYMBOL(drm_dp_send_power_updown_phy); +int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_query_stream_enc_status_ack_reply *status) +{ + struct drm_dp_sideband_msg_tx *txmsg; + u8 nonce[7]; + int len, ret; + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) + return -ENOMEM; + + port = drm_dp_mst_topology_get_port_validated(mgr, port); + if (!port) { + ret = -EINVAL; + goto out_get_port; + } + + get_random_bytes(nonce, sizeof(nonce)); + + /* + * "Source device targets the QUERY_STREAM_ENCRYPTION_STATUS message + * transaction at the MST Branch device directly connected to the + * Source" + */ + txmsg->dst = mgr->mst_primary; + + len = build_query_stream_enc_status(txmsg, port->vcpi.vcpi, nonce); + + drm_dp_queue_down_tx(mgr, txmsg); + + ret = drm_dp_mst_wait_tx_reply(mgr->mst_primary, txmsg); + if (ret < 0) { + goto out; + } else if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) { + drm_dbg_kms(mgr->dev, "query encryption status nak received\n"); + ret = -ENXIO; + goto out; + } + + ret = 0; + memcpy(status, &txmsg->reply.u.enc_status, sizeof(*status)); + +out: + drm_dp_mst_topology_put_port(port); +out_get_port: + kfree(txmsg); + return ret; +} +EXPORT_SYMBOL(drm_dp_send_query_stream_enc_status); + static int drm_dp_create_payload_step1(struct drm_dp_mst_topology_mgr *mgr, int id, struct drm_dp_payload *payload) diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c index bd990d1787657..1d696ec001cff 100644 --- a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c +++ b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c @@ -5,6 +5,8 @@ #define PREFIX_STR "[drm_dp_mst_helper]" +#include <linux/random.h> + #include <drm/drm_dp_mst_helper.h> #include <drm/drm_print.h> @@ -237,6 +239,21 @@ int igt_dp_mst_sideband_msg_req_decode(void *unused) in.u.i2c_write.bytes = data; DO_TEST(); + in.req_type = DP_QUERY_STREAM_ENC_STATUS; + in.u.enc_status.stream_id = 1; + DO_TEST(); + get_random_bytes(in.u.enc_status.client_id, + sizeof(in.u.enc_status.client_id)); + DO_TEST(); + in.u.enc_status.stream_event = 3; + DO_TEST(); + in.u.enc_status.valid_stream_event = 0; + DO_TEST(); + in.u.enc_status.stream_behavior = 3; + DO_TEST(); + in.u.enc_status.valid_stream_behavior = 1; + DO_TEST(); + #undef DO_TEST return 0; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index e47dc22ebf503..e2d2df5e869e2 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1108,6 +1108,9 @@ #define DP_POWER_DOWN_PHY 0x25 #define DP_SINK_EVENT_NOTIFY 0x30 #define DP_QUERY_STREAM_ENC_STATUS 0x38 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_NO_EXIST 0 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_INACTIVE 1 +#define DP_QUERY_STREAM_ENC_STATUS_STATE_ACTIVE 2 /* DP 1.2 MST sideband reply types */ #define DP_SIDEBAND_REPLY_ACK 0x00 diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 8b9eb4db3381c..371eef8798ad1 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -313,6 +313,34 @@ struct drm_dp_remote_i2c_write_ack_reply { u8 port_number; }; +struct drm_dp_query_stream_enc_status_ack_reply { + /* Bit[23:16]- Stream Id */ + u8 stream_id; + + /* Bit[15]- Signed */ + bool reply_signed; + + /* Bit[10:8]- Stream Output Sink Type */ + bool unauthorizable_device_present; + bool legacy_device_present; + bool query_capable_device_present; + + /* Bit[12:11]- Stream Output CP Type */ + bool hdcp_1x_device_present; + bool hdcp_2x_device_present; + + /* Bit[4]- Stream Authentication */ + bool auth_completed; + + /* Bit[3]- Stream Encryption */ + bool encryption_enabled; + + /* Bit[2]- Stream Repeater Function Present */ + bool repeater_present; + + /* Bit[1:0]- Stream State */ + u8 state; +}; #define DRM_DP_MAX_SDP_STREAMS 16 struct drm_dp_allocate_payload { @@ -374,6 +402,15 @@ struct drm_dp_remote_i2c_write { u8 *bytes; }; +struct drm_dp_query_stream_enc_status { + u8 stream_id; + u8 client_id[7]; /* 56-bit nonce */ + u8 stream_event; + bool valid_stream_event; + u8 stream_behavior; + u8 valid_stream_behavior; +}; + /* this covers ENUM_RESOURCES, POWER_DOWN_PHY, POWER_UP_PHY */ struct drm_dp_port_number_req { u8 port_number; @@ -422,6 +459,8 @@ struct drm_dp_sideband_msg_req_body { struct drm_dp_remote_i2c_read i2c_read; struct drm_dp_remote_i2c_write i2c_write; + + struct drm_dp_query_stream_enc_status enc_status; } u; }; @@ -444,6 +483,8 @@ struct drm_dp_sideband_msg_reply_body { struct drm_dp_remote_i2c_read_ack_reply remote_i2c_read_ack; struct drm_dp_remote_i2c_read_nak_reply remote_i2c_read_nack; struct drm_dp_remote_i2c_write_ack_reply remote_i2c_write_ack; + + struct drm_dp_query_stream_enc_status_ack_reply enc_status; } u; }; @@ -808,6 +849,9 @@ drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_port *port); int drm_dp_send_power_updown_phy(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, bool power_up); +int drm_dp_send_query_stream_enc_status(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + struct drm_dp_query_stream_enc_status_ack_reply *status); int __must_check drm_dp_mst_atomic_check(struct drm_atomic_state *state); void drm_dp_mst_get_port_malloc(struct drm_dp_mst_port *port); -- GitLab From da44edbb8429aa5227430609268e3f378f4fe1f7 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:39:04 -0400 Subject: [PATCH 0717/1494] drm/i915: Print HDCP version info for all connectors De-duplicate the HDCP version code for each connector and print it for all connectors. Cc: Juston Li <juston.li@intel.com> Cc: Ramalingam C <ramalingam.c@intel.com> Reviewed-by: Juston Li <juston.li@intel.com> Reviewed-by: Ramalingam C <ramalingam.c@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200227185714.171466-1-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-16-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-16-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-17-sean@poorly.run #v7 Changes in v4: - Added to the set Changes in v5: -Print "No connector support" for hdcp sink capability as well (Ram) Changes in v6: -None Changes in v7: -None Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-17-sean@poorly.run --- .../drm/i915/display/intel_display_debugfs.c | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 65ccf5d6cd399..53a0a3d9a22df 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -601,6 +601,11 @@ static void intel_hdcp_info(struct seq_file *m, { bool hdcp_cap, hdcp2_cap; + if (!intel_connector->hdcp.shim) { + seq_puts(m, "No Connector Support"); + goto out; + } + hdcp_cap = intel_hdcp_capable(intel_connector); hdcp2_cap = intel_hdcp2_capable(intel_connector); @@ -612,6 +617,7 @@ static void intel_hdcp_info(struct seq_file *m, if (!hdcp_cap && !hdcp2_cap) seq_puts(m, "None"); +out: seq_puts(m, "\n"); } @@ -628,10 +634,6 @@ static void intel_dp_info(struct seq_file *m, drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, &intel_dp->aux); - if (intel_connector->hdcp.shim) { - seq_puts(m, "\tHDCP version: "); - intel_hdcp_info(m, intel_connector); - } } static void intel_dp_mst_info(struct seq_file *m, @@ -649,10 +651,6 @@ static void intel_hdmi_info(struct seq_file *m, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder); seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio)); - if (intel_connector->hdcp.shim) { - seq_puts(m, "\tHDCP version: "); - intel_hdcp_info(m, intel_connector); - } } static void intel_lvds_info(struct seq_file *m, @@ -708,6 +706,9 @@ static void intel_connector_info(struct seq_file *m, break; } + seq_puts(m, "\tHDCP version: "); + intel_hdcp_info(m, intel_connector); + seq_printf(m, "\tmodes:\n"); list_for_each_entry(mode, &connector->modes, head) intel_seq_print_mode(m, 2, mode); @@ -2037,10 +2038,6 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) if (connector->status != connector_status_connected) return -ENODEV; - /* HDCP is supported by connector */ - if (!intel_connector->hdcp.shim) - return -EINVAL; - seq_printf(m, "%s:%d HDCP version: ", connector->name, connector->base.id); intel_hdcp_info(m, intel_connector); -- GitLab From 1fa0140956e72a47781af74ef704413b31411e95 Mon Sep 17 00:00:00 2001 From: Sean Paul <seanpaul@chromium.org> Date: Tue, 18 Aug 2020 11:39:05 -0400 Subject: [PATCH 0718/1494] drm/i915: Add HDCP 1.4 support for MST connectors Now that all the groundwork has been laid, we can turn on HDCP 1.4 over MST. Everything except for toggling the HDCP signalling and HDCP 2.2 support is the same as the DP case, so we'll re-use those callbacks Cc: Juston Li <juston.li@intel.com> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-12-sean@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20191212190230.188505-13-sean@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20200117193103.156821-13-sean@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20200218220242.107265-15-sean@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20200305201236.152307-17-sean@poorly.run #v5 Link: https://patchwork.freedesktop.org/patch/msgid/20200429195502.39919-17-sean@poorly.run #v6 Link: https://patchwork.freedesktop.org/patch/msgid/20200623155907.22961-18-sean@poorly.run #v7 Changes in v2: -Toggle HDCP from encoder disable/enable -Don't disable HDCP on MST connector destroy, leave that for encoder disable, just ensure the check_work routine isn't running any longer Changes in v3: -Place the shim in the new intel_dp_hdcp.c file (Ville) Changes in v4: -Actually use the mst shim for mst connections (Juston) -Use QUERY_STREAM_ENC_STATUS MST message to verify channel is encrypted Changes in v5: -Add sleep on disable signalling to match hdmi delay Changes in v6: -Disable HDCP over MST on GEN12+ since I'm unsure how it should work and I don't have hardware to test it Changes in v7: -Remove hdcp2 shims for MST in favor of skipping hdcp2 init (Ramalingam) Changes in v8: -None Signed-off-by: Ramalingam C <ramalingam.c@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-18-sean@poorly.run --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 66 +++++++++++++++++++- drivers/gpu/drm/i915/display/intel_dp_mst.c | 18 ++++++ drivers/gpu/drm/i915/display/intel_hdcp.c | 2 +- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index b744253a59246..03424d20e9f76 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -7,10 +7,12 @@ */ #include <drm/drm_dp_helper.h> +#include <drm/drm_dp_mst_helper.h> #include <drm/drm_hdcp.h> #include <drm/drm_print.h> #include "intel_display_types.h" +#include "intel_ddi.h" #include "intel_dp.h" #include "intel_hdcp.h" @@ -619,6 +621,65 @@ static const struct intel_hdcp_shim intel_dp_hdcp_shim = { .protocol = HDCP_PROTOCOL_DP, }; +static int +intel_dp_mst_hdcp_toggle_signalling(struct intel_digital_port *dig_port, + enum transcoder cpu_transcoder, + bool enable) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + int ret; + + if (!enable) + usleep_range(6, 60); /* Bspec says >= 6us */ + + ret = intel_ddi_toggle_hdcp_signalling(&dig_port->base, + cpu_transcoder, enable); + if (ret) + drm_dbg_kms(&i915->drm, "%s HDCP signalling failed (%d)\n", + enable ? "Enable" : "Disable", ret); + return ret; +} + +static +bool intel_dp_mst_hdcp_check_link(struct intel_digital_port *dig_port, + struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + struct intel_dp *intel_dp = &dig_port->dp; + struct drm_dp_query_stream_enc_status_ack_reply reply; + int ret; + + if (!intel_dp_hdcp_check_link(dig_port, connector)) + return false; + + ret = drm_dp_send_query_stream_enc_status(&intel_dp->mst_mgr, + connector->port, &reply); + if (ret) { + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] failed QSES ret=%d\n", + connector->base.base.id, connector->base.name, ret); + return false; + } + + return reply.auth_completed && reply.encryption_enabled; +} + +static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = { + .write_an_aksv = intel_dp_hdcp_write_an_aksv, + .read_bksv = intel_dp_hdcp_read_bksv, + .read_bstatus = intel_dp_hdcp_read_bstatus, + .repeater_present = intel_dp_hdcp_repeater_present, + .read_ri_prime = intel_dp_hdcp_read_ri_prime, + .read_ksv_ready = intel_dp_hdcp_read_ksv_ready, + .read_ksv_fifo = intel_dp_hdcp_read_ksv_fifo, + .read_v_prime_part = intel_dp_hdcp_read_v_prime_part, + .toggle_signalling = intel_dp_mst_hdcp_toggle_signalling, + .check_link = intel_dp_mst_hdcp_check_link, + .hdcp_capable = intel_dp_hdcp_capable, + + .protocol = HDCP_PROTOCOL_DP, +}; + int intel_dp_init_hdcp(struct intel_digital_port *dig_port, struct intel_connector *intel_connector) { @@ -631,7 +692,10 @@ int intel_dp_init_hdcp(struct intel_digital_port *dig_port, if (!is_hdcp_supported(dev_priv, port)) return 0; - if (!intel_dp_is_edp(intel_dp)) + if (intel_connector->mst_port) + return intel_hdcp_init(intel_connector, port, + &intel_dp_mst_hdcp_shim); + else if (!intel_dp_is_edp(intel_dp)) return intel_hdcp_init(intel_connector, port, &intel_dp_hdcp_shim); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index b97b2918d8029..b6424bf5d544d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -37,6 +37,7 @@ #include "intel_dp.h" #include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_hdcp.h" static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state, @@ -352,6 +353,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, drm_dbg_kms(&i915->drm, "active links %d\n", intel_dp->active_mst_links); + intel_hdcp_disable(intel_mst->connector); + drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); @@ -556,6 +559,13 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, if (pipe_config->has_audio) intel_audio_codec_enable(encoder, pipe_config, conn_state); + + /* Enable hdcp if it's desired */ + if (conn_state->content_protection == + DRM_MODE_CONTENT_PROTECTION_DESIRED) + intel_hdcp_enable(to_intel_connector(conn_state->connector), + pipe_config->cpu_transcoder, + (u8)conn_state->hdcp_content_type); } static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, @@ -799,6 +809,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo intel_attach_force_audio_property(connector); intel_attach_broadcast_rgb_property(connector); + + /* TODO: Figure out how to make HDCP work on GEN12+ */ + if (INTEL_GEN(dev_priv) < 12) { + ret = intel_dp_init_hdcp(dig_port, intel_connector); + if (ret) + DRM_DEBUG_KMS("HDCP init failed, skipping.\n"); + } + /* * Reuse the prop from the SST connector because we're * not allowed to create new props after device registration. diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index cd0b24a2ee66f..5492076d1ae09 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2050,7 +2050,7 @@ int intel_hdcp_init(struct intel_connector *connector, if (!shim) return -EINVAL; - if (is_hdcp2_supported(dev_priv)) + if (is_hdcp2_supported(dev_priv) && !connector->mst_port) intel_hdcp2_init(connector, port, shim); ret = -- GitLab From f7ec68b341dbd5da13d4c65ce444dcd605f1c42e Mon Sep 17 00:00:00 2001 From: Dinghao Liu <dinghao.liu@zju.edu.cn> Date: Wed, 19 Aug 2020 16:22:28 +0800 Subject: [PATCH 0719/1494] drm/crc-debugfs: Fix memleak in crc_control_write When verify_crc_source() fails, source needs to be freed. However, current code is returning directly and ends up leaking memory. Fixes: d5cc15a0c66e ("drm: crc: Introduce verify_crc_source callback") Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [danvet: change Fixes: tag per Laurent's review] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819082228.26847-1-dinghao.liu@zju.edu.cn --- drivers/gpu/drm/drm_debugfs_crc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 5d67a41f7c3a8..3dd70d813f694 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -144,8 +144,10 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf, source[len - 1] = '\0'; ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt); - if (ret) + if (ret) { + kfree(source); return ret; + } spin_lock_irq(&crc->lock); -- GitLab From adb48b26985686f93f20ca71c16c067d790e7af3 Mon Sep 17 00:00:00 2001 From: Sam McNally <sammc@chromium.org> Date: Mon, 27 Jul 2020 16:03:37 +1000 Subject: [PATCH 0720/1494] drm/dp_mst: Support remote i2c writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For DP MST outputs, the i2c device currently only supports transfers that can be implemented using remote i2c reads. Such transfers must consist of zero or more write transactions followed by one read transaction. DDC/CI commands require standalone write transactions and hence aren't supported. Since each remote i2c write is handled as a separate transfer, remote i2c writes can support transfers consisting of write transactions, where all but the last have I2C_M_STOP set. According to the DDC/CI 1.1 standard, DDC/CI commands only require a single write or read transaction in a transfer, so this is sufficient. For i2c transfers meeting the above criteria, generate and send a remote i2c write message for each transaction. Add the trivial remote i2c write reply parsing support so remote i2c write acks bubble up correctly. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/37 Signed-off-by: Sam McNally <sammc@chromium.org> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200727160225.1.I4e95a534de051551cd143e6cb83d4c5a9b0ad1cd@changeid --- drivers/gpu/drm/drm_dp_mst_topology.c | 106 ++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b23cb2fec3f35..166405d4c536e 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -961,6 +961,8 @@ static bool drm_dp_sideband_parse_reply(struct drm_dp_sideband_msg_rx *raw, return drm_dp_sideband_parse_remote_dpcd_write(raw, msg); case DP_REMOTE_I2C_READ: return drm_dp_sideband_parse_remote_i2c_read_ack(raw, msg); + case DP_REMOTE_I2C_WRITE: + return true; /* since there's nothing to parse */ case DP_ENUM_PATH_RESOURCES: return drm_dp_sideband_parse_enum_path_resources_ack(raw, msg); case DP_ALLOCATE_PAYLOAD: @@ -5327,29 +5329,29 @@ static bool remote_i2c_read_ok(const struct i2c_msg msgs[], int num) msgs[num - 1].len <= 0xff; } -/* I2C device */ -static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, - int num) +static bool remote_i2c_write_ok(const struct i2c_msg msgs[], int num) +{ + int i; + + for (i = 0; i < num - 1; i++) { + if (msgs[i].flags & I2C_M_RD || !(msgs[i].flags & I2C_M_STOP) || + msgs[i].len > 0xff) + return false; + } + + return !(msgs[num - 1].flags & I2C_M_RD) && msgs[num - 1].len <= 0xff; +} + +static int drm_dp_mst_i2c_read(struct drm_dp_mst_branch *mstb, + struct drm_dp_mst_port *port, + struct i2c_msg *msgs, int num) { - struct drm_dp_aux *aux = adapter->algo_data; - struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux); - struct drm_dp_mst_branch *mstb; struct drm_dp_mst_topology_mgr *mgr = port->mgr; unsigned int i; struct drm_dp_sideband_msg_req_body msg; struct drm_dp_sideband_msg_tx *txmsg = NULL; int ret; - mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); - if (!mstb) - return -EREMOTEIO; - - if (!remote_i2c_read_ok(msgs, num)) { - DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n"); - ret = -EIO; - goto out; - } - memset(&msg, 0, sizeof(msg)); msg.req_type = DP_REMOTE_I2C_READ; msg.u.i2c_read.num_transactions = num - 1; @@ -5390,6 +5392,78 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs } out: kfree(txmsg); + return ret; +} + +static int drm_dp_mst_i2c_write(struct drm_dp_mst_branch *mstb, + struct drm_dp_mst_port *port, + struct i2c_msg *msgs, int num) +{ + struct drm_dp_mst_topology_mgr *mgr = port->mgr; + unsigned int i; + struct drm_dp_sideband_msg_req_body msg; + struct drm_dp_sideband_msg_tx *txmsg = NULL; + int ret; + + txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); + if (!txmsg) { + ret = -ENOMEM; + goto out; + } + for (i = 0; i < num; i++) { + memset(&msg, 0, sizeof(msg)); + msg.req_type = DP_REMOTE_I2C_WRITE; + msg.u.i2c_write.port_number = port->port_num; + msg.u.i2c_write.write_i2c_device_id = msgs[i].addr; + msg.u.i2c_write.num_bytes = msgs[i].len; + msg.u.i2c_write.bytes = msgs[i].buf; + + memset(txmsg, 0, sizeof(*txmsg)); + txmsg->dst = mstb; + + drm_dp_encode_sideband_req(&msg, txmsg); + drm_dp_queue_down_tx(mgr, txmsg); + + ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); + if (ret > 0) { + if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) { + ret = -EREMOTEIO; + goto out; + } + } else { + goto out; + } + } + ret = num; +out: + kfree(txmsg); + return ret; +} + +/* I2C device */ +static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg *msgs, int num) +{ + struct drm_dp_aux *aux = adapter->algo_data; + struct drm_dp_mst_port *port = + container_of(aux, struct drm_dp_mst_port, aux); + struct drm_dp_mst_branch *mstb; + struct drm_dp_mst_topology_mgr *mgr = port->mgr; + int ret; + + mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); + if (!mstb) + return -EREMOTEIO; + + if (remote_i2c_read_ok(msgs, num)) { + ret = drm_dp_mst_i2c_read(mstb, port, msgs, num); + } else if (remote_i2c_write_ok(msgs, num)) { + ret = drm_dp_mst_i2c_write(mstb, port, msgs, num); + } else { + DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n"); + ret = -EIO; + } + drm_dp_mst_topology_put_mstb(mstb); return ret; } -- GitLab From 0e09c4fa72f9837ea8d78cb40ab0b52ff3252ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 28 Apr 2020 20:19:39 +0300 Subject: [PATCH 0721/1494] drm: Nuke mode->private_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last two uses of mode->private_flags (in i915 and gma500) are now gone. So let's remove mode->private_flags entirely. v2: Drop the earlier int->u8 conversion CC: Sam Ravnborg <sam@ravnborg.org> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200428171940.19552-16-ville.syrjala@linux.intel.com Reviewed-by: Emil Velikov <emil.velikov@collabora.com> --- include/drm/drm_modes.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index eee3c9de6c4f9..7d686f9a29bfa 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -349,16 +349,6 @@ struct drm_display_mode { */ u8 type; - /** - * @private_flags: - * - * Driver private flags. private_flags can only be used for mode - * objects passed to drivers in modeset operations. It shouldn't be used - * by atomic drivers since they can store any additional data by - * subclassing state structures. - */ - int private_flags; - /** * @head: * -- GitLab From 8445e2c54c257e92084a451a0f20d6a7f3f9fa34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 28 Apr 2020 20:19:40 +0300 Subject: [PATCH 0722/1494] drm: Replace mode->export_head with a boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to shrink drm_display_mode below the magic two cacheline mark in 64bit we need to shrink it by another 8 bytes. The easiest thing to eliminate is the 'export_head' list head which is only used during the getconnector ioctl to temporarly track which modes on the connector's mode list are to be exposed and which are to remain hidden. We can simply replace the list head with a boolean which we use to tag the modes that are to be exposed. If we make sure to clear the tags after we're done with them we don't even need an extra loop over the modes to reset the tags at the start of the getconnector ioctl. Conveniently we already have a hole for the boolean left behind by the removal of mode->private_flags. The final size of the struct is now 112 bytes on 32bit and 120 bytes on 64bit. Another alternative would be a temp bitmask so we wouldn't have to have anything in the mode struct itself. The main issue is how large of a bitmask do we need? I guess we could allocate it dynamically but that means an extra kcalloc() and an extra loop through the modes to count them first (or grow the bitmask with krealloc() as needed). CC: Sam Ravnborg <sam@ravnborg.org> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Emil Velikov <emil.l.velikov@gmail.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200428171940.19552-17-ville.syrjala@linux.intel.com Reviewed-by: Emil Velikov <emil.velikov@collabora.com> --- drivers/gpu/drm/drm_connector.c | 45 +++++++++++++++++++++++---------- include/drm/drm_modes.h | 22 ++++++++-------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 3d48ad1c36823..717c4e7271b04 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -2289,7 +2289,7 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode, - const struct list_head *export_list, + const struct list_head *modes, const struct drm_file *file_priv) { /* @@ -2305,15 +2305,17 @@ drm_mode_expose_to_userspace(const struct drm_display_mode *mode, * while preparing the list of user-modes. */ if (!file_priv->aspect_ratio_allowed) { - struct drm_display_mode *mode_itr; + const struct drm_display_mode *mode_itr; - list_for_each_entry(mode_itr, export_list, export_head) - if (drm_mode_match(mode_itr, mode, + list_for_each_entry(mode_itr, modes, head) { + if (mode_itr->expose_to_userspace && + drm_mode_match(mode_itr, mode, DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_CLOCK | DRM_MODE_MATCH_FLAGS | DRM_MODE_MATCH_3D_FLAGS)) return false; + } } return true; @@ -2333,7 +2335,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_mode_modeinfo u_mode; struct drm_mode_modeinfo __user *mode_ptr; uint32_t __user *encoder_ptr; - LIST_HEAD(export_list); if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EOPNOTSUPP; @@ -2377,25 +2378,30 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->connection = connector->status; /* delayed so we get modes regardless of pre-fill_modes state */ - list_for_each_entry(mode, &connector->modes, head) - if (drm_mode_expose_to_userspace(mode, &export_list, + list_for_each_entry(mode, &connector->modes, head) { + WARN_ON(mode->expose_to_userspace); + + if (drm_mode_expose_to_userspace(mode, &connector->modes, file_priv)) { - list_add_tail(&mode->export_head, &export_list); + mode->expose_to_userspace = true; mode_count++; } + } /* * This ioctl is called twice, once to determine how much space is * needed, and the 2nd time to fill it. - * The modes that need to be exposed to the user are maintained in the - * 'export_list'. When the ioctl is called first time to determine the, - * space, the export_list gets filled, to find the no.of modes. In the - * 2nd time, the user modes are filled, one by one from the export_list. */ if ((out_resp->count_modes >= mode_count) && mode_count) { copied = 0; mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; - list_for_each_entry(mode, &export_list, export_head) { + list_for_each_entry(mode, &connector->modes, head) { + if (!mode->expose_to_userspace) + continue; + + /* Clear the tag for the next time around */ + mode->expose_to_userspace = false; + drm_mode_convert_to_umode(&u_mode, mode); /* * Reset aspect ratio flags of user-mode, if modes with @@ -2406,13 +2412,26 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, if (copy_to_user(mode_ptr + copied, &u_mode, sizeof(u_mode))) { ret = -EFAULT; + + /* + * Clear the tag for the rest of + * the modes for the next time around. + */ + list_for_each_entry_continue(mode, &connector->modes, head) + mode->expose_to_userspace = false; + mutex_unlock(&dev->mode_config.mutex); goto out; } copied++; } + } else { + /* Clear the tag for the next time around */ + list_for_each_entry(mode, &connector->modes, head) + mode->expose_to_userspace = false; } + out_resp->count_modes = mode_count; mutex_unlock(&dev->mode_config.mutex); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 7d686f9a29bfa..cdf2a299ccd43 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -350,24 +350,22 @@ struct drm_display_mode { u8 type; /** - * @head: + * @expose_to_userspace: * - * struct list_head for mode lists. + * Indicates whether the mode is to be exposed to the userspace. + * This is to maintain a set of exposed modes while preparing + * user-mode's list in drm_mode_getconnector ioctl. The purpose of + * this only lies in the ioctl function, and is not to be used + * outside the function. */ - struct list_head head; + bool expose_to_userspace; /** - * @export_head: + * @head: * - * struct list_head for modes to be exposed to the userspace. - * This is to maintain a list of exposed modes while preparing - * user-mode's list in drm_mode_getconnector ioctl. The purpose of this - * list_head only lies in the ioctl function, and is not expected to be - * used outside the function. - * Once used, the stale pointers are not reset, but left as it is, to - * avoid overhead of protecting it by mode_config.mutex. + * struct list_head for mode lists. */ - struct list_head export_head; + struct list_head head; /** * @name: -- GitLab From c08503ec03dbe338c01ee4867b6dea026a78f6d4 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn <rikard.falkeborn@gmail.com> Date: Sun, 30 Aug 2020 23:17:41 +0200 Subject: [PATCH 0723/1494] drm/gma500: Constify static structs The only usage of these is to assign their address to the fbops field in the fb_info struct, which is a const pointer. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200830211741.17326-1-rikard.falkeborn@gmail.com --- drivers/gpu/drm/gma500/framebuffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index da02d7e8a8f55..54d9876b5305a 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -164,7 +164,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) return 0; } -static struct fb_ops psbfb_ops = { +static const struct fb_ops psbfb_ops = { .owner = THIS_MODULE, DRM_FB_HELPER_DEFAULT_OPS, .fb_setcolreg = psbfb_setcolreg, @@ -175,7 +175,7 @@ static struct fb_ops psbfb_ops = { .fb_sync = psbfb_sync, }; -static struct fb_ops psbfb_roll_ops = { +static const struct fb_ops psbfb_roll_ops = { .owner = THIS_MODULE, DRM_FB_HELPER_DEFAULT_OPS, .fb_setcolreg = psbfb_setcolreg, @@ -186,7 +186,7 @@ static struct fb_ops psbfb_roll_ops = { .fb_mmap = psbfb_mmap, }; -static struct fb_ops psbfb_unaccel_ops = { +static const struct fb_ops psbfb_unaccel_ops = { .owner = THIS_MODULE, DRM_FB_HELPER_DEFAULT_OPS, .fb_setcolreg = psbfb_setcolreg, -- GitLab From 1bc371cd0ec907bab870cacb6e898105f9c41dc8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 18 Aug 2020 09:25:10 +0200 Subject: [PATCH 0724/1494] drm/virtio: fix unblank When going through a disable/enable cycle without changing the framebuffer the optimization added by commit 3954ff10e06e ("drm/virtio: skip set_scanout if framebuffer didn't change") causes the screen stay blank. Add a bool to force an update to fix that. v2: use drm_atomic_crtc_needs_modeset() (Daniel). Cc: 1882851@bugs.launchpad.net Fixes: 3954ff10e06e ("drm/virtio: skip set_scanout if framebuffer didn't change") Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Tested-by: Jiri Slaby <jirislaby@kernel.org> Tested-by: Diego Viola <diego.viola@gmail.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20200818072511.6745-2-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 11 +++++++++++ drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_plane.c | 4 +++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 2c2742b8d6570..ad403325bc94b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -123,6 +123,17 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { + struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + + /* + * virtio-gpu can't do modeset and plane update operations + * independent from each other. So the actual modeset happens + * in the plane update callback, and here we just check + * whenever we must force the modeset. + */ + if (drm_atomic_crtc_needs_modeset(crtc->state)) { + output->needs_modeset = true; + } } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9a8bfbf85412c..d189db3a84589 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -145,6 +145,7 @@ struct virtio_gpu_output { int cur_x; int cur_y; bool enabled; + bool needs_modeset; }; #define drm_crtc_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, crtc) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 52d24179bcecc..65757409d9ed1 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -163,7 +163,9 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, plane->state->src_w != old_state->src_w || plane->state->src_h != old_state->src_h || plane->state->src_x != old_state->src_x || - plane->state->src_y != old_state->src_y) { + plane->state->src_y != old_state->src_y || + output->needs_modeset) { + output->needs_modeset = false; DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", bo->hw_res_handle, plane->state->crtc_w, plane->state->crtc_h, -- GitLab From 1174c8a0f33c1e5c442ac40381fe124248c08b3a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 18 Aug 2020 09:25:11 +0200 Subject: [PATCH 0725/1494] drm/virtio: drop virtio_gpu_output->enabled Not needed, already tracked by drm_crtc_state->active. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20200818072511.6745-3-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 4 ---- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 - drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index ad403325bc94b..effea07abe62d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -97,9 +97,6 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { - struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); - - output->enabled = true; } static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, @@ -111,7 +108,6 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_notify(vgdev); - output->enabled = false; } static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index d189db3a84589..a52b7a39f286e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -144,7 +144,6 @@ struct virtio_gpu_output { struct edid *edid; int cur_x; int cur_y; - bool enabled; bool needs_modeset; }; #define drm_crtc_to_virtio_gpu_output(x) \ diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 65757409d9ed1..6a311cd934403 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -142,7 +142,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, if (WARN_ON(!output)) return; - if (!plane->state->fb || !output->enabled) { + if (!plane->state->fb || !output->crtc.state->active) { DRM_DEBUG("nofb\n"); virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, plane->state->src_w >> 16, -- GitLab From e44cd6bc95a145418442f91045828c8fc49112bd Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Sun, 30 Aug 2020 21:17:13 -0700 Subject: [PATCH 0726/1494] dma-buf: fix kernel-doc warning in dma-fence.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add @cookie to dma_fence_end_signalling() to prevent kernel-doc warning in drivers/dma-buf/dma-fence.c: ../drivers/dma-buf/dma-fence.c:291: warning: Function parameter or member 'cookie' not described in 'dma_fence_end_signalling' Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Gustavo Padovan <gustavo@padovan.org> Cc: Christian König <christian.koenig@amd.com> Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Acked-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/388527/ Signed-off-by: Christian König <christian.koenig@amd.com> --- drivers/dma-buf/dma-fence.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 43624b4ee13d2..7475e09b06808 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -283,6 +283,7 @@ EXPORT_SYMBOL(dma_fence_begin_signalling); /** * dma_fence_end_signalling - end a critical DMA fence signalling section + * @cookie: opaque cookie from dma_fence_begin_signalling() * * Closes a critical section annotation opened by dma_fence_begin_signalling(). */ -- GitLab From 0f50257f5348751bf5b93d052885de23b2367cd2 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Sun, 30 Aug 2020 21:16:55 -0700 Subject: [PATCH 0727/1494] dma-buf: fix kernel-doc warning in <linux/dma-buf.h> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix kernel-doc warning in <linux/dma-buf.h>: ../include/linux/dma-buf.h:330: warning: Function parameter or member 'name_lock' not described in 'dma_buf' Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: Gustavo Padovan <gustavo@padovan.org> Cc: Christian König <christian.koenig@amd.com> Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/388523/ Signed-off-by: Christian König <christian.koenig@amd.com> --- include/linux/dma-buf.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index a2ca294eaebe7..957b398d30e5d 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -283,6 +283,7 @@ struct dma_buf_ops { * @exp_name: name of the exporter; useful for debugging. * @name: userspace-provided name; useful for accounting and debugging, * protected by @resv. + * @name_lock: spinlock to protect name access * @owner: pointer to exporter module; used for refcounting when exporter is a * kernel module. * @list_node: node for dma_buf accounting and debugging. @@ -311,7 +312,7 @@ struct dma_buf { void *vmap_ptr; const char *exp_name; const char *name; - spinlock_t name_lock; /* spinlock to protect name access */ + spinlock_t name_lock; struct module *owner; struct list_head list_node; void *priv; -- GitLab From d575ee11317f3327d6a1d899e56295424f53f3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 21 Aug 2020 17:29:22 +0200 Subject: [PATCH 0728/1494] drm/ttm: make sure that we always zero init mem.bus v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are trying to remove the io_lru handling and depend on zero init base, offset and addr here. v2: init addr as well Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/388642/ --- drivers/gpu/drm/ttm/ttm_bo.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e3931e515906e..772c640a6046a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -650,6 +650,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, evict_mem.mm_node = NULL; evict_mem.bus.io_reserved_vm = false; evict_mem.bus.io_reserved_count = 0; + evict_mem.bus.base = 0; + evict_mem.bus.offset = 0; + evict_mem.bus.addr = NULL; ret = ttm_bo_mem_space(bo, &placement, &evict_mem, ctx); if (ret) { @@ -1084,6 +1087,9 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, mem.page_alignment = bo->mem.page_alignment; mem.bus.io_reserved_vm = false; mem.bus.io_reserved_count = 0; + mem.bus.base = 0; + mem.bus.offset = 0; + mem.bus.addr = NULL; mem.mm_node = NULL; /* @@ -1243,6 +1249,9 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->mem.page_alignment = page_alignment; bo->mem.bus.io_reserved_vm = false; bo->mem.bus.io_reserved_count = 0; + bo->mem.bus.base = 0; + bo->mem.bus.offset = 0; + bo->mem.bus.addr = NULL; bo->moving = NULL; bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); bo->acc_size = acc_size; -- GitLab From 141b15e59175aa174ca1f7596188bd15a7ca17ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 21 Aug 2020 16:06:50 +0200 Subject: [PATCH 0729/1494] drm/nouveau: move io_reserve_lru handling into the driver v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While working on TTM cleanups I've found that the io_reserve_lru used by Nouveau is actually not working at all. In general we should remove driver specific handling from the memory management, so this patch moves the io_reserve_lru handling into Nouveau instead. v2: don't call ttm_bo_unmap_virtual in nouveau_ttm_io_mem_reserve v3: rebased and use both base and offset in the check v4: fix small typos and test the patch v5: rebased and keep the mem.bus init in TTM. Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/388643/ --- drivers/gpu/drm/nouveau/nouveau_bo.c | 101 ++++++++++++++++++++------ drivers/gpu/drm/nouveau/nouveau_bo.h | 3 + drivers/gpu/drm/nouveau/nouveau_drv.h | 2 + drivers/gpu/drm/nouveau/nouveau_ttm.c | 44 ++++++++++- 4 files changed, 127 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 9140387f30dcb..f74988771ed84 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -137,6 +137,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) struct nouveau_bo *nvbo = nouveau_bo(bo); WARN_ON(nvbo->pin_refcnt > 0); + nouveau_bo_del_io_reserve_lru(bo); nv10_bo_put_tile_region(dev, nvbo->tile, NULL); /* @@ -304,6 +305,7 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags, nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; nouveau_bo_placement_set(nvbo, flags, 0); + INIT_LIST_HEAD(&nvbo->io_reserve_lru); ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type, &nvbo->placement, align >> PAGE_SHIFT, false, @@ -574,6 +576,26 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) PAGE_SIZE, DMA_FROM_DEVICE); } +void nouveau_bo_add_io_reserve_lru(struct ttm_buffer_object *bo) +{ + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + + mutex_lock(&drm->ttm.io_reserve_mutex); + list_move_tail(&nvbo->io_reserve_lru, &drm->ttm.io_reserve_lru); + mutex_unlock(&drm->ttm.io_reserve_mutex); +} + +void nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object *bo) +{ + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + + mutex_lock(&drm->ttm.io_reserve_mutex); + list_del_init(&nvbo->io_reserve_lru); + mutex_unlock(&drm->ttm.io_reserve_mutex); +} + int nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, bool no_wait_gpu) @@ -888,6 +910,8 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, if (bo->destroy != nouveau_bo_del_ttm) return; + nouveau_bo_del_io_reserve_lru(bo); + if (mem && new_reg->mem_type != TTM_PL_SYSTEM && mem->mem.page == nvbo->page) { list_for_each_entry(vma, &nvbo->vma_list, head) { @@ -1018,17 +1042,42 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) filp->private_data); } +static void +nouveau_ttm_io_mem_free_locked(struct nouveau_drm *drm, + struct ttm_resource *reg) +{ + struct nouveau_mem *mem = nouveau_mem(reg); + + if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) { + switch (reg->mem_type) { + case TTM_PL_TT: + if (mem->kind) + nvif_object_unmap_handle(&mem->mem.object); + break; + case TTM_PL_VRAM: + nvif_object_unmap_handle(&mem->mem.object); + break; + default: + break; + } + } +} + static int nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) { struct nouveau_drm *drm = nouveau_bdev(bdev); struct nvkm_device *device = nvxx_device(&drm->client.device); struct nouveau_mem *mem = nouveau_mem(reg); + int ret; + mutex_lock(&drm->ttm.io_reserve_mutex); +retry: switch (reg->mem_type) { case TTM_PL_SYSTEM: /* System memory */ - return 0; + ret = 0; + goto out; case TTM_PL_TT: #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { @@ -1037,9 +1086,12 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) reg->bus.is_iomem = !drm->agp.cma; } #endif - if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || !mem->kind) + if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || + !mem->kind) { /* untiled */ + ret = 0; break; + } fallthrough; /* tiled memory */ case TTM_PL_VRAM: reg->bus.offset = reg->start << PAGE_SHIFT; @@ -1052,7 +1104,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) } args; u64 handle, length; u32 argc = 0; - int ret; switch (mem->mem.object.oclass) { case NVIF_CLASS_MEM_NV50: @@ -1078,39 +1129,47 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) &handle, &length); if (ret != 1) { if (WARN_ON(ret == 0)) - return -EINVAL; - return ret; + ret = -EINVAL; + goto out; } reg->bus.base = 0; reg->bus.offset = handle; + ret = 0; } break; default: - return -EINVAL; + ret = -EINVAL; } - return 0; + +out: + if (ret == -ENOSPC) { + struct nouveau_bo *nvbo; + + nvbo = list_first_entry_or_null(&drm->ttm.io_reserve_lru, + typeof(*nvbo), + io_reserve_lru); + if (nvbo) { + list_del_init(&nvbo->io_reserve_lru); + drm_vma_node_unmap(&nvbo->bo.base.vma_node, + bdev->dev_mapping); + nouveau_ttm_io_mem_free_locked(drm, &nvbo->bo.mem); + goto retry; + } + + } + mutex_unlock(&drm->ttm.io_reserve_mutex); + return ret; } static void nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_resource *reg) { struct nouveau_drm *drm = nouveau_bdev(bdev); - struct nouveau_mem *mem = nouveau_mem(reg); - if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) { - switch (reg->mem_type) { - case TTM_PL_TT: - if (mem->kind) - nvif_object_unmap_handle(&mem->mem.object); - break; - case TTM_PL_VRAM: - nvif_object_unmap_handle(&mem->mem.object); - break; - default: - break; - } - } + mutex_lock(&drm->ttm.io_reserve_mutex); + nouveau_ttm_io_mem_free_locked(drm, reg); + mutex_unlock(&drm->ttm.io_reserve_mutex); } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index aecb7481df0da..ae90aca33fefd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -18,6 +18,7 @@ struct nouveau_bo { bool force_coherent; struct ttm_bo_kmap_obj kmap; struct list_head head; + struct list_head io_reserve_lru; /* protected by ttm_bo_reserve() */ struct drm_file *reserved_by; @@ -96,6 +97,8 @@ int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, bool no_wait_gpu); void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo); void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo); +void nouveau_bo_add_io_reserve_lru(struct ttm_buffer_object *bo); +void nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object *bo); /* TODO: submit equivalent to TTM generic API upstream? */ static inline void __iomem * diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index f63ac72aa556f..26a2c1090045e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -164,6 +164,8 @@ struct nouveau_drm { int type_vram; int type_host[2]; int type_ncoh[2]; + struct mutex io_reserve_mutex; + struct list_head io_reserve_lru; } ttm; /* GEM interface support */ diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 53c6f88273228..a62f37b1131ca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -123,13 +123,51 @@ const struct ttm_resource_manager_func nv04_gart_manager = { .free = nouveau_manager_del, }; +static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct ttm_buffer_object *bo = vma->vm_private_data; + pgprot_t prot; + vm_fault_t ret; + + ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret; + + nouveau_bo_del_io_reserve_lru(bo); + + prot = vm_get_page_prot(vma->vm_flags); + ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; + + nouveau_bo_add_io_reserve_lru(bo); + + dma_resv_unlock(bo->base.resv); + + return ret; +} + +static struct vm_operations_struct nouveau_ttm_vm_ops = { + .fault = nouveau_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +}; + int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); + int ret; - return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); + ret = ttm_bo_mmap(filp, vma, &drm->ttm.bdev); + if (ret) + return ret; + + vma->vm_ops = &nouveau_ttm_vm_ops; + return 0; } static int @@ -173,7 +211,6 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) } man->func = &nouveau_vram_manager; - man->use_io_reserve_lru = true; ttm_resource_manager_init(man, drm->gem.vram_available >> PAGE_SHIFT); @@ -339,6 +376,9 @@ nouveau_ttm_init(struct nouveau_drm *drm) return ret; } + mutex_init(&drm->ttm.io_reserve_mutex); + INIT_LIST_HEAD(&drm->ttm.io_reserve_lru); + NV_INFO(drm, "VRAM: %d MiB\n", (u32)(drm->gem.vram_available >> 20)); NV_INFO(drm, "GART: %d MiB\n", (u32)(drm->gem.gart_available >> 20)); return 0; -- GitLab From fe662d846c957c8861ade7170115e88f6e6e5fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <ckoenig.leichtzumerken@gmail.com> Date: Mon, 30 Sep 2019 15:12:54 +0200 Subject: [PATCH 0730/1494] drm/ttm: remove io_reserve_lru handling v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is not used any more. v2: keep the NULL checks in TTM. v3: remove unused variable Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/388646/ --- drivers/gpu/drm/ttm/ttm_bo.c | 34 +-------- drivers/gpu/drm/ttm/ttm_bo_util.c | 117 +++-------------------------- drivers/gpu/drm/ttm/ttm_bo_vm.c | 39 +++------- drivers/gpu/drm/ttm/ttm_resource.c | 3 - include/drm/ttm/ttm_bo_api.h | 1 - include/drm/ttm/ttm_bo_driver.h | 5 -- include/drm/ttm/ttm_resource.h | 16 ---- 7 files changed, 24 insertions(+), 191 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 772c640a6046a..89d8ab6edd40f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -263,11 +263,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_resource_manager *new_man = ttm_manager_type(bdev, mem->mem_type); int ret; - ret = ttm_mem_io_lock(old_man, true); - if (unlikely(ret != 0)) - goto out_err; - ttm_bo_unmap_virtual_locked(bo); - ttm_mem_io_unlock(old_man); + ttm_bo_unmap_virtual(bo); /* * Create and bind a ttm if required. @@ -538,7 +534,6 @@ static void ttm_bo_release(struct kref *kref) struct ttm_buffer_object *bo = container_of(kref, struct ttm_buffer_object, kref); struct ttm_bo_device *bdev = bo->bdev; - struct ttm_resource_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); size_t acc_size = bo->acc_size; int ret; @@ -556,9 +551,7 @@ static void ttm_bo_release(struct kref *kref) bo->bdev->driver->release_notify(bo); drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node); - ttm_mem_io_lock(man, false); - ttm_mem_io_free_vm(bo); - ttm_mem_io_unlock(man); + ttm_mem_io_free(bdev, &bo->mem); } if (!dma_resv_test_signaled_rcu(bo->base.resv, true) || @@ -648,8 +641,6 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, evict_mem = bo->mem; evict_mem.mm_node = NULL; - evict_mem.bus.io_reserved_vm = false; - evict_mem.bus.io_reserved_count = 0; evict_mem.bus.base = 0; evict_mem.bus.offset = 0; evict_mem.bus.addr = NULL; @@ -1085,8 +1076,6 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; mem.page_alignment = bo->mem.page_alignment; - mem.bus.io_reserved_vm = false; - mem.bus.io_reserved_count = 0; mem.bus.base = 0; mem.bus.offset = 0; mem.bus.addr = NULL; @@ -1238,7 +1227,6 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, INIT_LIST_HEAD(&bo->lru); INIT_LIST_HEAD(&bo->ddestroy); INIT_LIST_HEAD(&bo->swap); - INIT_LIST_HEAD(&bo->io_reserve_lru); bo->bdev = bdev; bo->type = type; bo->num_pages = num_pages; @@ -1247,8 +1235,6 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->mem.num_pages = bo->num_pages; bo->mem.mm_node = NULL; bo->mem.page_alignment = page_alignment; - bo->mem.bus.io_reserved_vm = false; - bo->mem.bus.io_reserved_count = 0; bo->mem.bus.base = 0; bo->mem.bus.offset = 0; bo->mem.bus.addr = NULL; @@ -1554,25 +1540,13 @@ EXPORT_SYMBOL(ttm_bo_device_init); * buffer object vm functions. */ -void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) -{ - struct ttm_bo_device *bdev = bo->bdev; - - drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping); - ttm_mem_io_free_vm(bo); -} - void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_resource_manager *man = ttm_manager_type(bdev, bo->mem.mem_type); - ttm_mem_io_lock(man, false); - ttm_bo_unmap_virtual_locked(bo); - ttm_mem_io_unlock(man); + drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping); + ttm_mem_io_free(bdev, &bo->mem); } - - EXPORT_SYMBOL(ttm_bo_unmap_virtual); int ttm_bo_wait(struct ttm_buffer_object *bo, diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index ee04716b2603d..2c967607d4853 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -91,122 +91,42 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_move_ttm); -int ttm_mem_io_lock(struct ttm_resource_manager *man, bool interruptible) -{ - if (likely(!man->use_io_reserve_lru)) - return 0; - - if (interruptible) - return mutex_lock_interruptible(&man->io_reserve_mutex); - - mutex_lock(&man->io_reserve_mutex); - return 0; -} - -void ttm_mem_io_unlock(struct ttm_resource_manager *man) -{ - if (likely(!man->use_io_reserve_lru)) - return; - - mutex_unlock(&man->io_reserve_mutex); -} - -static int ttm_mem_io_evict(struct ttm_resource_manager *man) -{ - struct ttm_buffer_object *bo; - - bo = list_first_entry_or_null(&man->io_reserve_lru, - struct ttm_buffer_object, - io_reserve_lru); - if (!bo) - return -ENOSPC; - - list_del_init(&bo->io_reserve_lru); - ttm_bo_unmap_virtual_locked(bo); - return 0; -} - int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { - struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); - int ret; - - if (mem->bus.io_reserved_count++) + if (mem->bus.base || mem->bus.offset || mem->bus.addr) return 0; + mem->bus.is_iomem = false; if (!bdev->driver->io_mem_reserve) return 0; - mem->bus.addr = NULL; - mem->bus.offset = 0; - mem->bus.base = 0; - mem->bus.is_iomem = false; -retry: - ret = bdev->driver->io_mem_reserve(bdev, mem); - if (ret == -ENOSPC) { - ret = ttm_mem_io_evict(man); - if (ret == 0) - goto retry; - } - return ret; + return bdev->driver->io_mem_reserve(bdev, mem); } void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_resource *mem) { - if (--mem->bus.io_reserved_count) - return; - - if (!bdev->driver->io_mem_free) + if (!mem->bus.base && !mem->bus.offset && !mem->bus.addr) return; - bdev->driver->io_mem_free(bdev, mem); -} - -int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) -{ - struct ttm_resource_manager *man = ttm_manager_type(bo->bdev, bo->mem.mem_type); - struct ttm_resource *mem = &bo->mem; - int ret; - - if (mem->bus.io_reserved_vm) - return 0; - - ret = ttm_mem_io_reserve(bo->bdev, mem); - if (unlikely(ret != 0)) - return ret; - mem->bus.io_reserved_vm = true; - if (man->use_io_reserve_lru) - list_add_tail(&bo->io_reserve_lru, - &man->io_reserve_lru); - return 0; -} - -void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) -{ - struct ttm_resource *mem = &bo->mem; - - if (!mem->bus.io_reserved_vm) - return; + if (bdev->driver->io_mem_free) + bdev->driver->io_mem_free(bdev, mem); - mem->bus.io_reserved_vm = false; - list_del_init(&bo->io_reserve_lru); - ttm_mem_io_free(bo->bdev, mem); + mem->bus.base = 0; + mem->bus.offset = 0; + mem->bus.addr = NULL; } static int ttm_resource_ioremap(struct ttm_bo_device *bdev, struct ttm_resource *mem, void **virtual) { - struct ttm_resource_manager *man = ttm_manager_type(bdev, mem->mem_type); int ret; void *addr; *virtual = NULL; - (void) ttm_mem_io_lock(man, false); ret = ttm_mem_io_reserve(bdev, mem); - ttm_mem_io_unlock(man); if (ret || !mem->bus.is_iomem) return ret; @@ -222,9 +142,7 @@ static int ttm_resource_ioremap(struct ttm_bo_device *bdev, addr = ioremap(mem->bus.base + mem->bus.offset, bus_size); if (!addr) { - (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); - ttm_mem_io_unlock(man); return -ENOMEM; } } @@ -236,15 +154,9 @@ static void ttm_resource_iounmap(struct ttm_bo_device *bdev, struct ttm_resource *mem, void *virtual) { - struct ttm_resource_manager *man; - - man = ttm_manager_type(bdev, mem->mem_type); - if (virtual && mem->bus.addr == NULL) iounmap(virtual); - (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); - ttm_mem_io_unlock(man); } static int ttm_copy_io_page(void *dst, void *src, unsigned long page) @@ -458,7 +370,6 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, INIT_LIST_HEAD(&fbo->base.ddestroy); INIT_LIST_HEAD(&fbo->base.lru); INIT_LIST_HEAD(&fbo->base.swap); - INIT_LIST_HEAD(&fbo->base.io_reserve_lru); fbo->base.moving = NULL; drm_vma_node_reset(&fbo->base.base.vma_node); @@ -573,8 +484,6 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, unsigned long num_pages, struct ttm_bo_kmap_obj *map) { - struct ttm_resource_manager *man = - ttm_manager_type(bo->bdev, bo->mem.mem_type); unsigned long offset, size; int ret; @@ -585,9 +494,7 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, if (start_page > bo->num_pages) return -EINVAL; - (void) ttm_mem_io_lock(man, false); ret = ttm_mem_io_reserve(bo->bdev, &bo->mem); - ttm_mem_io_unlock(man); if (ret) return ret; if (!bo->mem.bus.is_iomem) { @@ -602,10 +509,6 @@ EXPORT_SYMBOL(ttm_bo_kmap); void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) { - struct ttm_buffer_object *bo = map->bo; - struct ttm_resource_manager *man = - ttm_manager_type(bo->bdev, bo->mem.mem_type); - if (!map->virtual) return; switch (map->bo_kmap_type) { @@ -623,9 +526,7 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) default: BUG(); } - (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(map->bo->bdev, &map->bo->mem); - ttm_mem_io_unlock(man); map->virtual = NULL; map->page = NULL; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 0b805f72d18ee..d3dc0682425c4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -281,8 +281,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, pgoff_t i; vm_fault_t ret = VM_FAULT_NOPAGE; unsigned long address = vmf->address; - struct ttm_resource_manager *man = - ttm_manager_type(bdev, bo->mem.mem_type); /* * Refuse to fault imported pages. This should be handled @@ -321,24 +319,17 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, if (unlikely(ret != 0)) return ret; - err = ttm_mem_io_lock(man, true); + err = ttm_mem_io_reserve(bdev, &bo->mem); if (unlikely(err != 0)) - return VM_FAULT_NOPAGE; - err = ttm_mem_io_reserve_vm(bo); - if (unlikely(err != 0)) { - ret = VM_FAULT_SIGBUS; - goto out_io_unlock; - } + return VM_FAULT_SIGBUS; page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node); page_last = vma_pages(vma) + vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node); - if (unlikely(page_offset >= bo->num_pages)) { - ret = VM_FAULT_SIGBUS; - goto out_io_unlock; - } + if (unlikely(page_offset >= bo->num_pages)) + return VM_FAULT_SIGBUS; prot = ttm_io_prot(bo->mem.placement, prot); if (!bo->mem.bus.is_iomem) { @@ -350,21 +341,17 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, }; ttm = bo->ttm; - if (ttm_tt_populate(bo->ttm, &ctx)) { - ret = VM_FAULT_OOM; - goto out_io_unlock; - } + if (ttm_tt_populate(bo->ttm, &ctx)) + return VM_FAULT_OOM; } else { /* Iomem should not be marked encrypted */ prot = pgprot_decrypted(prot); } /* We don't prefault on huge faults. Yet. */ - if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && fault_page_size != 1) { - ret = ttm_bo_vm_insert_huge(vmf, bo, page_offset, - fault_page_size, prot); - goto out_io_unlock; - } + if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && fault_page_size != 1) + return ttm_bo_vm_insert_huge(vmf, bo, page_offset, + fault_page_size, prot); /* * Speculatively prefault a number of pages. Only error on @@ -376,8 +363,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, } else { page = ttm->pages[page_offset]; if (unlikely(!page && i == 0)) { - ret = VM_FAULT_OOM; - goto out_io_unlock; + return VM_FAULT_OOM; } else if (unlikely(!page)) { break; } @@ -404,7 +390,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, /* Never error on prefaulted PTEs */ if (unlikely((ret & VM_FAULT_ERROR))) { if (i == 0) - goto out_io_unlock; + return VM_FAULT_NOPAGE; else break; } @@ -413,9 +399,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, if (unlikely(++page_offset >= page_last)) break; } - ret = VM_FAULT_NOPAGE; -out_io_unlock: - ttm_mem_io_unlock(man); return ret; } EXPORT_SYMBOL(ttm_bo_vm_fault_reserved); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 33b642532e5ca..3a4602f9a03bd 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -65,10 +65,7 @@ void ttm_resource_manager_init(struct ttm_resource_manager *man, { unsigned i; - man->use_io_reserve_lru = false; - mutex_init(&man->io_reserve_mutex); spin_lock_init(&man->move_lock); - INIT_LIST_HEAD(&man->io_reserve_lru); man->size = p_size; for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 6c580987ba163..36ff64e2736cd 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -151,7 +151,6 @@ struct ttm_buffer_object { struct list_head lru; struct list_head ddestroy; struct list_head swap; - struct list_head io_reserve_lru; /** * Members protected by a bo reservation. diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index bc8d0ebb75689..9744ed9d677ec 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -441,11 +441,6 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); */ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo); -int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo); -void ttm_mem_io_free_vm(struct ttm_buffer_object *bo); -int ttm_mem_io_lock(struct ttm_resource_manager *man, bool interruptible); -void ttm_mem_io_unlock(struct ttm_resource_manager *man); - /** * ttm_bo_reserve: * diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 6d4226190480b..406baa8f0068e 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -113,10 +113,6 @@ struct ttm_resource_manager_func { * @default_caching: The default caching policy used for a buffer object * placed in this memory type if the user doesn't provide one. * @func: structure pointer implementing the range manager. See above - * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures - * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions - * reserved by the TTM vm system. - * @io_reserve_lru: Optional lru list for unreserving io mem regions. * @move_lock: lock for move fence * static information. bdev::driver::io_mem_free is never used. * @lru: The lru list for this memory type. @@ -134,16 +130,8 @@ struct ttm_resource_manager { uint32_t available_caching; uint32_t default_caching; const struct ttm_resource_manager_func *func; - struct mutex io_reserve_mutex; - bool use_io_reserve_lru; spinlock_t move_lock; - /* - * Protected by @io_reserve_mutex: - */ - - struct list_head io_reserve_lru; - /* * Protected by the global->lru_lock. */ @@ -163,8 +151,6 @@ struct ttm_resource_manager { * @base: bus base address * @is_iomem: is this io memory ? * @offset: offset from the base address - * @io_reserved_vm: The VM system has a refcount in @io_reserved_count - * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve * * Structure indicating the bus placement of an object. */ @@ -173,8 +159,6 @@ struct ttm_bus_placement { phys_addr_t base; unsigned long offset; bool is_iomem; - bool io_reserved_vm; - uint64_t io_reserved_count; }; /** -- GitLab From cf696856bc54a31f78e6538b84c8f7a006b6108b Mon Sep 17 00:00:00 2001 From: Kai Vehmanen <kai.vehmanen@linux.intel.com> Date: Tue, 1 Sep 2020 18:10:36 +0300 Subject: [PATCH 0731/1494] drm/i915: fix regression leading to display audio probe failure on GLK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 4f0b4352bd26 ("drm/i915: Extract cdclk requirements checking to separate function") the order of force_min_cdclk_changed check and intel_modeset_checks(), was reversed. This broke the mechanism to immediately force a new CDCLK minimum, and lead to driver probe errors for display audio on GLK platform with 5.9-rc1 kernel. Fix the issue by moving intel_modeset_checks() call later. [vsyrjala: It also broke the ability of planes to bump up the cdclk and thus could lead to underruns when eg. flipping from 32bpp to 64bpp framebuffer. To be clear, we still compute the new cdclk correctly but fail to actually program it to the hardware due to intel_set_cdclk_{pre,post}_plane_update() not getting called on account of state->modeset==false.] Fixes: 4f0b4352bd26 ("drm/i915: Extract cdclk requirements checking to separate function") BugLink: https://github.com/thesofproject/linux/issues/2410 Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200901151036.1312357-1-kai.vehmanen@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7d50b7177d402..8caeed23037cf 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15009,12 +15009,6 @@ static int intel_atomic_check(struct drm_device *dev, if (dev_priv->wm.distrust_bios_wm) any_ms = true; - if (any_ms) { - ret = intel_modeset_checks(state); - if (ret) - goto fail; - } - intel_fbc_choose_crtc(dev_priv, state); ret = calc_watermark_data(state); if (ret) @@ -15029,6 +15023,10 @@ static int intel_atomic_check(struct drm_device *dev, goto fail; if (any_ms) { + ret = intel_modeset_checks(state); + if (ret) + goto fail; + ret = intel_modeset_calc_cdclk(state); if (ret) return ret; -- GitLab From 4c8e84b8876dc726a7e5327b3113d75423c46728 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed, 2 Sep 2020 09:26:27 +0200 Subject: [PATCH 0732/1494] drm/managed: Cleanup of unused functions and polishing docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following functions are only used internally, not by drivers: - devm_drm_dev_init Also, now that we have a very slick and polished way to allocate a drm_device with devm_drm_dev_alloc, update all the docs to reflect the new reality. Mostly this consists of deleting old and misleading hints. Two main ones: - it is no longer required that the drm_device base class is first in the structure. devm_drm_dev_alloc can cope with it being anywhere - obviously embedded now strongly recommends using devm_drm_dev_alloc v2: Fix typos (Noralf) v3: Split out the removal of drm_dev_init, that's blocked on some discussions on how to convert vgem/vkms/i915-selftests. Adjust commit message to reflect that. Cc: Noralf Trønnes <noralf@tronnes.org> Acked-by: Noralf Trønnes <noralf@tronnes.org> (v2) Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: Luben Tuikov <luben.tuikov@amd.com> Cc: amd-gfx@lists.freedesktop.org Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200902072627.3617301-1-daniel.vetter@ffwll.ch --- .../driver-api/driver-model/devres.rst | 2 +- drivers/gpu/drm/drm_drv.c | 78 +++++-------------- drivers/gpu/drm/drm_managed.c | 2 +- include/drm/drm_device.h | 2 +- include/drm/drm_drv.h | 16 ++-- 5 files changed, 30 insertions(+), 70 deletions(-) diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index eaaaafc21134f..aa4d2420f79e8 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -263,7 +263,7 @@ DMA dmam_pool_destroy() DRM - devm_drm_dev_init() + devm_drm_dev_alloc() GPIO devm_gpiod_get() diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 13068fdf4331a..3b70f91e4316a 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -240,13 +240,13 @@ void drm_minor_release(struct drm_minor *minor) * DOC: driver instance overview * * A device instance for a drm driver is represented by &struct drm_device. This - * is initialized with drm_dev_init(), usually from bus-specific ->probe() - * callbacks implemented by the driver. The driver then needs to initialize all - * the various subsystems for the drm device like memory management, vblank - * handling, modesetting support and intial output configuration plus obviously - * initialize all the corresponding hardware bits. Finally when everything is up - * and running and ready for userspace the device instance can be published - * using drm_dev_register(). + * is allocated and initialized with devm_drm_dev_alloc(), usually from + * bus-specific ->probe() callbacks implemented by the driver. The driver then + * needs to initialize all the various subsystems for the drm device like memory + * management, vblank handling, modesetting support and initial output + * configuration plus obviously initialize all the corresponding hardware bits. + * Finally when everything is up and running and ready for userspace the device + * instance can be published using drm_dev_register(). * * There is also deprecated support for initalizing device instances using * bus-specific helpers and the &drm_driver.load callback. But due to @@ -274,7 +274,7 @@ void drm_minor_release(struct drm_minor *minor) * * The following example shows a typical structure of a DRM display driver. * The example focus on the probe() function and the other functions that is - * almost always present and serves as a demonstration of devm_drm_dev_init(). + * almost always present and serves as a demonstration of devm_drm_dev_alloc(). * * .. code-block:: c * @@ -294,22 +294,12 @@ void drm_minor_release(struct drm_minor *minor) * struct drm_device *drm; * int ret; * - * // devm_kzalloc() can't be used here because the drm_device ' - * // lifetime can exceed the device lifetime if driver unbind - * // happens when userspace still has open file descriptors. - * priv = kzalloc(sizeof(*priv), GFP_KERNEL); - * if (!priv) - * return -ENOMEM; - * + * priv = devm_drm_dev_alloc(&pdev->dev, &driver_drm_driver, + * struct driver_device, drm); + * if (IS_ERR(priv)) + * return PTR_ERR(priv); * drm = &priv->drm; * - * ret = devm_drm_dev_init(&pdev->dev, drm, &driver_drm_driver); - * if (ret) { - * kfree(priv); - * return ret; - * } - * drmm_add_final_kfree(drm, priv); - * * ret = drmm_mode_config_init(drm); * if (ret) * return ret; @@ -550,9 +540,9 @@ static void drm_fs_inode_free(struct inode *inode) * following guidelines apply: * * - The entire device initialization procedure should be run from the - * &component_master_ops.master_bind callback, starting with drm_dev_init(), - * then binding all components with component_bind_all() and finishing with - * drm_dev_register(). + * &component_master_ops.master_bind callback, starting with + * devm_drm_dev_alloc(), then binding all components with + * component_bind_all() and finishing with drm_dev_register(). * * - The opaque pointer passed to all components through component_bind_all() * should point at &struct drm_device of the device instance, not some driver @@ -706,24 +696,9 @@ static void devm_drm_dev_init_release(void *data) drm_dev_put(data); } -/** - * devm_drm_dev_init - Resource managed drm_dev_init() - * @parent: Parent device object - * @dev: DRM device - * @driver: DRM driver - * - * Managed drm_dev_init(). The DRM device initialized with this function is - * automatically put on driver detach using drm_dev_put(). - * - * Note that drivers must call drmm_add_final_kfree() after this function has - * completed successfully. - * - * RETURNS: - * 0 on success, or error code on failure. - */ -int devm_drm_dev_init(struct device *parent, - struct drm_device *dev, - struct drm_driver *driver) +static int devm_drm_dev_init(struct device *parent, + struct drm_device *dev, + struct drm_driver *driver) { int ret; @@ -737,7 +712,6 @@ int devm_drm_dev_init(struct device *parent, return ret; } -EXPORT_SYMBOL(devm_drm_dev_init); void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver, size_t size, size_t offset) @@ -767,19 +741,9 @@ EXPORT_SYMBOL(__devm_drm_dev_alloc); * @driver: DRM driver to allocate device for * @parent: Parent device object * - * Allocate and initialize a new DRM device. No device registration is done. - * Call drm_dev_register() to advertice the device to user space and register it - * with other core subsystems. This should be done last in the device - * initialization sequence to make sure userspace can't access an inconsistent - * state. - * - * The initial ref-count of the object is 1. Use drm_dev_get() and - * drm_dev_put() to take and drop further ref-counts. - * - * Note that for purely virtual devices @parent can be NULL. - * - * Drivers that wish to subclass or embed &struct drm_device into their - * own struct should look at using drm_dev_init() instead. + * This is the deprecated version of devm_drm_dev_alloc(), which does not support + * subclassing through embedding the struct &drm_device in a driver private + * structure, and which does not support automatic cleanup through devres. * * RETURNS: * Pointer to new DRM device, or ERR_PTR on failure. diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index 1e1356560c2ef..c36e3d98fd713 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -27,7 +27,7 @@ * be done directly with drmm_kmalloc() and the related functions. Everything * will be released on the final drm_dev_put() in reverse order of how the * release actions have been added and memory has been allocated since driver - * loading started with drm_dev_init(). + * loading started with devm_drm_dev_alloc(). * * Note that release actions and managed memory can also be added and removed * during the lifetime of the driver, all the functions are fully concurrent diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 0988351d743c4..f4f68e7a9149e 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -92,7 +92,7 @@ struct drm_device { * NULL. * * Instead of using this pointer it is recommended that drivers use - * drm_dev_init() and embed struct &drm_device in their larger + * devm_drm_dev_alloc() and embed struct &drm_device in their larger * per-device structure. */ void *dev_private; diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 7116abc1a04e0..9b11a2f0babc0 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -163,13 +163,12 @@ struct drm_driver { /** * @load: * - * Backward-compatible driver callback to complete - * initialization steps after the driver is registered. For - * this reason, may suffer from race conditions and its use is - * deprecated for new drivers. It is therefore only supported - * for existing drivers not yet converted to the new scheme. - * See drm_dev_init() and drm_dev_register() for proper and - * race-free way to set up a &struct drm_device. + * Backward-compatible driver callback to complete initialization steps + * after the driver is registered. For this reason, may suffer from + * race conditions and its use is deprecated for new drivers. It is + * therefore only supported for existing drivers not yet converted to + * the new scheme. See devm_drm_dev_alloc() and drm_dev_register() for + * proper and race-free way to set up a &struct drm_device. * * This is deprecated, do not use! * @@ -592,9 +591,6 @@ struct drm_driver { int drm_dev_init(struct drm_device *dev, struct drm_driver *driver, struct device *parent); -int devm_drm_dev_init(struct device *parent, - struct drm_device *dev, - struct drm_driver *driver); void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver, size_t size, size_t offset); -- GitLab From bc21585f3ff050f3fc7faaefc5e5c0541cec7aae Mon Sep 17 00:00:00 2001 From: Nirmoy Das <nirmoy.das@amd.com> Date: Sat, 29 Aug 2020 06:51:41 +0200 Subject: [PATCH 0733/1494] drm/amdgpu: disable gpu-sched load balance for uvd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On hardware with multiple uvd instances, dependent uvd jobs may get scheduled to different uvd instances. Because uvd_enc jobs retain hw context, dependent jobs should always run on the same uvd instance. This patch disables GPU scheduler's load balancer for a context that binds jobs from the same context to a uvd instance. v2: Squash in uvd_enc fix Signed-off-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 59032c26fc823..c80d8339f58c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -114,7 +114,11 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, scheds = adev->gpu_sched[hw_ip][hw_prio].sched; num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds; - if (hw_ip == AMDGPU_HW_IP_VCN_ENC || hw_ip == AMDGPU_HW_IP_VCN_DEC) { + /* disable load balance if the hw engine retains context among dependent jobs */ + if (hw_ip == AMDGPU_HW_IP_VCN_ENC || + hw_ip == AMDGPU_HW_IP_VCN_DEC || + hw_ip == AMDGPU_HW_IP_UVD_ENC || + hw_ip == AMDGPU_HW_IP_UVD) { sched = drm_sched_pick_best(scheds, num_scheds); scheds = &sched; num_scheds = 1; -- GitLab From 337b57aecb3e11294b0e547aac871a5481fd42ed Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 26 Aug 2020 23:22:24 -0400 Subject: [PATCH 0734/1494] drm/amdgpu/swsmu: add new callback for getting fan parameters To fetch the max rpm from pptable. Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 4 ++++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 4c5c041af4ee5..787fc682e0a52 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -452,6 +452,9 @@ struct smu_context struct work_struct throttling_logging_work; atomic64_t throttle_int_counter; + + unsigned fan_max_rpm; + unsigned manual_fan_speed_rpm; }; struct i2c_adapter; @@ -598,6 +601,7 @@ struct pptable_funcs { int (*enable_mgpu_fan_boost)(struct smu_context *smu); int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); int (*deep_sleep_control)(struct smu_context *smu, bool enablement); + int (*get_fan_parameters)(struct smu_context *smu); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8462b30f4fe39..114e85613e24b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -504,6 +504,8 @@ static int smu_late_init(void *handle) smu_get_unique_id(smu); + smu_get_fan_parameters(smu); + smu_handle_task(&adev->smu, smu->smu_dpm.dpm_level, AMD_PP_TASK_COMPLETE_INIT, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index c88f8fab1bae9..38c10177ed212 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -94,6 +94,7 @@ #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) #define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement) +#define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu) #endif #endif -- GitLab From 3204ff3e08f2c1bf7f7c93a15bae77d0043587d6 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 26 Aug 2020 23:34:57 -0400 Subject: [PATCH 0735/1494] drm/amdgpu/swsmu: add get_fan_parameters callbacks for smu11 asics grab the value from the pptable. Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 10 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 10 ++++++++++ .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 59b245c6c4d7b..198fc1185b2dc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1148,6 +1148,15 @@ static int arcturus_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int arcturus_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int arcturus_get_power_limit(struct smu_context *smu) { struct smu_11_0_powerplay_table *powerplay_table = @@ -2397,6 +2406,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_gpu_metrics = arcturus_get_gpu_metrics, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = arcturus_get_fan_parameters, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index cc67d5c60f3d0..3a9500dcb436e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1385,6 +1385,15 @@ static int navi10_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int navi10_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) { DpmActivityMonitorCoeffInt_t activity_monitor; @@ -2666,6 +2675,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = navi10_get_fan_parameters, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index b67931fd64b4a..2ac942b13bade 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1192,6 +1192,15 @@ static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *buf) { DpmActivityMonitorCoeffInt_t activity_monitor; @@ -2811,6 +2820,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = sienna_cichlid_get_fan_parameters, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- GitLab From eff6474260028d7293ac23234f33b49cde0f85f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 26 Aug 2020 23:49:37 -0400 Subject: [PATCH 0736/1494] drm/amdgpu/swsmu: drop get_fan_speed_percent (v2) No longer needed as we can calculate it based on the fan's max rpm. v2: rework code to avoid possible uninitialized variable use. Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +++++++++-- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 21 ------------------- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 19 ----------------- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 19 ----------------- 5 files changed, 10 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 787fc682e0a52..0ca997f83fb6d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -498,7 +498,6 @@ struct pptable_funcs { int (*notify_smc_display_config)(struct smu_context *smu); int (*set_cpu_power_state)(struct smu_context *smu); bool (*is_dpm_running)(struct smu_context *smu); - int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); int (*set_watermarks_table)(struct smu_context *smu, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 114e85613e24b..53e2051432bf0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2192,17 +2192,25 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value) int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) { int ret = 0; + uint32_t percent; + uint32_t current_rpm; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_percent) - ret = smu->ppt_funcs->get_fan_speed_percent(smu, speed); + if (smu->ppt_funcs->get_fan_speed_rpm) { + ret = smu->ppt_funcs->get_fan_speed_rpm(smu, ¤t_rpm); + if (!ret) { + percent = current_rpm * 100 / smu->fan_max_rpm; + *speed = percent > 100 ? 100 : percent; + } + } mutex_unlock(&smu->mutex); + return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 198fc1185b2dc..1998e7916fefc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1128,26 +1128,6 @@ static int arcturus_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int arcturus_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t percent, current_rpm; - int ret = 0; - - if (!speed) - return -EINVAL; - - ret = arcturus_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int arcturus_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2338,7 +2318,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .print_clk_levels = arcturus_print_clk_levels, .force_clk_levels = arcturus_force_clk_levels, .read_sensor = arcturus_read_sensor, - .get_fan_speed_percent = arcturus_get_fan_speed_percent, .get_fan_speed_rpm = arcturus_get_fan_speed_rpm, .get_power_profile_mode = arcturus_get_power_profile_mode, .set_power_profile_mode = arcturus_set_power_profile_mode, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 3a9500dcb436e..d5c25e538a03f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1367,24 +1367,6 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int navi10_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = navi10_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int navi10_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2606,7 +2588,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .display_config_changed = navi10_display_config_changed, .notify_smc_display_config = navi10_notify_smc_display_config, .is_dpm_running = navi10_is_dpm_running, - .get_fan_speed_percent = navi10_get_fan_speed_percent, .get_fan_speed_rpm = navi10_get_fan_speed_rpm, .get_power_profile_mode = navi10_get_power_profile_mode, .set_power_profile_mode = navi10_set_power_profile_mode, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 2ac942b13bade..97e54d382862b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1174,24 +1174,6 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = sienna_cichlid_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2753,7 +2735,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .display_config_changed = sienna_cichlid_display_config_changed, .notify_smc_display_config = sienna_cichlid_notify_smc_display_config, .is_dpm_running = sienna_cichlid_is_dpm_running, - .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent, .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm, .get_power_profile_mode = sienna_cichlid_get_power_profile_mode, .set_power_profile_mode = sienna_cichlid_set_power_profile_mode, -- GitLab From 8d6e65adc25e23fabbc5293b6cd320195c708dca Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 27 Aug 2020 00:04:24 -0400 Subject: [PATCH 0737/1494] drm/amdgpu/swsmu: drop set_fan_speed_percent (v2) No longer needed as we can calculate it based on the fan's max rpm. v2: minor code rework Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 -- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 9 ++++-- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 - .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 - .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 - .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 31 +------------------ 7 files changed, 8 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 0ca997f83fb6d..d22a759b6b435 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -573,7 +573,6 @@ struct pptable_funcs { int (*conv_power_profile_to_pplib_workload)(int power_profile); uint32_t (*get_fan_control_mode)(struct smu_context *smu); int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode); - int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed); int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed); int (*set_xgmi_pstate)(struct smu_context *smu, uint32_t pstate); int (*gfx_off_control)(struct smu_context *smu, bool enable); diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 2a3f1ee4a50b0..8307e2b790daf 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -200,9 +200,6 @@ int smu_v11_0_set_fan_control_mode(struct smu_context *smu, uint32_t mode); -int -smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); - int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 53e2051432bf0..7a55ece1f1246 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2217,14 +2217,19 @@ int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) { int ret = 0; + uint32_t rpm; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_percent) - ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed); + if (smu->ppt_funcs->set_fan_speed_rpm) { + if (speed > 100) + speed = 100; + rpm = speed * smu->fan_max_rpm / 100; + ret = smu->ppt_funcs->set_fan_speed_rpm(smu, rpm); + } mutex_unlock(&smu->mutex); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 1998e7916fefc..f6d9b0db3e823 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2363,7 +2363,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index d5c25e538a03f..87b5f9ff40212 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2631,7 +2631,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 97e54d382862b..863372436b984 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2778,7 +2778,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index ec20e839f555c..5abc06f7c9f3a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1099,35 +1099,6 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode) return 0; } -int -smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t duty100, duty; - uint64_t tmp64; - - if (speed > 100) - speed = 100; - - if (smu_v11_0_auto_fan_control(smu, 0)) - return -EINVAL; - - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - if (!duty100) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); - - return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC); -} - int smu_v11_0_set_fan_control_mode(struct smu_context *smu, uint32_t mode) @@ -1136,7 +1107,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu, switch (mode) { case AMD_FAN_CTRL_NONE: - ret = smu_v11_0_set_fan_speed_percent(smu, 100); + ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm); break; case AMD_FAN_CTRL_MANUAL: ret = smu_v11_0_auto_fan_control(smu, 0); -- GitLab From 9a7fd01384c3fdb16e303e2b13810d3f72835d2a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 25 Aug 2020 14:35:50 -0400 Subject: [PATCH 0738/1494] drm/amdgpu/swsmu: add smu11 helper to get manual fan speed (v2) Will be used to fetch the fan speeds when manual fan mode is set. v2: squash in a Coverity fix from Colin Ian King Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 +++ .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 8307e2b790daf..1f9575a4dfe7c 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -203,6 +203,9 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu, int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed); + int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, uint32_t pstate); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 5abc06f7c9f3a..f5aeb0b5cf977 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1153,6 +1153,27 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, return ret; } +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t tach_period, crystal_clock_freq; + uint64_t tmp64; + + tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, TARGET_PERIOD); + if (!tach_period) + return -EINVAL; + + crystal_clock_freq = amdgpu_asic_get_xclk(adev); + + tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000; + do_div(tmp64, (tach_period * 8)); + *speed = (uint32_t)tmp64; + + return 0; +} + int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, uint32_t pstate) { -- GitLab From f6eb433954bf32ab582208d9b58ec397f7814e5a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 27 Aug 2020 00:12:38 -0400 Subject: [PATCH 0739/1494] drm/amdgpu/swsmu: handle manual fan readback on SMU11 Need to read back from registers for manual mode rather than using the metrics table. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1164 Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 11 ++++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 11 ++++++++--- .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 11 ++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index f6d9b0db3e823..2ce6ad9c66094 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1123,9 +1123,14 @@ static int arcturus_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return arcturus_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return arcturus_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int arcturus_get_fan_parameters(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 87b5f9ff40212..42d53cca73600 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1362,9 +1362,14 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return navi10_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return navi10_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int navi10_get_fan_parameters(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 863372436b984..5c22611d5878b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1169,9 +1169,14 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return sienna_cichlid_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return sienna_cichlid_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) -- GitLab From 81202807ae6096bfbbfa28c2bc83cae1841bba38 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Tue, 1 Sep 2020 09:03:53 +0800 Subject: [PATCH 0740/1494] drm/amdgpu: block ring buffer access during GPU recovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When GPU is in reset, its status isn't stable and ring buffer also need be reset when resuming. Therefore driver should protect GPU recovery thread from ring buffer accessed by other threads. Otherwise GPU will randomly hang during recovery. v2: correct indent Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 17 +++++++++++++---- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 11 +++++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6518e444beada..c4900471beb00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -319,8 +319,12 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, { uint32_t ret; - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) - return amdgpu_kiq_rreg(adev, reg); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + ret = amdgpu_kiq_rreg(adev, reg); + up_read(&adev->reset_sem); + return ret; + } if ((reg * 4) < adev->rmmio_size) ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); @@ -332,6 +336,7 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); } + trace_amdgpu_mm_rreg(adev->pdev->device, reg, ret); return ret; } @@ -409,8 +414,12 @@ static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) { - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) - return amdgpu_kiq_wreg(adev, reg, v); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + amdgpu_kiq_wreg(adev, reg, v); + up_read(&adev->reset_sem); + return; + } amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index ad9ad622ccce7..31359e519d69d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,8 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { - + down_read_trylock(&adev->reset_sem)) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type); @@ -297,6 +296,8 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid); + + up_read(&adev->reset_sem); return; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 1ca79030e95eb..93ee77b14cc90 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -503,13 +503,14 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, * as GFXOFF under bare metal */ if (adev->gfx.kiq.ring.sched.ready && - (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && + down_read_trylock(&adev->reset_sem)) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid); + up_read(&adev->reset_sem); return; } @@ -602,7 +603,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, if (amdgpu_in_reset(adev)) return -EIO; - if (ring->sched.ready) { + if (ring->sched.ready && down_read_trylock(&adev->reset_sem)) { /* Vega20+XGMI caches PTEs in TC and TLB. Add a * heavy-weight TLB flush (type 2), which flushes * both. Due to a race condition with concurrent @@ -629,6 +630,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, if (r) { amdgpu_ring_undo(ring); spin_unlock(&adev->gfx.kiq.ring_lock); + up_read(&adev->reset_sem); return -ETIME; } @@ -637,9 +639,10 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); + up_read(&adev->reset_sem); return -ETIME; } - + up_read(&adev->reset_sem); return 0; } -- GitLab From 3d7248d7cee40ced0ac27517f1678beac67502f5 Mon Sep 17 00:00:00 2001 From: xinhui pan <xinhui.pan@amd.com> Date: Tue, 1 Sep 2020 15:28:06 +0800 Subject: [PATCH 0741/1494] drm/amdgpu: Fix a redundant kfree drm_dev_alloc() alloc *dev* and set managed.final_kfree to dev to free itself. Now from commit 5cdd68498918("drm/amdgpu: Embed drm_device into amdgpu_device (v3)") we alloc *adev* and ddev is just a member of it. So drm_dev_release try to free a wrong pointer then. Also driver's release trys to free adev, but drm_dev_release will access dev after call drvier's release. To fix it, remove driver's release and set managed.final_kfree to adev. [ 36.269348] BUG: unable to handle page fault for address: ffffa0c279940028 [ 36.276841] #PF: supervisor read access in kernel mode [ 36.282434] #PF: error_code(0x0000) - not-present page [ 36.288053] PGD 676601067 P4D 676601067 PUD 86a414067 PMD 86a247067 PTE 800ffff8066bf060 [ 36.296868] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC NOPTI [ 36.302409] CPU: 4 PID: 1375 Comm: bash Tainted: G O 5.9.0-rc2+ #46 [ 36.310670] Hardware name: System manufacturer System Product Name/PRIME Z390-A, BIOS 1401 11/26/2019 [ 36.320725] RIP: 0010:drm_managed_release+0x25/0x110 [drm] [ 36.326741] Code: 80 00 00 00 00 0f 1f 44 00 00 55 48 c7 c2 5a 9f 41 c0 be 00 02 00 00 48 89 e5 41 57 41 56 41 55 41 54 49 89 fc 53 48 83 ec 08 <48> 8b 7f 18 e8 c2 10 ff ff 4d 8b 74 24 20 49 8d 44 24 5 [ 36.347217] RSP: 0018:ffffb9424141fce0 EFLAGS: 00010282 [ 36.352931] RAX: 0000000000000006 RBX: ffffa0c279940010 RCX: 0000000000000006 [ 36.360718] RDX: ffffffffc0419f5a RSI: 0000000000000200 RDI: ffffa0c279940010 [ 36.368503] RBP: ffffb9424141fd10 R08: 0000000000000001 R09: 0000000000000001 [ 36.376304] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0c279940010 [ 36.384070] R13: ffffffffc0e2a000 R14: ffffa0c26924e220 R15: fffffffffffffff2 [ 36.391845] FS: 00007fc4a277b740(0000) GS:ffffa0c288e00000(0000) knlGS:0000000000000000 [ 36.400669] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.406937] CR2: ffffa0c279940028 CR3: 0000000792304006 CR4: 00000000003706e0 [ 36.414732] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 36.422550] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 36.430354] Call Trace: [ 36.433044] drm_dev_put.part.0+0x40/0x60 [drm] [ 36.438017] drm_dev_put+0x13/0x20 [drm] [ 36.442398] amdgpu_pci_remove+0x56/0x60 [amdgpu] [ 36.447528] pci_device_remove+0x3e/0xb0 [ 36.451807] device_release_driver_internal+0xff/0x1d0 [ 36.457416] device_release_driver+0x12/0x20 [ 36.462094] pci_stop_bus_device+0x70/0xa0 [ 36.466588] pci_stop_and_remove_bus_device_locked+0x1b/0x30 [ 36.472786] remove_store+0x7b/0x90 [ 36.476614] dev_attr_store+0x17/0x30 [ 36.480646] sysfs_kf_write+0x4b/0x60 [ 36.484655] kernfs_fop_write+0xe8/0x1d0 [ 36.488952] vfs_write+0xf5/0x230 [ 36.492562] ksys_write+0x70/0xf0 [ 36.496206] __x64_sys_write+0x1a/0x20 [ 36.500292] do_syscall_64+0x38/0x90 [ 36.504219] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: xinhui pan <xinhui.pan@amd.com> Acked-by: Alex Deucher <alexancer.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index dfc1a9721867e..9799501339062 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1153,7 +1153,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, if (ret) goto err_free; - drmm_add_final_kfree(ddev, ddev); + drmm_add_final_kfree(ddev, adev); if (!supports_atomic) ddev->driver_features &= ~DRIVER_ATOMIC; @@ -1209,13 +1209,6 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_dev_put(dev); } -static void amdgpu_driver_release(struct drm_device *ddev) -{ - struct amdgpu_device *adev = drm_to_adev(ddev); - - kfree(adev); -} - static void amdgpu_pci_shutdown(struct pci_dev *pdev) { @@ -1510,7 +1503,6 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, - .release = amdgpu_driver_release, .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, .gem_free_object_unlocked = amdgpu_gem_object_free, -- GitLab From 1545fbf97eafc1dbdc2923e58b4186b16a834784 Mon Sep 17 00:00:00 2001 From: xinhui pan <xinhui.pan@amd.com> Date: Tue, 1 Sep 2020 15:49:36 +0800 Subject: [PATCH 0742/1494] drm/amd/display: Fix a list corruption Remove the private obj from the internal list before we free aconnector. [ 56.925828] BUG: unable to handle page fault for address: ffff8f84a870a560 [ 56.933272] #PF: supervisor read access in kernel mode [ 56.938801] #PF: error_code(0x0000) - not-present page [ 56.944376] PGD 18e605067 P4D 18e605067 PUD 86a614067 PMD 86a4d0067 PTE 800ffff8578f5060 [ 56.953260] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC NOPTI [ 56.958815] CPU: 6 PID: 1407 Comm: bash Tainted: G O 5.9.0-rc2+ #46 [ 56.967092] Hardware name: System manufacturer System Product Name/PRIME Z390-A, BIOS 1401 11/26/2019 [ 56.977162] RIP: 0010:__list_del_entry_valid+0x31/0xa0 [ 56.982768] Code: 00 ad de 55 48 8b 17 4c 8b 47 08 48 89 e5 48 39 c2 74 27 48 b8 22 01 00 00 00 00 ad de 49 39 c0 74 2d 49 8b 30 48 39 fe 75 3d <48> 8b 52 08 48 39 f2 75 4c b8 01 00 00 00 5d c3 48 89 7 [ 57.003327] RSP: 0018:ffffb40c81687c90 EFLAGS: 00010246 [ 57.009048] RAX: dead000000000122 RBX: ffff8f84ea41f4f0 RCX: 0000000000000006 [ 57.016871] RDX: ffff8f84a870a558 RSI: ffff8f84ea41f4f0 RDI: ffff8f84ea41f4f0 [ 57.024672] RBP: ffffb40c81687c90 R08: ffff8f84ea400998 R09: 0000000000000001 [ 57.032490] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000006 [ 57.040287] R13: ffff8f84ea422a90 R14: ffff8f84b4129a20 R15: fffffffffffffff2 [ 57.048105] FS: 00007f550d885740(0000) GS:ffff8f8509600000(0000) knlGS:0000000000000000 [ 57.056979] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 57.063260] CR2: ffff8f84a870a560 CR3: 00000007e5144001 CR4: 00000000003706e0 [ 57.071053] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 57.078849] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 57.086684] Call Trace: [ 57.089381] drm_atomic_private_obj_fini+0x29/0x82 [drm] [ 57.095247] amdgpu_dm_fini+0x83/0x170 [amdgpu] [ 57.100264] dm_hw_fini+0x23/0x30 [amdgpu] [ 57.104814] amdgpu_device_fini+0x1df/0x4fe [amdgpu] [ 57.110271] amdgpu_driver_unload_kms+0x43/0x70 [amdgpu] [ 57.116136] amdgpu_pci_remove+0x3b/0x60 [amdgpu] [ 57.121291] pci_device_remove+0x3e/0xb0 [ 57.125583] device_release_driver_internal+0xff/0x1d0 [ 57.131223] device_release_driver+0x12/0x20 [ 57.135903] pci_stop_bus_device+0x70/0xa0 [ 57.140401] pci_stop_and_remove_bus_device_locked+0x1b/0x30 [ 57.146571] remove_store+0x7b/0x90 [ 57.150429] dev_attr_store+0x17/0x30 [ 57.154441] sysfs_kf_write+0x4b/0x60 [ 57.158479] kernfs_fop_write+0xe8/0x1d0 [ 57.162788] vfs_write+0xf5/0x230 [ 57.166426] ksys_write+0x70/0xf0 [ 57.170087] __x64_sys_write+0x1a/0x20 [ 57.174219] do_syscall_64+0x38/0x90 [ 57.178145] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: xinhui pan <xinhui.pan@amd.com> Acked-by: Feifei Xu <Feifei Xu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e2e7138c4e3f3..b91ae0feda275 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4993,6 +4993,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; + drm_atomic_private_obj_fini(&aconnector->mst_mgr.base); #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) -- GitLab From abb6fccbb4e5bab30ff9b96e27acdd9107426f28 Mon Sep 17 00:00:00 2001 From: Alex Sierra <alex.sierra@amd.com> Date: Tue, 1 Sep 2020 23:24:56 -0500 Subject: [PATCH 0743/1494] drm/amdgpu: enable ih1 ih2 for Arcturus only Enable multi-ring ih1 and ih2 for Arcturus only. For Navi10 family multi-ring has been disabled. Apparently, having multi-ring enabled in Navi was causing continus page fault interrupts. Further investigation is needed to get to the root cause. Related issue link: https://gitlab.freedesktop.org/drm/amd/-/issues/1279 Signed-off-by: Alex Sierra <alex.sierra@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 30 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 350f1bf063c61..74b1e7dc49a9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -306,7 +306,8 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev) } else { WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl); } - navi10_ih_reroute_ih(adev); + if (adev->irq.ih1.ring_size) + navi10_ih_reroute_ih(adev); if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)) { if (ih->use_bus_addr) { @@ -668,19 +669,26 @@ static int navi10_ih_sw_init(void *handle) adev->irq.ih.use_doorbell = true; adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1; - r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true); - if (r) - return r; + adev->irq.ih1.ring_size = 0; + adev->irq.ih2.ring_size = 0; - adev->irq.ih1.use_doorbell = true; - adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1; + if (adev->asic_type < CHIP_NAVI10) { + r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true); + if (r) + return r; - r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true); - if (r) - return r; + adev->irq.ih1.use_doorbell = true; + adev->irq.ih1.doorbell_index = + (adev->doorbell_index.ih + 1) << 1; + + r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true); + if (r) + return r; - adev->irq.ih2.use_doorbell = true; - adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1; + adev->irq.ih2.use_doorbell = true; + adev->irq.ih2.doorbell_index = + (adev->doorbell_index.ih + 2) << 1; + } r = amdgpu_irq_init(adev); -- GitLab From 1625951a3a7bdd776d38f2cdd35f72a795e82df0 Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Tue, 1 Sep 2020 19:10:32 -0400 Subject: [PATCH 0744/1494] drm/amdgpu: Remove superfluous NULL check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DRM device is a static member of the amdgpu device structure and as such always exists, so long as the PCI and thus the amdgpu device exist. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c4900471beb00..6dcc256b9ebce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3471,9 +3471,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) struct drm_connector_list_iter iter; int r; - if (!dev) - return -ENODEV; - adev = drm_to_adev(dev); if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) -- GitLab From ee354ff1c7c210fb41952ebf0a820fb714eae7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 2 Sep 2020 11:07:14 +0200 Subject: [PATCH 0745/1494] drm/amdgpu: fix max_entries calculation v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calculate the correct value for max_entries or we might run after the page_address array. v2: Xinhui pointed out we don't need the shift v3: use local copy of start and simplify some calculation v4: fix the case that we map less VA range than BO size Signed-off-by: Christian König <christian.koenig@amd.com> Fixes: 1e691e244487 drm/amdgpu: stop allocating dummy GTT nodes Reviewed-by: xinhui pan <xinhui.pan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 620472a70460a..37221b99ca960 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1693,13 +1693,13 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, uint64_t max_entries; uint64_t addr, last; + max_entries = mapping->last - start + 1; if (nodes) { addr = nodes->start << PAGE_SHIFT; - max_entries = (nodes->size - pfn) * - AMDGPU_GPU_PAGES_IN_CPU_PAGE; + max_entries = min((nodes->size - pfn) * + AMDGPU_GPU_PAGES_IN_CPU_PAGE, max_entries); } else { addr = 0; - max_entries = S64_MAX; } if (pages_addr) { @@ -1729,7 +1729,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, addr += pfn << PAGE_SHIFT; } - last = min((uint64_t)mapping->last, start + max_entries - 1); + last = start + max_entries - 1; r = amdgpu_vm_bo_update_mapping(adev, vm, false, false, resv, start, last, flags, addr, dma_addr, fence); -- GitLab From 6627d1c1a82ba72d6595a10d7453b6d30e288467 Mon Sep 17 00:00:00 2001 From: Changfeng <Changfeng.Zhu@amd.com> Date: Tue, 1 Sep 2020 16:17:01 +0800 Subject: [PATCH 0746/1494] drm/amdgpu: add ta firmware load in psp_v12_0 for renoir It needs to load renoir_ta firmware because hdcp is enabled by default for renoir now. This can avoid error:DTM TA is not initialized Signed-off-by: Changfeng <Changfeng.Zhu@amd.com> Reviewed-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c index 6c9614f77d33e..75489313dbadf 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c @@ -38,6 +38,8 @@ #include "oss/osssys_4_0_sh_mask.h" MODULE_FIRMWARE("amdgpu/renoir_asd.bin"); +MODULE_FIRMWARE("amdgpu/renoir_ta.bin"); + /* address block */ #define smnMP1_FIRMWARE_FLAGS 0x3010024 @@ -45,7 +47,10 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; const char *chip_name; + char fw_name[30]; int err = 0; + const struct ta_firmware_header_v1_0 *ta_hdr; + DRM_DEBUG("\n"); switch (adev->asic_type) { case CHIP_RENOIR: @@ -56,6 +61,55 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) } err = psp_init_asd_microcode(psp, chip_name); + if (err) + goto out; + + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); + err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); + if (err) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + dev_info(adev->dev, + "psp v12.0: Failed to load firmware \"%s\"\n", + fw_name); + } else { + err = amdgpu_ucode_validate(adev->psp.ta_fw); + if (err) + goto out2; + + ta_hdr = (const struct ta_firmware_header_v1_0 *) + adev->psp.ta_fw->data; + adev->psp.ta_hdcp_ucode_version = + le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); + adev->psp.ta_hdcp_ucode_size = + le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); + adev->psp.ta_hdcp_start_addr = + (uint8_t *)ta_hdr + + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); + + adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); + + adev->psp.ta_dtm_ucode_version = + le32_to_cpu(ta_hdr->ta_dtm_ucode_version); + adev->psp.ta_dtm_ucode_size = + le32_to_cpu(ta_hdr->ta_dtm_size_bytes); + adev->psp.ta_dtm_start_addr = + (uint8_t *)adev->psp.ta_hdcp_start_addr + + le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); + } + + return 0; + +out2: + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; +out: + if (err) { + dev_err(adev->dev, + "psp v12.0: Failed to load firmware \"%s\"\n", + fw_name); + } + return err; } -- GitLab From 2d37949dc3bacf3523b97ec84eb16a26574fe5b3 Mon Sep 17 00:00:00 2001 From: Ye Bin <yebin10@huawei.com> Date: Thu, 3 Sep 2020 10:17:56 +0800 Subject: [PATCH 0747/1494] drm/amdgpu/gfx10: Delete some duplicated argument to '|' 1. gfx_v10_0_soft_reset GRBM_STATUS__SPI_BUSY_MASK 2. gfx_v10_0_update_gfx_clock_gating AMD_CG_SUPPORT_GFX_CGLS Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Ye Bin <yebin10@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 2db195ec8d0c6..d502e30f67d9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7055,8 +7055,7 @@ static int gfx_v10_0_soft_reset(void *handle) GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK | GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__DB_BUSY_MASK | GRBM_STATUS__CB_BUSY_MASK | GRBM_STATUS__GDS_BUSY_MASK | - GRBM_STATUS__SPI_BUSY_MASK | GRBM_STATUS__GE_BUSY_NO_DMA_MASK - | GRBM_STATUS__BCI_BUSY_MASK)) { + GRBM_STATUS__SPI_BUSY_MASK | GRBM_STATUS__GE_BUSY_NO_DMA_MASK)) { grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP, 1); @@ -7449,7 +7448,6 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev, (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_CGCG | - AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) gfx_v10_0_enable_gui_idle_interrupt(adev, enable); -- GitLab From be99ecbfff4e3603994ebfcc37072270b0734ab7 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 1 Sep 2020 17:48:23 -0400 Subject: [PATCH 0748/1494] drm/amdgpu/gmc9: print client id string for gfxhub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 30 +++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 93ee77b14cc90..6a0ac57d75eaa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -71,6 +71,22 @@ #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 +static const char *gfxhub_client_ids[] = { + "CB", + "DB", + "IA", + "WD", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "PA", +}; + static const u32 golden_settings_vega10_hdp[] = { 0xf64, 0x0fffffff, 0x00000000, @@ -303,7 +319,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, { struct amdgpu_vmhub *hub; bool retry_fault = !!(entry->src_data[1] & 0x80); - uint32_t status = 0; + uint32_t status = 0, cid = 0; u64 addr; char hub_name[10]; @@ -340,6 +356,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, RREG32(hub->vm_l2_pro_fault_status); status = RREG32(hub->vm_l2_pro_fault_status); + cid = REG_GET_FIELD(status, + VM_L2_PROTECTION_FAULT_STATUS, CID); WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); } @@ -362,9 +380,13 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - VM_L2_PROTECTION_FAULT_STATUS, CID)); + if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); + else + dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%x\n", + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); -- GitLab From 93fabd84c90683199a294b6696559772f3e43e3a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 1 Sep 2020 17:49:47 -0400 Subject: [PATCH 0749/1494] drm/amdgpu/gmc10: print client id string for gfxhub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 30 +++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 30 +++++++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 76acd7f7723e1..b882ac59879a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -31,6 +31,27 @@ #include "soc15_common.h" +static const char *gfxhub_client_ids[] = { + "CB/DB", + "Reserved", + "GE1", + "GE2", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "Reserved", + "SDMA0", + "SDMA1", + "GCR", + "SDMA2", + "SDMA3", +}; + static uint32_t gfxhub_v2_0_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -55,12 +76,15 @@ static void gfxhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + u32 cid = REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID); + dev_err(adev->dev, "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 80c906a0383f9..237a9ff5afa0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -31,6 +31,27 @@ #include "soc15_common.h" +static const char *gfxhub_client_ids[] = { + "CB/DB", + "Reserved", + "GE1", + "GE2", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "Reserved", + "SDMA0", + "SDMA1", + "GCR", + "SDMA2", + "SDMA3", +}; + static uint32_t gfxhub_v2_1_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -55,12 +76,15 @@ static void gfxhub_v2_1_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + u32 cid = REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID); + dev_err(adev->dev, "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); -- GitLab From 02f23f5f7c4bad0bea5ed1685d78280df0295478 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 2 Sep 2020 13:07:47 -0400 Subject: [PATCH 0750/1494] drm/amdgpu/gmc9: print client id string for mmhub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 239 +++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6a0ac57d75eaa..d0645ad3446e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -87,6 +87,203 @@ static const char *gfxhub_client_ids[] = { "PA", }; +static const char *mmhub_client_ids_raven[][2] = { + [0][0] = "MP1", + [1][0] = "MP0", + [2][0] = "VCN", + [3][0] = "VCNU", + [4][0] = "HDP", + [5][0] = "DCE", + [13][0] = "UTCL2", + [19][0] = "TLS", + [26][0] = "OSS", + [27][0] = "SDMA0", + [0][1] = "MP1", + [1][1] = "MP0", + [2][1] = "VCN", + [3][1] = "VCNU", + [4][1] = "HDP", + [5][1] = "XDP", + [6][1] = "DBGU0", + [7][1] = "DCE", + [8][1] = "DCEDWB0", + [9][1] = "DCEDWB1", + [26][1] = "OSS", + [27][1] = "SDMA0", +}; + +static const char *mmhub_client_ids_renoir[][2] = { + [0][0] = "MP1", + [1][0] = "MP0", + [2][0] = "HDP", + [4][0] = "DCEDMC", + [5][0] = "DCEVGA", + [13][0] = "UTCL2", + [19][0] = "TLS", + [26][0] = "OSS", + [27][0] = "SDMA0", + [28][0] = "VCN", + [29][0] = "VCNU", + [30][0] = "JPEG", + [0][1] = "MP1", + [1][1] = "MP0", + [2][1] = "HDP", + [3][1] = "XDP", + [6][1] = "DBGU0", + [7][1] = "DCEDMC", + [8][1] = "DCEVGA", + [9][1] = "DCEDWB", + [26][1] = "OSS", + [27][1] = "SDMA0", + [28][1] = "VCN", + [29][1] = "VCNU", + [30][1] = "JPEG", +}; + +static const char *mmhub_client_ids_vega10[][2] = { + [0][0] = "MP0", + [1][0] = "UVD", + [2][0] = "UVDU", + [3][0] = "HDP", + [13][0] = "UTCL2", + [14][0] = "OSS", + [15][0] = "SDMA1", + [32+0][0] = "VCE0", + [32+1][0] = "VCE0U", + [32+2][0] = "XDMA", + [32+3][0] = "DCE", + [32+4][0] = "MP1", + [32+14][0] = "SDMA0", + [0][1] = "MP0", + [1][1] = "UVD", + [2][1] = "UVDU", + [3][1] = "DBGU0", + [4][1] = "HDP", + [5][1] = "XDP", + [14][1] = "OSS", + [15][1] = "SDMA0", + [32+0][1] = "VCE0", + [32+1][1] = "VCE0U", + [32+2][1] = "XDMA", + [32+3][1] = "DCE", + [32+4][1] = "DCEDWB", + [32+5][1] = "MP1", + [32+6][1] = "DBGU1", + [32+14][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_vega12[][2] = { + [0][0] = "MP0", + [1][0] = "VCE0", + [2][0] = "VCE0U", + [3][0] = "HDP", + [13][0] = "UTCL2", + [14][0] = "OSS", + [15][0] = "SDMA1", + [32+0][0] = "DCE", + [32+1][0] = "XDMA", + [32+2][0] = "UVD", + [32+3][0] = "UVDU", + [32+4][0] = "MP1", + [32+15][0] = "SDMA0", + [0][1] = "MP0", + [1][1] = "VCE0", + [2][1] = "VCE0U", + [3][1] = "DBGU0", + [4][1] = "HDP", + [5][1] = "XDP", + [14][1] = "OSS", + [15][1] = "SDMA0", + [32+0][1] = "DCE", + [32+1][1] = "DCEDWB", + [32+2][1] = "XDMA", + [32+3][1] = "UVD", + [32+4][1] = "UVDU", + [32+5][1] = "MP1", + [32+6][1] = "DBGU1", + [32+15][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_vega20[][2] = { + [0][0] = "XDMA", + [1][0] = "DCE", + [2][0] = "VCE0", + [3][0] = "VCE0U", + [4][0] = "UVD", + [5][0] = "UVD1U", + [13][0] = "OSS", + [14][0] = "HDP", + [15][0] = "SDMA0", + [32+0][0] = "UVD", + [32+1][0] = "UVDU", + [32+2][0] = "MP1", + [32+3][0] = "MP0", + [32+12][0] = "UTCL2", + [32+14][0] = "SDMA1", + [0][1] = "XDMA", + [1][1] = "DCE", + [2][1] = "DCEDWB", + [3][1] = "VCE0", + [4][1] = "VCE0U", + [5][1] = "UVD1", + [6][1] = "UVD1U", + [7][1] = "DBGU0", + [8][1] = "XDP", + [13][1] = "OSS", + [14][1] = "HDP", + [15][1] = "SDMA0", + [32+0][1] = "UVD", + [32+1][1] = "UVDU", + [32+2][1] = "DBGU1", + [32+3][1] = "MP1", + [32+4][1] = "MP0", + [32+14][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_arcturus[][2] = { + [2][0] = "MP1", + [3][0] = "MP0", + [10][0] = "UTCL2", + [13][0] = "OSS", + [14][0] = "HDP", + [15][0] = "SDMA0", + [32+15][0] = "SDMA1", + [64+15][0] = "SDMA2", + [96+15][0] = "SDMA3", + [128+15][0] = "SDMA4", + [160+11][0] = "JPEG", + [160+12][0] = "VCN", + [160+13][0] = "VCNU", + [160+15][0] = "SDMA5", + [192+10][0] = "UTCL2", + [192+11][0] = "JPEG1", + [192+12][0] = "VCN1", + [192+13][0] = "VCN1U", + [192+15][0] = "SDMA6", + [224+15][0] = "SDMA7", + [0][1] = "DBGU1", + [1][1] = "XDP", + [2][1] = "MP1", + [3][1] = "MP0", + [13][1] = "OSS", + [14][1] = "HDP", + [15][1] = "SDMA0", + [32+15][1] = "SDMA1", + [32+15][1] = "SDMA1", + [64+15][1] = "SDMA2", + [96+15][1] = "SDMA3", + [128+15][1] = "SDMA4", + [160+11][1] = "JPEG", + [160+12][1] = "VCN", + [160+13][1] = "VCNU", + [160+15][1] = "SDMA5", + [192+11][1] = "JPEG1", + [192+12][1] = "VCN1", + [192+13][1] = "VCN1U", + [192+15][1] = "SDMA6", + [224+15][1] = "SDMA7", +}; + static const u32 golden_settings_vega10_hdp[] = { 0xf64, 0x0fffffff, 0x00000000, @@ -319,9 +516,10 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, { struct amdgpu_vmhub *hub; bool retry_fault = !!(entry->src_data[1] & 0x80); - uint32_t status = 0, cid = 0; + uint32_t status = 0, cid = 0, rw = 0; u64 addr; char hub_name[10]; + const char *mmhub_cid; addr = (u64)entry->src_data[0] << 12; addr |= ((u64)entry->src_data[1] & 0xf) << 44; @@ -358,6 +556,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, status = RREG32(hub->vm_l2_pro_fault_status); cid = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, CID); + rw = REG_GET_FIELD(status, + VM_L2_PROTECTION_FAULT_STATUS, RW); WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); } @@ -380,13 +580,37 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) + if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) { dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], cid); - else - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%x\n", - cid); + } else { + switch (adev->asic_type) { + case CHIP_VEGA10: + mmhub_cid = mmhub_client_ids_vega10[cid][rw]; + break; + case CHIP_VEGA12: + mmhub_cid = mmhub_client_ids_vega12[cid][rw]; + break; + case CHIP_VEGA20: + mmhub_cid = mmhub_client_ids_vega20[cid][rw]; + break; + case CHIP_ARCTURUS: + mmhub_cid = mmhub_client_ids_arcturus[cid][rw]; + break; + case CHIP_RAVEN: + mmhub_cid = mmhub_client_ids_raven[cid][rw]; + break; + case CHIP_RENOIR: + mmhub_cid = mmhub_client_ids_renoir[cid][rw]; + break; + default: + mmhub_cid = NULL; + break; + } + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + mmhub_cid ? mmhub_cid : "unknown", cid); + } dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); @@ -399,10 +623,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); - dev_err(adev->dev, "\t RW: 0x%lx\n", - REG_GET_FIELD(status, - VM_L2_PROTECTION_FAULT_STATUS, RW)); - + dev_err(adev->dev, "\t RW: 0x%x\n", rw); } } -- GitLab From 11bc98bd71fe2e0cb572988519e51bca9d58a18a Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 2 Sep 2020 13:38:00 -0400 Subject: [PATCH 0751/1494] drm/amdgpu/mmhub2.0: print client id string for mmhub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 88 +++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 5baf899417d8c..2d88278c50bf7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -36,6 +36,63 @@ #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 +static const char *mmhub_client_ids_navi1x[][2] = { + [3][0] = "DCEDMC", + [4][0] = "DCEVGA", + [5][0] = "MP0", + [6][0] = "MP1", + [13][0] = "VMC", + [14][0] = "HDP", + [15][0] = "OSS", + [16][0] = "VCNU", + [17][0] = "JPEG", + [18][0] = "VCN", + [3][1] = "DCEDMC", + [4][1] = "DCEXFC", + [5][1] = "DCEVGA", + [6][1] = "DCEDWB", + [7][1] = "MP0", + [8][1] = "MP1", + [9][1] = "DBGU1", + [10][1] = "DBGU0", + [11][1] = "XDP", + [14][1] = "HDP", + [15][1] = "OSS", + [16][1] = "VCNU", + [17][1] = "JPEG", + [18][1] = "VCN", +}; + +static const char *mmhub_client_ids_sienna_cichlid[][2] = { + [3][0] = "DCEDMC", + [4][0] = "DCEVGA", + [5][0] = "MP0", + [6][0] = "MP1", + [8][0] = "VMC", + [9][0] = "VCNU0", + [10][0] = "JPEG", + [12][0] = "VCNU1", + [13][0] = "VCN1", + [14][0] = "HDP", + [15][0] = "OSS", + [32+11][0] = "VCN0", + [0][1] = "DBGU0", + [1][1] = "DBGU1", + [2][1] = "DCEDWB", + [3][1] = "DCEDMC", + [4][1] = "DCEVGA", + [5][1] = "MP0", + [6][1] = "MP1", + [7][1] = "XDP", + [9][1] = "VCNU0", + [10][1] = "JPEG", + [11][1] = "VCN0", + [12][1] = "VCNU1", + [13][1] = "VCN1", + [14][1] = "HDP", + [15][1] = "OSS", +}; + static uint32_t mmhub_v2_0_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -60,12 +117,33 @@ static void mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + uint32_t cid, rw; + const char *mmhub_cid = NULL; + + cid = REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, CID); + rw = REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, RW); + dev_err(adev->dev, "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - MMVM_L2_PROTECTION_FAULT_STATUS, CID)); + switch (adev->asic_type) { + case CHIP_NAVI10: + case CHIP_NAVI12: + case CHIP_NAVI14: + mmhub_cid = mmhub_client_ids_navi1x[cid][rw]; + break; + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw]; + break; + default: + mmhub_cid = NULL; + break; + } + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + mmhub_cid ? mmhub_cid : "unknown", cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, MMVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); @@ -78,9 +156,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", REG_GET_FIELD(status, MMVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); - dev_err(adev->dev, "\t RW: 0x%lx\n", - REG_GET_FIELD(status, - MMVM_L2_PROTECTION_FAULT_STATUS, RW)); + dev_err(adev->dev, "\t RW: 0x%x\n", rw); } static void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, -- GitLab From a5f2488f645f1f4db292e0e1088c0af0465d8311 Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Wed, 2 Sep 2020 17:30:20 +0300 Subject: [PATCH 0752/1494] drm/i915: split intel_modeset_init() pre/post gem init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn current intel_modeset_init() to a pre-gem init function, and add a new intel_modeset_init() function and move all post-gem modeset init there, in the correct layer. No functional changes. Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/5f4603f2c0216dba980338f00e0bfa791b526231.1599056955.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 28 ++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_display.h | 1 + drivers/gpu/drm/i915/i915_drv.c | 17 ++---------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8caeed23037cf..c3385995cbbba 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17907,8 +17907,8 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) return 0; } -/* part #2: call after irq install */ -int intel_modeset_init(struct drm_i915_private *i915) +/* part #2: call after irq install, but before gem init */ +int intel_modeset_init_nogem(struct drm_i915_private *i915) { struct drm_device *dev = &i915->drm; enum pipe pipe; @@ -18007,6 +18007,30 @@ int intel_modeset_init(struct drm_i915_private *i915) return 0; } +/* part #3: call after gem init */ +int intel_modeset_init(struct drm_i915_private *i915) +{ + int ret; + + intel_overlay_setup(i915); + + if (!HAS_DISPLAY(i915) || !INTEL_DISPLAY_ENABLED(i915)) + return 0; + + ret = intel_fbdev_init(&i915->drm); + if (ret) + return ret; + + /* Only enable hotplug handling once the fbdev is fully set up. */ + intel_hpd_init(i915); + + intel_init_ipc(i915); + + intel_psr_set_force_mode_changed(i915->psr.dp); + + return 0; +} + void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) { struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe); diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index e890c8fb779b8..63130e1a9effc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -629,6 +629,7 @@ intel_format_info_is_yuv_semiplanar(const struct drm_format_info *info, /* modesetting */ void intel_modeset_init_hw(struct drm_i915_private *i915); int intel_modeset_init_noirq(struct drm_i915_private *i915); +int intel_modeset_init_nogem(struct drm_i915_private *i915); int intel_modeset_init(struct drm_i915_private *i915); void intel_modeset_driver_remove(struct drm_i915_private *i915); void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e6918c7c07098..db301d75cfdee 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -58,7 +58,6 @@ #include "display/intel_hotplug.h" #include "display/intel_overlay.h" #include "display/intel_pipe_crc.h" -#include "display/intel_psr.h" #include "display/intel_sprite.h" #include "display/intel_vga.h" @@ -263,7 +262,7 @@ static int i915_driver_modeset_probe(struct drm_i915_private *i915) /* Important: The output setup functions called by modeset_init need * working irqs for e.g. gmbus and dp aux transfers. */ - ret = intel_modeset_init(i915); + ret = intel_modeset_init_nogem(i915); if (ret) goto out; @@ -271,22 +270,10 @@ static int i915_driver_modeset_probe(struct drm_i915_private *i915) if (ret) goto cleanup_modeset; - intel_overlay_setup(i915); - - if (!HAS_DISPLAY(i915) || !INTEL_DISPLAY_ENABLED(i915)) - return 0; - - ret = intel_fbdev_init(&i915->drm); + ret = intel_modeset_init(i915); if (ret) goto cleanup_gem; - /* Only enable hotplug handling once the fbdev is fully set up. */ - intel_hpd_init(i915); - - intel_init_ipc(i915); - - intel_psr_set_force_mode_changed(i915->psr.dp); - return 0; cleanup_gem: -- GitLab From 24d98a54b4a17ace71e01eb8862fb5ac1686962a Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Wed, 2 Sep 2020 17:30:21 +0300 Subject: [PATCH 0753/1494] drm/i915: move more display related probe to intel_modeset_init_noirq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the intel_modeset_* probe functions clarified, we can continue with moving more related calls to the right layer: - drm_vblank_init() - intel_bios_init() - intel_vga_register() - intel_csr_ucode_init() Unfortunately, for the time being, we also need to move a call to the *wrong* layer: the power domain init. No functional changes. v2: move probe failure while at it, power domain init Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/da229ffbed64983f002605074533c8b2878d17ee.1599056955.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 37 ++++++++++++++++++-- drivers/gpu/drm/i915/i915_drv.c | 36 +------------------ 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c3385995cbbba..459267b493f67 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -67,6 +67,7 @@ #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_csr.h" #include "intel_display_types.h" #include "intel_dp_link_training.h" #include "intel_fbc.h" @@ -17878,6 +17879,27 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) { int ret; + if (i915_inject_probe_failure(i915)) + return -ENODEV; + + if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) { + ret = drm_vblank_init(&i915->drm, + INTEL_NUM_PIPES(i915)); + if (ret) + return ret; + } + + intel_bios_init(i915); + + ret = intel_vga_register(i915); + if (ret) + goto cleanup_bios; + + /* FIXME: completely on the wrong abstraction layer */ + intel_power_domains_init_hw(i915, false); + + intel_csr_ucode_init(i915); + i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0); i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI | WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); @@ -17886,15 +17908,15 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) ret = intel_cdclk_init(i915); if (ret) - return ret; + goto cleanup_vga_client_pw_domain_csr; ret = intel_dbuf_init(i915); if (ret) - return ret; + goto cleanup_vga_client_pw_domain_csr; ret = intel_bw_init(i915); if (ret) - return ret; + goto cleanup_vga_client_pw_domain_csr; init_llist_head(&i915->atomic_helper.free_list); INIT_WORK(&i915->atomic_helper.free_work, @@ -17905,6 +17927,15 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) intel_fbc_init(i915); return 0; + +cleanup_vga_client_pw_domain_csr: + intel_csr_ucode_fini(i915); + intel_power_domains_driver_remove(i915); + intel_vga_unregister(i915); +cleanup_bios: + intel_bios_driver_remove(i915); + + return ret; } /* part #2: call after irq install, but before gem init */ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index db301d75cfdee..3737e1f102fbe 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -218,41 +218,7 @@ intel_teardown_mchbar(struct drm_i915_private *dev_priv) /* part #1: call before irq install */ static int i915_driver_modeset_probe_noirq(struct drm_i915_private *i915) { - int ret; - - if (i915_inject_probe_failure(i915)) - return -ENODEV; - - if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) { - ret = drm_vblank_init(&i915->drm, - INTEL_NUM_PIPES(i915)); - if (ret) - return ret; - } - - intel_bios_init(i915); - - ret = intel_vga_register(i915); - if (ret) - goto cleanup_bios; - - intel_power_domains_init_hw(i915, false); - - intel_csr_ucode_init(i915); - - ret = intel_modeset_init_noirq(i915); - if (ret) - goto cleanup_vga_client_pw_domain_csr; - - return 0; - -cleanup_vga_client_pw_domain_csr: - intel_csr_ucode_fini(i915); - intel_power_domains_driver_remove(i915); - intel_vga_unregister(i915); -cleanup_bios: - intel_bios_driver_remove(i915); - return ret; + return intel_modeset_init_noirq(i915); } /* part #2: call after irq install */ -- GitLab From eb4612d8ce4887f276c5bab67cb9921c399553d4 Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Wed, 2 Sep 2020 17:30:22 +0300 Subject: [PATCH 0754/1494] drm/i915: split out intel_modeset_driver_remove_nogem() and simplify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split out a separate display function for driver remove after gem deinitialization. Note that the sequence is not symmetric with init. However use similar naming as that reflects the deinit sequence. No functional changes. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/197fa7e488b412e147ff0fe9440c48811888f1a6.1599056955.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 12 ++++++++++ drivers/gpu/drm/i915/display/intel_display.h | 1 + drivers/gpu/drm/i915/i915_drv.c | 24 +++----------------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 459267b493f67..2ccb2cb6462f5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -18946,6 +18946,18 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915) intel_fbc_cleanup_cfb(i915); } +/* part #3: call after gem init */ +void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915) +{ + intel_csr_ucode_fini(i915); + + intel_power_domains_driver_remove(i915); + + intel_vga_unregister(i915); + + intel_bios_driver_remove(i915); +} + #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) struct intel_display_error_state { diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 63130e1a9effc..3670cabeb3cd6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -633,6 +633,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915); int intel_modeset_init(struct drm_i915_private *i915); void intel_modeset_driver_remove(struct drm_i915_private *i915); void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915); +void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915); void intel_display_resume(struct drm_device *dev); void intel_init_pch_refclk(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3737e1f102fbe..452c86a31e026 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -255,24 +255,6 @@ static int i915_driver_modeset_probe(struct drm_i915_private *i915) return ret; } -/* part #1: call before irq uninstall */ -static void i915_driver_modeset_remove(struct drm_i915_private *i915) -{ - intel_modeset_driver_remove(i915); -} - -/* part #2: call after irq uninstall */ -static void i915_driver_modeset_remove_noirq(struct drm_i915_private *i915) -{ - intel_csr_ucode_fini(i915); - - intel_power_domains_driver_remove(i915); - - intel_vga_unregister(i915); - - intel_bios_driver_remove(i915); -} - static void intel_init_dpio(struct drm_i915_private *dev_priv) { /* @@ -966,7 +948,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_cleanup_irq: intel_irq_uninstall(i915); out_cleanup_modeset: - i915_driver_modeset_remove_noirq(i915); + intel_modeset_driver_remove_nogem(i915); out_cleanup_hw: i915_driver_hw_remove(i915); intel_memory_regions_driver_release(i915); @@ -998,7 +980,7 @@ void i915_driver_remove(struct drm_i915_private *i915) intel_gvt_driver_remove(i915); - i915_driver_modeset_remove(i915); + intel_modeset_driver_remove(i915); intel_irq_uninstall(i915); @@ -1007,7 +989,7 @@ void i915_driver_remove(struct drm_i915_private *i915) i915_reset_error_state(i915); i915_gem_driver_remove(i915); - i915_driver_modeset_remove_noirq(i915); + intel_modeset_driver_remove_nogem(i915); i915_driver_hw_remove(i915); -- GitLab From d6843dda38dfa6dec213786d514051af34c9b84c Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Wed, 2 Sep 2020 17:30:23 +0300 Subject: [PATCH 0755/1494] drm/i915: remove the extra modeset init layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Streamline the modeset init by removing the extra init layer. No functional changes, which means the cleanup path looks hideous. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/62c32c35683b843ecdc2eca2bd2d3e62cb705e96.1599056955.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 64 +++++++++++---------------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 452c86a31e026..2746f3dcdc34d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -215,46 +215,6 @@ intel_teardown_mchbar(struct drm_i915_private *dev_priv) release_resource(&dev_priv->mch_res); } -/* part #1: call before irq install */ -static int i915_driver_modeset_probe_noirq(struct drm_i915_private *i915) -{ - return intel_modeset_init_noirq(i915); -} - -/* part #2: call after irq install */ -static int i915_driver_modeset_probe(struct drm_i915_private *i915) -{ - int ret; - - /* Important: The output setup functions called by modeset_init need - * working irqs for e.g. gmbus and dp aux transfers. */ - ret = intel_modeset_init_nogem(i915); - if (ret) - goto out; - - ret = i915_gem_init(i915); - if (ret) - goto cleanup_modeset; - - ret = intel_modeset_init(i915); - if (ret) - goto cleanup_gem; - - return 0; - -cleanup_gem: - i915_gem_suspend(i915); - i915_gem_driver_remove(i915); - i915_gem_driver_release(i915); -cleanup_modeset: - /* FIXME */ - intel_modeset_driver_remove(i915); - intel_irq_uninstall(i915); - intel_modeset_driver_remove_noirq(i915); -out: - return ret; -} - static void intel_init_dpio(struct drm_i915_private *dev_priv) { /* @@ -923,7 +883,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret < 0) goto out_cleanup_mmio; - ret = i915_driver_modeset_probe_noirq(i915); + ret = intel_modeset_init_noirq(i915); if (ret < 0) goto out_cleanup_hw; @@ -931,10 +891,18 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_cleanup_modeset; - ret = i915_driver_modeset_probe(i915); - if (ret < 0) + ret = intel_modeset_init_nogem(i915); + if (ret) goto out_cleanup_irq; + ret = i915_gem_init(i915); + if (ret) + goto out_cleanup_modeset2; + + ret = intel_modeset_init(i915); + if (ret) + goto out_cleanup_gem; + i915_driver_register(i915); enable_rpm_wakeref_asserts(&i915->runtime_pm); @@ -945,6 +913,16 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +out_cleanup_gem: + i915_gem_suspend(i915); + i915_gem_driver_remove(i915); + i915_gem_driver_release(i915); +out_cleanup_modeset2: + /* FIXME clean up the error path */ + intel_modeset_driver_remove(i915); + intel_irq_uninstall(i915); + intel_modeset_driver_remove_noirq(i915); + goto out_cleanup_modeset; out_cleanup_irq: intel_irq_uninstall(i915); out_cleanup_modeset: -- GitLab From c33b7c0389e17da3619434d46be9adf3fa0eba85 Mon Sep 17 00:00:00 2001 From: Kalyan Thota <kalyan_t@codeaurora.org> Date: Thu, 16 Jul 2020 17:05:34 +0530 Subject: [PATCH 0756/1494] drm/msm/dpu: add support for clk and bw scaling for display This change adds support to scale src clk and bandwidth as per composition requirements. Interconnect registration for bw has been moved to mdp device node from mdss to facilitate the scaling. Changes in v1: - Address armv7 compilation issues with the patch (Rob) Signed-off-by: Kalyan Thota <kalyan_t@codeaurora.org> Reviewed-by: Rob Clark <robdclark@chromium.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 109 +++++++++++++++--- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 5 +- .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 37 +++++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 4 + drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c | 9 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 84 ++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h | 4 + 8 files changed, 233 insertions(+), 23 deletions(-) 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 b36919d953628..393858ef8a832 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -30,6 +30,74 @@ enum dpu_perf_mode { DPU_PERF_MODE_MAX }; +/** + * @_dpu_core_perf_calc_bw() - to calculate BW per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * Return: returns aggregated BW for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_bw(struct dpu_kms *kms, + struct drm_crtc *crtc) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + u64 crtc_plane_bw = 0; + u32 bw_factor; + + drm_atomic_crtc_for_each_plane(plane, crtc) { + pstate = to_dpu_plane_state(plane->state); + if (!pstate) + continue; + + crtc_plane_bw += pstate->plane_fetch_bw; + } + + bw_factor = kms->catalog->perf.bw_inefficiency_factor; + if (bw_factor) { + crtc_plane_bw *= bw_factor; + do_div(crtc_plane_bw, 100); + } + + return crtc_plane_bw; +} + +/** + * _dpu_core_perf_calc_clk() - to calculate clock per crtc + * @kms - pointer to the dpu_kms + * @crtc - pointer to a crtc + * @state - pointer to a crtc state + * Return: returns max clk for all planes in crtc. + */ +static u64 _dpu_core_perf_calc_clk(struct dpu_kms *kms, + struct drm_crtc *crtc, struct drm_crtc_state *state) +{ + struct drm_plane *plane; + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + u64 crtc_clk; + u32 clk_factor; + + mode = &state->adjusted_mode; + + crtc_clk = 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); + } + + clk_factor = kms->catalog->perf.clk_inefficiency_factor; + if (clk_factor) { + crtc_clk *= clk_factor; + do_div(crtc_clk, 100); + } + + return crtc_clk; +} + static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -52,12 +120,7 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, dpu_cstate = to_dpu_crtc_state(state); memset(perf, 0, sizeof(struct dpu_core_perf_params)); - if (!dpu_cstate->bw_control) { - perf->bw_ctl = kms->catalog->perf.max_bw_high * - 1000ULL; - perf->max_per_pipe_ib = perf->bw_ctl; - perf->core_clk_rate = kms->perf.max_core_clk_rate; - } else if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { + if (kms->perf.perf_tune.mode == DPU_PERF_MODE_MINIMUM) { perf->bw_ctl = 0; perf->max_per_pipe_ib = 0; perf->core_clk_rate = 0; @@ -65,6 +128,10 @@ static void _dpu_core_perf_calc_crtc(struct dpu_kms *kms, perf->bw_ctl = kms->perf.fix_core_ab_vote; perf->max_per_pipe_ib = kms->perf.fix_core_ib_vote; perf->core_clk_rate = kms->perf.fix_core_clk_rate; + } else { + perf->bw_ctl = _dpu_core_perf_calc_bw(kms, crtc); + perf->max_per_pipe_ib = kms->catalog->perf.min_dram_ib; + perf->core_clk_rate = _dpu_core_perf_calc_clk(kms, crtc, state); } DPU_DEBUG( @@ -116,11 +183,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("crtc:%d bw:%llu ctrl:%d\n", tmp_crtc->base.id, tmp_cstate->new_perf.bw_ctl, tmp_cstate->bw_control); - /* - * For bw check only use the bw if the - * atomic property has been already set - */ - if (tmp_cstate->bw_control) + bw_sum_of_intfs += tmp_cstate->new_perf.bw_ctl; } @@ -132,9 +195,7 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc, DPU_DEBUG("final threshold bw limit = %d\n", threshold); - if (!dpu_cstate->bw_control) { - DPU_DEBUG("bypass bandwidth check\n"); - } else if (!threshold) { + if (!threshold) { DPU_ERROR("no bandwidth limits specified\n"); return -E2BIG; } else if (bw > threshold) { @@ -155,7 +216,11 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate; - int ret = 0; + int i, ret = 0; + u64 avg_bw; + + if (!kms->num_paths) + return -EINVAL; drm_for_each_crtc(tmp_crtc, crtc->dev) { if (tmp_crtc->enabled && @@ -166,10 +231,20 @@ static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, perf.max_per_pipe_ib = max(perf.max_per_pipe_ib, dpu_cstate->new_perf.max_per_pipe_ib); - DPU_DEBUG("crtc=%d bw=%llu\n", tmp_crtc->base.id, - dpu_cstate->new_perf.bw_ctl); + perf.bw_ctl += dpu_cstate->new_perf.bw_ctl; + + DPU_DEBUG("crtc=%d bw=%llu paths:%d\n", + tmp_crtc->base.id, + dpu_cstate->new_perf.bw_ctl, kms->num_paths); } } + + avg_bw = perf.bw_ctl; + do_div(avg_bw, (kms->num_paths * 1000)); /*Bps_to_icc*/ + + for (i = 0; i < kms->num_paths; i++) + icc_set_bw(kms->path[i], avg_bw, perf.max_per_pipe_ib); + return ret; } 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 97d122eee96df..60b304b72b7c3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -684,7 +684,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { .max_bw_high = 6800000, .min_core_ib = 2400000, .min_llcc_ib = 800000, - .min_dram_ib = 800000, + .min_dram_ib = 1600000, + .min_prefill_lines = 24, .danger_lut_tbl = {0xff, 0xffff, 0x0}, .qos_lut_tbl = { {.nentry = ARRAY_SIZE(sc7180_qos_linear), @@ -701,6 +702,8 @@ static const struct dpu_perf_cfg sc7180_perf_data = { {.rd_enable = 1, .wr_enable = 1}, {.rd_enable = 1, .wr_enable = 0} }, + .clk_inefficiency_factor = 105, + .bw_inefficiency_factor = 120, }; static const struct dpu_perf_cfg sm8150_perf_data = { 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 1b7a9213a7561..3544af1a45c5a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -659,6 +659,8 @@ struct dpu_perf_cdp_cfg { * @downscaling_prefill_lines downscaling latency in lines * @amortizable_theshold minimum y position for traffic shaping prefill * @min_prefill_lines minimum pipeline latency in lines + * @clk_inefficiency_factor DPU src clock inefficiency factor + * @bw_inefficiency_factor DPU axi bus bw inefficiency factor * @safe_lut_tbl: LUT tables for safe signals * @danger_lut_tbl: LUT tables for danger signals * @qos_lut_tbl: LUT tables for QoS signals @@ -683,6 +685,8 @@ struct dpu_perf_cfg { u32 downscaling_prefill_lines; u32 amortizable_threshold; u32 min_prefill_lines; + u32 clk_inefficiency_factor; + u32 bw_inefficiency_factor; u32 safe_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; u32 danger_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; struct dpu_qos_lut_tbl qos_lut_tbl[DPU_QOS_LUT_USAGE_MAX]; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index c0a4d4e16d820..5abf0047c2d32 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -290,6 +290,28 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms) return 0; } +static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) +{ + struct icc_path *path0; + struct icc_path *path1; + struct drm_device *dev = dpu_kms->dev; + + path0 = of_icc_get(dev->dev, "mdp0-mem"); + path1 = of_icc_get(dev->dev, "mdp1-mem"); + + if (IS_ERR_OR_NULL(path0)) + return PTR_ERR_OR_ZERO(path0); + + dpu_kms->path[0] = path0; + dpu_kms->num_paths = 1; + + if (!IS_ERR_OR_NULL(path1)) { + dpu_kms->path[1] = path1; + dpu_kms->num_paths++; + } + return 0; +} + static int dpu_kms_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) { return dpu_crtc_vblank(crtc, true); @@ -952,6 +974,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms) dpu_vbif_init_memtypes(dpu_kms); + if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) + dpu_kms_parse_data_bus_icc_path(dpu_kms); + pm_runtime_put_sync(&dpu_kms->pdev->dev); return 0; @@ -1079,7 +1104,7 @@ static int dpu_dev_remove(struct platform_device *pdev) static int __maybe_unused dpu_runtime_suspend(struct device *dev) { - int rc = -1; + int i, rc = -1; struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp; @@ -1090,6 +1115,9 @@ static int __maybe_unused dpu_runtime_suspend(struct device *dev) if (rc) DPU_ERROR("clock disable failed rc:%d\n", rc); + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, 0); + return rc; } @@ -1101,8 +1129,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev) struct drm_encoder *encoder; struct drm_device *ddev; struct dss_module_power *mp = &dpu_kms->mp; + int i; ddev = dpu_kms->dev; + + /* Min vote of BW is required before turning on AXI clk */ + for (i = 0; i < dpu_kms->num_paths; i++) + icc_set_bw(dpu_kms->path[i], 0, + dpu_kms->catalog->perf.min_dram_ib); + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) { DPU_ERROR("clock enable failed rc:%d\n", rc); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index e140cd633071d..1c0e4c0c9ffb3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -8,6 +8,8 @@ #ifndef __DPU_KMS_H__ #define __DPU_KMS_H__ +#include <linux/interconnect.h> + #include <drm/drm_drv.h> #include "msm_drv.h" @@ -140,6 +142,8 @@ struct dpu_kms { * when disabled. */ atomic_t bandwidth_ref; + struct icc_path *path[2]; + u32 num_paths; }; struct vsync_info { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 7d3fdbb00e7eb..cd4078807db1b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -8,7 +8,6 @@ #include <linux/irqdesc.h> #include <linux/irqchip/chained_irq.h> #include "dpu_kms.h" -#include <linux/interconnect.h> #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base) @@ -277,9 +276,11 @@ int dpu_mdss_init(struct drm_device *dev) DRM_DEBUG("mapped mdss address space @%pK\n", dpu_mdss->mmio); - ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); - if (ret) - return ret; + if (!of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss")) { + ret = dpu_mdss_parse_data_bus_icc_path(dev, dpu_mdss); + if (ret) + return ret; + } mp = &dpu_mdss->mp; ret = msm_dss_parse_clock(pdev, mp); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 29e373d2e7b5d..7ea90d25a3b69 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -131,6 +131,86 @@ static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane) return to_dpu_kms(priv->kms); } +/** + * _dpu_plane_calc_bw - calculate bandwidth required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated bandwidth in the plane state. + * BW Equation: src_w * src_h * bpp * fps * (v_total / v_dest) + * Prefill BW Equation: line src bytes * line_time + */ +static void _dpu_plane_calc_bw(struct drm_plane *plane, + struct drm_framebuffer *fb) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + const struct dpu_format *fmt = NULL; + struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + int src_width, src_height, dst_height, fps; + u64 plane_prefill_bw; + u64 plane_bw; + u32 hw_latency_lines; + u64 scale_factor; + int vbp, vpw; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + fmt = dpu_get_dpu_format_ext(fb->format->format, fb->modifier); + + src_width = drm_rect_width(&pdpu->pipe_cfg.src_rect); + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + vbp = mode->vtotal - mode->vsync_end; + vpw = mode->vsync_end - mode->vsync_start; + hw_latency_lines = dpu_kms->catalog->perf.min_prefill_lines; + scale_factor = src_height > dst_height ? + mult_frac(src_height, 1, dst_height) : 1; + + plane_bw = + src_width * mode->vtotal * fps * fmt->bpp * + scale_factor; + + plane_prefill_bw = + src_width * hw_latency_lines * fps * fmt->bpp * + scale_factor * mode->vtotal; + + do_div(plane_prefill_bw, (vbp+vpw)); + + pstate->plane_fetch_bw = max(plane_bw, plane_prefill_bw); +} + +/** + * _dpu_plane_calc_clk - calculate clock required for a plane + * @Plane: Pointer to drm plane. + * Result: Updates calculated clock in the plane state. + * Clock equation: dst_w * v_total * fps * (src_h / dst_h) + */ +static void _dpu_plane_calc_clk(struct drm_plane *plane) +{ + struct dpu_plane *pdpu = to_dpu_plane(plane); + struct dpu_plane_state *pstate; + struct drm_display_mode *mode; + int dst_width, src_height, dst_height, fps; + + pstate = to_dpu_plane_state(plane->state); + mode = &plane->state->crtc->mode; + + src_height = drm_rect_height(&pdpu->pipe_cfg.src_rect); + dst_width = drm_rect_width(&pdpu->pipe_cfg.dst_rect); + dst_height = drm_rect_height(&pdpu->pipe_cfg.dst_rect); + fps = drm_mode_vrefresh(mode); + + pstate->plane_clk = + dst_width * mode->vtotal * fps; + + if (src_height > dst_height) { + pstate->plane_clk *= src_height; + do_div(pstate->plane_clk, dst_height); + } +} + /** * _dpu_plane_calc_fill_level - calculate fill level of the given source format * @plane: Pointer to drm plane @@ -1102,6 +1182,10 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane) } _dpu_plane_set_qos_remap(plane); + + _dpu_plane_calc_bw(plane, fb); + + _dpu_plane_calc_clk(plane); } static void _dpu_plane_atomic_disable(struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h index 456949713e90a..ca83b8753d590 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h @@ -25,6 +25,8 @@ * @scaler3_cfg: configuration data for scaler3 * @pixel_ext: configuration data for pixel extensions * @cdp_cfg: CDP configuration + * @plane_fetch_bw: calculated BW per plane + * @plane_clk: calculated clk per plane */ struct dpu_plane_state { struct drm_plane_state base; @@ -39,6 +41,8 @@ struct dpu_plane_state { struct dpu_hw_pixel_ext pixel_ext; struct dpu_hw_pipe_cdp_cfg cdp_cfg; + u64 plane_fetch_bw; + u64 plane_clk; }; /** -- GitLab From a046c2c28aa81ff083003c278540dc0b84ddd4b0 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org> Date: Tue, 4 Aug 2020 12:14:42 +0530 Subject: [PATCH 0757/1494] drm/msm/mdp4: Remove unused downstream bus scaling apis MSM bus scaling has moved on to use interconnect framework and downstream bus scaling apis are not present anymore. Remove them as they are nop anyways in the current code, no functional change. Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- .../gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c | 51 ------------------- drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h | 13 ----- .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 47 ----------------- 3 files changed, 111 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c index 5d8956055286d..88645dbc3785b 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c @@ -25,54 +25,9 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -/* not ironically named at all.. no, really.. */ -static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) -{ - struct drm_device *dev = mdp4_dtv_encoder->base.dev; - struct lcdc_platform_data *dtv_pdata = mdp4_find_pdata("dtv.0"); - - if (!dtv_pdata) { - DRM_DEV_ERROR(dev->dev, "could not find dtv pdata\n"); - return; - } - - if (dtv_pdata->bus_scale_table) { - mdp4_dtv_encoder->bsc = msm_bus_scale_register_client( - dtv_pdata->bus_scale_table); - DBG("bus scale client: %08x", mdp4_dtv_encoder->bsc); - DBG("lcdc_power_save: %p", dtv_pdata->lcdc_power_save); - if (dtv_pdata->lcdc_power_save) - dtv_pdata->lcdc_power_save(1); - } -} - -static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) -{ - if (mdp4_dtv_encoder->bsc) { - msm_bus_scale_unregister_client(mdp4_dtv_encoder->bsc); - mdp4_dtv_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) -{ - if (mdp4_dtv_encoder->bsc) { - DBG("set bus scaling: %d", idx); - msm_bus_scale_client_update_request(mdp4_dtv_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {} -static void bs_fini(struct mdp4_dtv_encoder *mdp4_dtv_encoder) {} -static void bs_set(struct mdp4_dtv_encoder *mdp4_dtv_encoder, int idx) {} -#endif - static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder) { struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); - bs_fini(mdp4_dtv_encoder); drm_encoder_cleanup(encoder); kfree(mdp4_dtv_encoder); } @@ -162,8 +117,6 @@ static void mdp4_dtv_encoder_disable(struct drm_encoder *encoder) clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk); clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk); - bs_set(mdp4_dtv_encoder, 0); - mdp4_dtv_encoder->enabled = false; } @@ -185,8 +138,6 @@ static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder) MDP4_DMA_CONFIG_PACK(0x21)); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1); - bs_set(mdp4_dtv_encoder, 1); - DBG("setting mdp_clk=%lu", pc); ret = clk_set_rate(mdp4_dtv_encoder->mdp_clk, pc); @@ -252,8 +203,6 @@ struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev) goto fail; } - bs_init(mdp4_dtv_encoder); - return encoder; fail: diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h index 18933bd81c77a..e8ee92ab79566 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h @@ -222,17 +222,4 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) } #endif -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -/* bus scaling data is associated with extra pointless platform devices, - * "dtv", etc.. this is a bit of a hack, but we need a way for encoders - * to find their pdata to make the bus-scaling stuff work. - */ -static inline void *mdp4_find_pdata(const char *devname) -{ - struct device *dev; - dev = bus_find_device_by_name(&platform_bus_type, NULL, devname); - return dev ? dev->platform_data : NULL; -} -#endif - #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 871f3514ef693..10eb3e5b218ef 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -30,51 +30,10 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder) return to_mdp4_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) -{ - struct drm_device *dev = mdp4_lcdc_encoder->base.dev; - struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0"); - - if (!lcdc_pdata) { - DRM_DEV_ERROR(dev->dev, "could not find lvds pdata\n"); - return; - } - - if (lcdc_pdata->bus_scale_table) { - mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client( - lcdc_pdata->bus_scale_table); - DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc); - } -} - -static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) -{ - if (mdp4_lcdc_encoder->bsc) { - msm_bus_scale_unregister_client(mdp4_lcdc_encoder->bsc); - mdp4_lcdc_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) -{ - if (mdp4_lcdc_encoder->bsc) { - DBG("set bus scaling: %d", idx); - msm_bus_scale_client_update_request(mdp4_lcdc_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {} -static void bs_fini(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) {} -static void bs_set(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder, int idx) {} -#endif - static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder) { struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); - bs_fini(mdp4_lcdc_encoder); drm_encoder_cleanup(encoder); kfree(mdp4_lcdc_encoder); } @@ -348,8 +307,6 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) DRM_DEV_ERROR(dev->dev, "failed to disable regulator: %d\n", ret); } - bs_set(mdp4_lcdc_encoder, 0); - mdp4_lcdc_encoder->enabled = false; } @@ -382,8 +339,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); - bs_set(mdp4_lcdc_encoder, 1); - for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) @@ -480,8 +435,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev, } mdp4_lcdc_encoder->regs[2] = reg; - bs_init(mdp4_lcdc_encoder); - return encoder; fail: -- GitLab From f032b68101b14a585a49c39c91660cf98ffce68c Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org> Date: Tue, 4 Aug 2020 12:14:43 +0530 Subject: [PATCH 0758/1494] drm/msm/mdp5: Remove unused downstream bus scaling apis MSM bus scaling has moved on to use interconnect framework and downstream bus scaling apis are not present anymore. Remove them as they are nop anyways in the current code, no functional change. Signed-off-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- .../gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c | 24 ------- drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 68 ------------------- 2 files changed, 92 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c index eeef41fcd4e1a..ff2c1d583c792 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c @@ -14,27 +14,6 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder) return to_mdp5_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -#include <linux/msm-bus.h> -#include <linux/msm-bus-board.h> - -static void bs_set(struct mdp5_encoder *mdp5_cmd_enc, int idx) -{ - if (mdp5_cmd_enc->bsc) { - DBG("set bus scaling: %d", idx); - /* HACK: scaling down, and then immediately back up - * seems to leave things broken (underflow).. so - * never disable: - */ - idx = 1; - msm_bus_scale_client_update_request(mdp5_cmd_enc->bsc, idx); - } -} -#else -static void bs_set(struct mdp5_encoder *mdp5_cmd_enc, int idx) {} -#endif - #define VSYNC_CLK_RATE 19200000 static int pingpong_tearcheck_setup(struct drm_encoder *encoder, struct drm_display_mode *mode) @@ -146,8 +125,6 @@ void mdp5_cmd_encoder_disable(struct drm_encoder *encoder) mdp5_ctl_set_encoder_state(ctl, pipeline, false); mdp5_ctl_commit(ctl, pipeline, mdp_ctl_flush_mask_encoder(intf), true); - bs_set(mdp5_cmd_enc, 0); - mdp5_cmd_enc->enabled = false; } @@ -161,7 +138,6 @@ void mdp5_cmd_encoder_enable(struct drm_encoder *encoder) if (WARN_ON(mdp5_cmd_enc->enabled)) return; - bs_set(mdp5_cmd_enc, 1); if (pingpong_tearcheck_enable(encoder)) return; diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c index f48827283c2bd..79d67c495780f 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c @@ -16,72 +16,9 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder) return to_mdp5_kms(to_mdp_kms(priv->kms)); } -#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING -#include <mach/board.h> -#include <mach/msm_bus.h> -#include <mach/msm_bus_board.h> -#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \ - { \ - .src = MSM_BUS_MASTER_MDP_PORT0, \ - .dst = MSM_BUS_SLAVE_EBI_CH0, \ - .ab = (ab_val), \ - .ib = (ib_val), \ - } - -static struct msm_bus_vectors mdp_bus_vectors[] = { - MDP_BUS_VECTOR_ENTRY(0, 0), - MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000), -}; -static struct msm_bus_paths mdp_bus_usecases[] = { { - .num_paths = 1, - .vectors = &mdp_bus_vectors[0], -}, { - .num_paths = 1, - .vectors = &mdp_bus_vectors[1], -} }; -static struct msm_bus_scale_pdata mdp_bus_scale_table = { - .usecase = mdp_bus_usecases, - .num_usecases = ARRAY_SIZE(mdp_bus_usecases), - .name = "mdss_mdp", -}; - -static void bs_init(struct mdp5_encoder *mdp5_encoder) -{ - mdp5_encoder->bsc = msm_bus_scale_register_client( - &mdp_bus_scale_table); - DBG("bus scale client: %08x", mdp5_encoder->bsc); -} - -static void bs_fini(struct mdp5_encoder *mdp5_encoder) -{ - if (mdp5_encoder->bsc) { - msm_bus_scale_unregister_client(mdp5_encoder->bsc); - mdp5_encoder->bsc = 0; - } -} - -static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) -{ - if (mdp5_encoder->bsc) { - DBG("set bus scaling: %d", idx); - /* HACK: scaling down, and then immediately back up - * seems to leave things broken (underflow).. so - * never disable: - */ - idx = 1; - msm_bus_scale_client_update_request(mdp5_encoder->bsc, idx); - } -} -#else -static void bs_init(struct mdp5_encoder *mdp5_encoder) {} -static void bs_fini(struct mdp5_encoder *mdp5_encoder) {} -static void bs_set(struct mdp5_encoder *mdp5_encoder, int idx) {} -#endif - static void mdp5_encoder_destroy(struct drm_encoder *encoder) { struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); - bs_fini(mdp5_encoder); drm_encoder_cleanup(encoder); kfree(mdp5_encoder); } @@ -222,8 +159,6 @@ static void mdp5_vid_encoder_disable(struct drm_encoder *encoder) */ mdp_irq_wait(&mdp5_kms->base, intf2vblank(mixer, intf)); - bs_set(mdp5_encoder, 0); - mdp5_encoder->enabled = false; } @@ -240,7 +175,6 @@ static void mdp5_vid_encoder_enable(struct drm_encoder *encoder) if (WARN_ON(mdp5_encoder->enabled)) return; - bs_set(mdp5_encoder, 1); spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intfn), 1); spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); @@ -426,8 +360,6 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, drm_encoder_helper_add(encoder, &mdp5_encoder_helper_funcs); - bs_init(mdp5_encoder); - return encoder; fail: -- GitLab From e1bf29e022fb48eabe3c3db9ab981ed56307c69b Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 13 Jul 2020 11:16:42 -0700 Subject: [PATCH 0759/1494] drm/msm: drop cache sync hack Now that it isn't causing problems to use dma_map/unmap, we can drop the hack of using dma_sync in certain cases. Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/msm_gem.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b2f49152b4d4c..3cb7aeb93fd3b 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -52,26 +52,16 @@ static void sync_for_device(struct msm_gem_object *msm_obj) { struct device *dev = msm_obj->base.dev->dev; - if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) { - dma_sync_sg_for_device(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); - } else { - dma_map_sg(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); - } + dma_map_sg(dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, DMA_BIDIRECTIONAL); } static void sync_for_cpu(struct msm_gem_object *msm_obj) { struct device *dev = msm_obj->base.dev->dev; - if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) { - dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); - } else { - dma_unmap_sg(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); - } + dma_unmap_sg(dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, DMA_BIDIRECTIONAL); } /* allocate pages from VRAM carveout, used when no IOMMU: */ -- GitLab From d768e5043c056822ef7ed1546e2d7134877ae6d1 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Fri, 14 Aug 2020 01:17:44 -0700 Subject: [PATCH 0760/1494] drm/msm/adreno: remove return value of function XX_print XX_print like pfp_print/me_print/meq_print/roq_print are just used in file a5xx_debugfs.c. And these function always return 0, this return value is meaningless. This change is to make the code a bit more readable. Signed-off-by: Bernard Zhao <bernard@vivo.com> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a5xx_debugfs.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c index 68eddac7771c1..fc2c905b6c9e9 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c @@ -11,7 +11,7 @@ #include "a5xx_gpu.h" -static int pfp_print(struct msm_gpu *gpu, struct drm_printer *p) +static void pfp_print(struct msm_gpu *gpu, struct drm_printer *p) { int i; @@ -22,11 +22,9 @@ static int pfp_print(struct msm_gpu *gpu, struct drm_printer *p) drm_printf(p, " %02x: %08x\n", i, gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA)); } - - return 0; } -static int me_print(struct msm_gpu *gpu, struct drm_printer *p) +static void me_print(struct msm_gpu *gpu, struct drm_printer *p) { int i; @@ -37,11 +35,9 @@ static int me_print(struct msm_gpu *gpu, struct drm_printer *p) drm_printf(p, " %02x: %08x\n", i, gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA)); } - - return 0; } -static int meq_print(struct msm_gpu *gpu, struct drm_printer *p) +static void meq_print(struct msm_gpu *gpu, struct drm_printer *p) { int i; @@ -52,11 +48,9 @@ static int meq_print(struct msm_gpu *gpu, struct drm_printer *p) drm_printf(p, " %02x: %08x\n", i, gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA)); } - - return 0; } -static int roq_print(struct msm_gpu *gpu, struct drm_printer *p) +static void roq_print(struct msm_gpu *gpu, struct drm_printer *p) { int i; @@ -71,8 +65,6 @@ static int roq_print(struct msm_gpu *gpu, struct drm_printer *p) drm_printf(p, " %02x: %08x %08x %08x %08x\n", i, val[0], val[1], val[2], val[3]); } - - return 0; } static int show(struct seq_file *m, void *arg) @@ -81,10 +73,11 @@ static int show(struct seq_file *m, void *arg) struct drm_device *dev = node->minor->dev; struct msm_drm_private *priv = dev->dev_private; struct drm_printer p = drm_seq_file_printer(m); - int (*show)(struct msm_gpu *gpu, struct drm_printer *p) = + void (*show)(struct msm_gpu *gpu, struct drm_printer *p) = node->info_ent->data; - return show(priv->gpu, &p); + show(priv->gpu, &p); + return 0; } #define ENT(n) { .name = #n, .show = show, .data = n ##_print } -- GitLab From b7b23e4476872d80b7d70cd24e158a0505fdad5f Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 23:51:01 +0200 Subject: [PATCH 0761/1494] drm/panel: s6e63m0: Break out SPI transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This panel can be accessed using both SPI and DSI. To make it possible to probe and use the device also from a DSI bus, first break out the SPI support to its own file. Since all the panel driver does is write DCS commands to the panel, we pass a DCS write function to probe() from each subdriver. We make the Kconfig entry for SPI mode default so all current users will continue to work. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Stephan Gerhold <stephan@gerhold.net> Cc: PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com> Acked-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/384873/ --- drivers/gpu/drm/panel/Kconfig | 15 +++- drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 89 +++++++++++++++++++ drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 79 +++------------- drivers/gpu/drm/panel/panel-samsung-s6e63m0.h | 10 +++ 5 files changed, 124 insertions(+), 70 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0.h diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 8d97d07c58713..f8d61e6addc34 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -324,13 +324,22 @@ config DRM_PANEL_SAMSUNG_S6E63J0X03 select VIDEOMODE_HELPERS config DRM_PANEL_SAMSUNG_S6E63M0 - tristate "Samsung S6E63M0 RGB/SPI panel" + tristate "Samsung S6E63M0 RGB panel" depends on OF - depends on SPI depends on BACKLIGHT_CLASS_DEVICE help Say Y here if you want to enable support for Samsung S6E63M0 - AMOLED LCD panel. + AMOLED LCD panel. This panel can be accessed using SPI or + DSI. + +config DRM_PANEL_SAMSUNG_S6E63M0_SPI + tristate "Samsung S6E63M0 RGB SPI interface" + depends on SPI + depends on DRM_PANEL_SAMSUNG_S6E63M0 + default DRM_PANEL_SAMSUNG_S6E63M0 + help + Say Y here if you want to be able to access the Samsung + S6E63M0 panel using SPI. config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller" diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 15a4e77529514..63f53bd886495 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6D16D0) += panel-samsung-s6d16d0.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c new file mode 100644 index 0000000000000..4082fbd75b79b --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/spi/spi.h> +#include <linux/delay.h> + +#include <drm/drm_print.h> + +#include "panel-samsung-s6e63m0.h" + +#define DATA_MASK 0x100 + +static int s6e63m0_spi_write_word(struct device *dev, u16 data) +{ + struct spi_device *spi = to_spi_device(dev); + struct spi_transfer xfer = { + .len = 2, + .tx_buf = &data, + }; + struct spi_message msg; + + spi_message_init(&msg); + spi_message_add_tail(&xfer, &msg); + + return spi_sync(spi, &msg); +} + +static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len) +{ + int ret = 0; + + DRM_DEV_DEBUG(dev, "SPI writing dcs seq: %*ph\n", (int)len, data); + ret = s6e63m0_spi_write_word(dev, *data); + + while (!ret && --len) { + ++data; + ret = s6e63m0_spi_write_word(dev, *data | DATA_MASK); + } + + if (ret) { + DRM_DEV_ERROR(dev, "SPI error %d writing dcs seq: %*ph\n", ret, + (int)len, data); + } + + usleep_range(300, 310); + + return ret; +} + +static int s6e63m0_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + int ret; + + spi->bits_per_word = 9; + spi->mode = SPI_MODE_3; + ret = spi_setup(spi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "spi setup failed.\n"); + return ret; + } + return s6e63m0_probe(dev, s6e63m0_spi_dcs_write); +} + +static int s6e63m0_spi_remove(struct spi_device *spi) +{ + return s6e63m0_remove(&spi->dev); +} + +static const struct of_device_id s6e63m0_spi_of_match[] = { + { .compatible = "samsung,s6e63m0" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, s6e63m0_spi_of_match); + +static struct spi_driver s6e63m0_spi_driver = { + .probe = s6e63m0_spi_probe, + .remove = s6e63m0_spi_remove, + .driver = { + .name = "panel-samsung-s6e63m0", + .of_match_table = s6e63m0_spi_of_match, + }, +}; +module_spi_driver(s6e63m0_spi_driver); + +MODULE_AUTHOR("PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com>"); +MODULE_DESCRIPTION("s6e63m0 LCD SPI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 2cc772fdc456d..64d95201a7d48 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -16,10 +16,11 @@ #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/regulator/consumer.h> -#include <linux/spi/spi.h> #include <video/mipi_display.h> +#include "panel-samsung-s6e63m0.h" + /* Manufacturer Command Set */ #define MCS_ELVSS_ON 0xb1 #define MCS_MIECTL1 0xc0 @@ -33,8 +34,6 @@ #define NUM_GAMMA_LEVELS 11 #define GAMMA_TABLE_COUNT 23 -#define DATA_MASK 0x100 - #define MAX_BRIGHTNESS (NUM_GAMMA_LEVELS - 1) /* array of gamma tables for gamma value 2.2 */ @@ -87,6 +86,7 @@ static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = { struct s6e63m0 { struct device *dev; + int (*dcs_write)(struct device *dev, const u8 *data, size_t len); struct drm_panel panel; struct backlight_device *bl_dev; @@ -134,42 +134,12 @@ static int s6e63m0_clear_error(struct s6e63m0 *ctx) return ret; } -static int s6e63m0_spi_write_word(struct s6e63m0 *ctx, u16 data) -{ - struct spi_device *spi = to_spi_device(ctx->dev); - struct spi_transfer xfer = { - .len = 2, - .tx_buf = &data, - }; - struct spi_message msg; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - return spi_sync(spi, &msg); -} - static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len) { - int ret = 0; - if (ctx->error < 0 || len == 0) return; - dev_dbg(ctx->dev, "writing dcs seq: %*ph\n", (int)len, data); - ret = s6e63m0_spi_write_word(ctx, *data); - - while (!ret && --len) { - ++data; - ret = s6e63m0_spi_write_word(ctx, *data | DATA_MASK); - } - - if (ret) { - dev_err(ctx->dev, "error %d writing dcs seq: %*ph\n", ret, (int)len, data); - ctx->error = ret; - } - - usleep_range(300, 310); + ctx->error = ctx->dcs_write(ctx->dev, data, len); } #define s6e63m0_dcs_write_seq_static(ctx, seq ...) \ @@ -429,9 +399,9 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx) return ret; } -static int s6e63m0_probe(struct spi_device *spi) +int s6e63m0_probe(struct device *dev, + int (*dcs_write)(struct device *dev, const u8 *data, size_t len)) { - struct device *dev = &spi->dev; struct s6e63m0 *ctx; int ret; @@ -439,7 +409,8 @@ static int s6e63m0_probe(struct spi_device *spi) if (!ctx) return -ENOMEM; - spi_set_drvdata(spi, ctx); + ctx->dcs_write = dcs_write; + dev_set_drvdata(dev, ctx); ctx->dev = dev; ctx->enabled = false; @@ -460,14 +431,6 @@ static int s6e63m0_probe(struct spi_device *spi) return PTR_ERR(ctx->reset_gpio); } - spi->bits_per_word = 9; - spi->mode = SPI_MODE_3; - ret = spi_setup(spi); - if (ret < 0) { - dev_err(dev, "spi setup failed.\n"); - return ret; - } - drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs, DRM_MODE_CONNECTOR_DPI); @@ -479,32 +442,14 @@ static int s6e63m0_probe(struct spi_device *spi) return 0; } +EXPORT_SYMBOL_GPL(s6e63m0_probe); -static int s6e63m0_remove(struct spi_device *spi) +int s6e63m0_remove(struct device *dev) { - struct s6e63m0 *ctx = spi_get_drvdata(spi); + struct s6e63m0 *ctx = dev_get_drvdata(dev); drm_panel_remove(&ctx->panel); return 0; } - -static const struct of_device_id s6e63m0_of_match[] = { - { .compatible = "samsung,s6e63m0" }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, s6e63m0_of_match); - -static struct spi_driver s6e63m0_driver = { - .probe = s6e63m0_probe, - .remove = s6e63m0_remove, - .driver = { - .name = "panel-samsung-s6e63m0", - .of_match_table = s6e63m0_of_match, - }, -}; -module_spi_driver(s6e63m0_driver); - -MODULE_AUTHOR("PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com>"); -MODULE_DESCRIPTION("s6e63m0 LCD Driver"); -MODULE_LICENSE("GPL v2"); +EXPORT_SYMBOL_GPL(s6e63m0_remove); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h new file mode 100644 index 0000000000000..44e31f39f211b --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _PANEL_SAMSUNG_S6E63M0_H +#define _PANEL_SAMSUNG_S6E63M0_H + +int s6e63m0_probe(struct device *dev, + int (*dcs_write)(struct device *dev, const u8 *data, size_t len)); +int s6e63m0_remove(struct device *dev); + +#endif /* _PANEL_SAMSUNG_S6E63M0_H */ -- GitLab From 435e06c06cb2e3bd2f650a52641ddb13a95a1624 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 23:51:02 +0200 Subject: [PATCH 0762/1494] drm/panel: s6e63m0: Add DSI transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it possible to use the s6e63m0 panel with a DSI host, such as in the Samsung GT-I8190 (Golden) mobile phone. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Stephan Gerhold <stephan@gerhold.net> Cc: Stephan Gerhold <stephan@gerhold.net> Cc: PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com> Acked-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200809215104.1830206-3-linus.walleij@linaro.org --- drivers/gpu/drm/panel/Kconfig | 8 ++ drivers/gpu/drm/panel/Makefile | 1 + .../gpu/drm/panel/panel-samsung-s6e63m0-dsi.c | 128 ++++++++++++++++++ .../gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 2 +- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 4 +- drivers/gpu/drm/panel/panel-samsung-s6e63m0.h | 4 +- 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index f8d61e6addc34..b9dbedf8f15e8 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -341,6 +341,14 @@ config DRM_PANEL_SAMSUNG_S6E63M0_SPI Say Y here if you want to be able to access the Samsung S6E63M0 panel using SPI. +config DRM_PANEL_SAMSUNG_S6E63M0_DSI + tristate "Samsung S6E63M0 RGB DSI interface" + depends on DRM_MIPI_DSI + depends on DRM_PANEL_SAMSUNG_S6E63M0 + help + Say Y here if you want to be able to access the Samsung + S6E63M0 panel using DSI. + config DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01 tristate "Samsung AMS452EF01 panel with S6E88A0 DSI video mode controller" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 63f53bd886495..2ba560bca61d7 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0) += panel-samsung-s6e63m0.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_SPI) += panel-samsung-s6e63m0-spi.o +obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63M0_DSI) += panel-samsung-s6e63m0-dsi.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E88A0_AMS452EF01) += panel-samsung-s6e88a0-ams452ef01.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o obj-$(CONFIG_DRM_PANEL_SEIKO_43WVF1G) += panel-seiko-43wvf1g.o diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c new file mode 100644 index 0000000000000..f4927a6ce26d0 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * DSI interface to the Samsung S6E63M0 panel. + * (C) 2019 Linus Walleij + */ + +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/of_device.h> + +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_print.h> + +#include "panel-samsung-s6e63m0.h" + +#define MCS_GLOBAL_PARAM 0xb0 +#define S6E63M0_DSI_MAX_CHUNK 15 /* CMD + 15 bytes max */ + +static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + const u8 *seqp = data; + u8 cmd; + u8 cmdwritten; + int remain; + int chunk; + int ret; + + DRM_DEV_INFO(dev, "DSI writing dcs seq: %*ph\n", (int)len, data); + + /* Pick out and skip past the DCS command */ + cmd = *seqp; + seqp++; + cmdwritten = 0; + remain = len - 1; + chunk = remain; + + /* Send max S6E63M0_DSI_MAX_CHUNK bytes at a time */ + if (chunk > S6E63M0_DSI_MAX_CHUNK) + chunk = S6E63M0_DSI_MAX_CHUNK; + ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk); + if (ret < 0) { + DRM_DEV_ERROR(dev, + "error sending DCS command seq cmd %02x\n", + cmd); + return ret; + } + cmdwritten += chunk; + seqp += chunk; + + while (cmdwritten < remain) { + chunk = remain - cmdwritten; + if (chunk > S6E63M0_DSI_MAX_CHUNK) + chunk = S6E63M0_DSI_MAX_CHUNK; + ret = mipi_dsi_dcs_write(dsi, MCS_GLOBAL_PARAM, &cmdwritten, 1); + if (ret < 0) { + DRM_DEV_ERROR(dev, + "error sending CMD %02x global param %02x\n", + cmd, cmdwritten); + return ret; + } + ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk); + if (ret < 0) { + DRM_DEV_ERROR(dev, + "error sending CMD %02x chunk\n", + cmd); + return ret; + } + cmdwritten += chunk; + seqp += chunk; + } + DRM_DEV_INFO(dev, "sent command %02x %02x bytes\n", + cmd, cmdwritten); + + usleep_range(8000, 9000); + + return 0; +} + +static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + int ret; + + dsi->lanes = 2; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->hs_rate = 349440000; + dsi->lp_rate = 9600000; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_EOT_PACKET | + MIPI_DSI_MODE_VIDEO_BURST; + + ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_write, true); + if (ret) + return ret; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) + s6e63m0_remove(dev); + + return ret; +} + +static int s6e63m0_dsi_remove(struct mipi_dsi_device *dsi) +{ + mipi_dsi_detach(dsi); + return s6e63m0_remove(&dsi->dev); +} + +static const struct of_device_id s6e63m0_dsi_of_match[] = { + { .compatible = "samsung,s6e63m0" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, s6e63m0_dsi_of_match); + +static struct mipi_dsi_driver s6e63m0_dsi_driver = { + .probe = s6e63m0_dsi_probe, + .remove = s6e63m0_dsi_remove, + .driver = { + .name = "panel-samsung-s6e63m0", + .of_match_table = s6e63m0_dsi_of_match, + }, +}; +module_mipi_dsi_driver(s6e63m0_dsi_driver); + +MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>"); +MODULE_DESCRIPTION("s6e63m0 LCD DSI Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index 4082fbd75b79b..0587eac52f2aa 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -60,7 +60,7 @@ static int s6e63m0_spi_probe(struct spi_device *spi) DRM_DEV_ERROR(dev, "spi setup failed.\n"); return ret; } - return s6e63m0_probe(dev, s6e63m0_spi_dcs_write); + return s6e63m0_probe(dev, s6e63m0_spi_dcs_write, false); } static int s6e63m0_spi_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 64d95201a7d48..260c51642b25e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -400,7 +400,8 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx) } int s6e63m0_probe(struct device *dev, - int (*dcs_write)(struct device *dev, const u8 *data, size_t len)) + int (*dcs_write)(struct device *dev, const u8 *data, size_t len), + bool dsi_mode) { struct s6e63m0 *ctx; int ret; @@ -432,6 +433,7 @@ int s6e63m0_probe(struct device *dev, } drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs, + dsi_mode ? DRM_MODE_CONNECTOR_DSI : DRM_MODE_CONNECTOR_DPI); ret = s6e63m0_backlight_register(ctx); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h index 44e31f39f211b..229e23b0c97a2 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h @@ -4,7 +4,9 @@ #define _PANEL_SAMSUNG_S6E63M0_H int s6e63m0_probe(struct device *dev, - int (*dcs_write)(struct device *dev, const u8 *data, size_t len)); + int (*dcs_write)(struct device *dev, const u8 *data, + size_t len), + bool dsi_mode); int s6e63m0_remove(struct device *dev); #endif /* _PANEL_SAMSUNG_S6E63M0_H */ -- GitLab From 91867ac7d6724c31f32c3a63e2bb5db978893eaf Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 23:51:03 +0200 Subject: [PATCH 0763/1494] drm/panel: s6e63m0: Add reading functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds code to send read commands to read a single byte from the display, in order to perform MTP ID look-up of the mounted panel on the s6e63m0 controller. This is needed for proper biasing on the DSI variants. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Stephan Gerhold <stephan@gerhold.net> Cc: PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com> Acked-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200809215104.1830206-4-linus.walleij@linaro.org --- .../gpu/drm/panel/panel-samsung-s6e63m0-dsi.c | 19 ++++++++++++++++++- .../gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 14 +++++++++++++- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 11 +++++++++++ drivers/gpu/drm/panel/panel-samsung-s6e63m0.h | 1 + 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c index f4927a6ce26d0..2ec9e7900791e 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c @@ -16,6 +16,22 @@ #define MCS_GLOBAL_PARAM 0xb0 #define S6E63M0_DSI_MAX_CHUNK 15 /* CMD + 15 bytes max */ +static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data) +{ + struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + int ret; + + ret = mipi_dsi_dcs_read(dsi, cmd, data, 1); + if (ret < 0) { + DRM_DEV_ERROR(dev, "could not read DCS CMD %02x\n", cmd); + return ret; + } + + DRM_DEV_INFO(dev, "DSI read CMD %02x = %02x\n", cmd, *data); + + return 0; +} + static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len) { struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); @@ -90,7 +106,8 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi) MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_BURST; - ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_write, true); + ret = s6e63m0_probe(dev, s6e63m0_dsi_dcs_read, s6e63m0_dsi_dcs_write, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index 0587eac52f2aa..3b1a2a3a44ea5 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -11,6 +11,17 @@ #define DATA_MASK 0x100 +static int s6e63m0_spi_dcs_read(struct device *dev, const u8 cmd, u8 *data) +{ + /* + * FIXME: implement reading DCS commands over SPI so we can + * properly identify which physical panel is connected. + */ + *data = 0; + + return 0; +} + static int s6e63m0_spi_write_word(struct device *dev, u16 data) { struct spi_device *spi = to_spi_device(dev); @@ -60,7 +71,8 @@ static int s6e63m0_spi_probe(struct spi_device *spi) DRM_DEV_ERROR(dev, "spi setup failed.\n"); return ret; } - return s6e63m0_probe(dev, s6e63m0_spi_dcs_write, false); + return s6e63m0_probe(dev, s6e63m0_spi_dcs_read, s6e63m0_spi_dcs_write, + false); } static int s6e63m0_spi_remove(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 260c51642b25e..c53706edee44f 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -86,6 +86,7 @@ static u8 const s6e63m0_gamma_22[NUM_GAMMA_LEVELS][GAMMA_TABLE_COUNT] = { struct s6e63m0 { struct device *dev; + int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val); int (*dcs_write)(struct device *dev, const u8 *data, size_t len); struct drm_panel panel; struct backlight_device *bl_dev; @@ -134,6 +135,14 @@ static int s6e63m0_clear_error(struct s6e63m0 *ctx) return ret; } +static void s6e63m0_dcs_read(struct s6e63m0 *ctx, const u8 cmd, u8 *data) +{ + if (ctx->error < 0) + return; + + ctx->error = ctx->dcs_read(ctx->dev, cmd, data); +} + static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len) { if (ctx->error < 0 || len == 0) @@ -400,6 +409,7 @@ static int s6e63m0_backlight_register(struct s6e63m0 *ctx) } int s6e63m0_probe(struct device *dev, + int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val), int (*dcs_write)(struct device *dev, const u8 *data, size_t len), bool dsi_mode) { @@ -410,6 +420,7 @@ int s6e63m0_probe(struct device *dev, if (!ctx) return -ENOMEM; + ctx->dcs_read = dcs_read; ctx->dcs_write = dcs_write; dev_set_drvdata(dev, ctx); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h index 229e23b0c97a2..c669fec917631 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.h @@ -4,6 +4,7 @@ #define _PANEL_SAMSUNG_S6E63M0_H int s6e63m0_probe(struct device *dev, + int (*dcs_read)(struct device *dev, const u8 cmd, u8 *val), int (*dcs_write)(struct device *dev, const u8 *data, size_t len), bool dsi_mode); -- GitLab From 83ba7a7b3d4a70fe92122f039539566c9526228c Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 9 Aug 2020 23:51:04 +0200 Subject: [PATCH 0764/1494] drm/panel: s6e63m0: Add code to identify panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We add code to identify a few different panels mounted on the s6e63m0 controller. This is necessary to achieve the proper biasing with DSI versions of the panel. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Stephan Gerhold <stephan@gerhold.net> Cc: PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com> Acked-by: Paul Cercueil <paul@crapouillou.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200809215104.1830206-5-linus.walleij@linaro.org --- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index c53706edee44f..842f8221be157 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -25,12 +25,21 @@ #define MCS_ELVSS_ON 0xb1 #define MCS_MIECTL1 0xc0 #define MCS_BCMODE 0xc1 +#define MCS_READ_ID1 0xda +#define MCS_READ_ID2 0xdb +#define MCS_READ_ID3 0xdc +#define MCS_LEVEL_2_KEY 0xf0 +#define MCS_MTP_KEY 0xf1 #define MCS_DISCTL 0xf2 #define MCS_SRCCTL 0xf6 #define MCS_IFCTL 0xf7 #define MCS_PANELCTL 0xF8 #define MCS_PGAMMACTL 0xfa +#define S6E63M0_LCD_ID_VALUE_M2 0xA4 +#define S6E63M0_LCD_ID_VALUE_SM2 0xB4 +#define S6E63M0_LCD_ID_VALUE_SM2_1 0xB6 + #define NUM_GAMMA_LEVELS 11 #define GAMMA_TABLE_COUNT 23 @@ -90,6 +99,7 @@ struct s6e63m0 { int (*dcs_write)(struct device *dev, const u8 *data, size_t len); struct drm_panel panel; struct backlight_device *bl_dev; + u8 lcd_type; struct regulator_bulk_data supplies[2]; struct gpio_desc *reset_gpio; @@ -157,6 +167,47 @@ static void s6e63m0_dcs_write(struct s6e63m0 *ctx, const u8 *data, size_t len) s6e63m0_dcs_write(ctx, d, ARRAY_SIZE(d)); \ }) +static int s6e63m0_check_lcd_type(struct s6e63m0 *ctx) +{ + u8 id1, id2, id3; + int ret; + + s6e63m0_dcs_read(ctx, MCS_READ_ID1, &id1); + s6e63m0_dcs_read(ctx, MCS_READ_ID2, &id2); + s6e63m0_dcs_read(ctx, MCS_READ_ID3, &id3); + + ret = s6e63m0_clear_error(ctx); + if (ret) { + DRM_DEV_ERROR(ctx->dev, "error checking LCD type (%d)\n", + ret); + ctx->lcd_type = 0x00; + return ret; + } + + DRM_DEV_INFO(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3); + + /* We attempt to detect what panel is mounted on the controller */ + switch (id2) { + case S6E63M0_LCD_ID_VALUE_M2: + DRM_DEV_INFO(ctx->dev, + "detected LCD panel AMS397GE MIPI M2\n"); + break; + case S6E63M0_LCD_ID_VALUE_SM2: + case S6E63M0_LCD_ID_VALUE_SM2_1: + DRM_DEV_INFO(ctx->dev, + "detected LCD panel AMS397GE MIPI SM2\n"); + break; + default: + DRM_DEV_INFO(ctx->dev, + "unknown LCD panel type %02x\n", id2); + break; + } + + ctx->lcd_type = id2; + + return 0; +} + static void s6e63m0_init(struct s6e63m0 *ctx) { s6e63m0_dcs_write_seq_static(ctx, MCS_PANELCTL, @@ -310,6 +361,15 @@ static int s6e63m0_prepare(struct drm_panel *panel) if (ret < 0) return ret; + /* Magic to unlock level 2 control of the display */ + s6e63m0_dcs_write_seq_static(ctx, MCS_LEVEL_2_KEY, 0x5a, 0x5a); + /* Magic to unlock MTP reading */ + s6e63m0_dcs_write_seq_static(ctx, MCS_MTP_KEY, 0x5a, 0x5a); + + ret = s6e63m0_check_lcd_type(ctx); + if (ret < 0) + return ret; + s6e63m0_init(ctx); ret = s6e63m0_clear_error(ctx); -- GitLab From ec219f1ba23777c84e913b08e192413eea22d220 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Mon, 17 Aug 2020 23:39:06 +0200 Subject: [PATCH 0765/1494] drm/panel: s6e63m0: Order enable/disable sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upstream S6E63M0 driver has some peculiarities around the prepare/enable disable/unprepare sequence: the screen is taken out of sleep in prepare() as part of s6e63m0_init() the put to on with MIPI_DCS_SET_DISPLAY_ON in enable(). However it is just put into sleep mode directly in disable(). As disable()/enable() can be called without unprepare()/prepare() being called, this is unbalanced, we should take the display out of sleep in enable() then turn it off(). Further MIPI_DCS_SET_DISPLAY_OFF is never called balanced with MIPI_DCS_SET_DISPLAY_ON. The vendor driver for Samsung GT-I8190 (Golden) does all of these things in strict order. Augment the driver to do exit sleep/set display on in enable() and set display off/enter sleep in disable(). Further send an explicit reset pulse in power_on() so we come up in a known state, and issue the MCS_ERROR_CHECK command after setting display on like the vendor driver does. Also use the timings from the vendor driver in the sequence. Doing all of these things makes the display much more stable on the Samsung GT-I8190 when enabling/disabling the display pipeline. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com> Cc: Stephan Gerhold <stephan@gerhold.net> Link: https://patchwork.freedesktop.org/patch/msgid/20200817213906.88207-1-linus.walleij@linaro.org --- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 842f8221be157..c9472b2ae0cd1 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -25,6 +25,7 @@ #define MCS_ELVSS_ON 0xb1 #define MCS_MIECTL1 0xc0 #define MCS_BCMODE 0xc1 +#define MCS_ERROR_CHECK 0xd5 #define MCS_READ_ID1 0xda #define MCS_READ_ID2 0xdb #define MCS_READ_ID3 0xdc @@ -279,8 +280,6 @@ static void s6e63m0_init(struct s6e63m0 *ctx) s6e63m0_dcs_write_seq_static(ctx, MCS_ELVSS_ON, 0x0b); - - s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE); } static int s6e63m0_power_on(struct s6e63m0 *ctx) @@ -293,6 +292,9 @@ static int s6e63m0_power_on(struct s6e63m0 *ctx) msleep(25); + /* Be sure to send a reset pulse */ + gpiod_set_value(ctx->reset_gpio, 1); + msleep(5); gpiod_set_value(ctx->reset_gpio, 0); msleep(120); @@ -322,8 +324,10 @@ static int s6e63m0_disable(struct drm_panel *panel) backlight_disable(ctx->bl_dev); + s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_OFF); + msleep(10); s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_ENTER_SLEEP_MODE); - msleep(200); + msleep(120); ctx->enabled = false; @@ -389,7 +393,15 @@ static int s6e63m0_enable(struct drm_panel *panel) if (ctx->enabled) return 0; + s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_EXIT_SLEEP_MODE); + msleep(120); s6e63m0_dcs_write_seq_static(ctx, MIPI_DCS_SET_DISPLAY_ON); + msleep(10); + + s6e63m0_dcs_write_seq_static(ctx, MCS_ERROR_CHECK, + 0xE7, 0x14, 0x60, 0x17, 0x0A, 0x49, 0xC3, + 0x8F, 0x19, 0x64, 0x91, 0x84, 0x76, 0x20, + 0x0F, 0x00); backlight_enable(ctx->bl_dev); -- GitLab From 96f51a4d43508e7d916caac02e382123d299c0d7 Mon Sep 17 00:00:00 2001 From: CK Hu <ck.hu@mediatek.com> Date: Thu, 9 May 2019 10:21:37 +0800 Subject: [PATCH 0766/1494] drm/mediatek: Move tz_disabled from mtk_hdmi_phy to mtk_hdmi driver tz_disabled is used to control mtk_hdmi output signal, but this variable is stored in mtk_hdmi_phy and mtk_hdmi_phy does not use it. So move tz_disabled to mtk_hdmi where it's used. Signed-off-by: CK Hu <ck.hu@mediatek.com> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> Tested-by: Frank Wunderlich <frank-w@public-files.de> --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 19 ++++++++++++++++--- drivers/gpu/drm/mediatek/mtk_hdmi_phy.h | 1 - .../gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c | 1 - 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index f2e9b429960b9..d44348c7ecbef 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -145,11 +145,16 @@ struct hdmi_audio_param { struct hdmi_codec_params codec_params; }; +struct mtk_hdmi_conf { + bool tz_disabled; +}; + struct mtk_hdmi { struct drm_bridge bridge; struct drm_bridge *next_bridge; struct drm_connector conn; struct device *dev; + const struct mtk_hdmi_conf *conf; struct phy *phy; struct device *cec_dev; struct i2c_adapter *ddc_adpt; @@ -234,7 +239,6 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) { struct arm_smccc_res res; - struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(hdmi->phy); /* * MT8173 HDMI hardware has an output control bit to enable/disable HDMI @@ -242,7 +246,7 @@ static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) * The ARM trusted firmware provides an API for the HDMI driver to set * this control bit to enable HDMI output in supervisor mode. */ - if (hdmi_phy->conf && hdmi_phy->conf->tz_disabled) + if (hdmi->conf && hdmi->conf->tz_disabled) regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, 0x80008005, enable ? 0x80000005 : 0x8000); @@ -1723,6 +1727,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return -ENOMEM; hdmi->dev = dev; + hdmi->conf = of_device_get_match_data(dev); ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev); if (ret) @@ -1803,8 +1808,16 @@ static int mtk_hdmi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(mtk_hdmi_pm_ops, mtk_hdmi_suspend, mtk_hdmi_resume); +static const struct mtk_hdmi_conf mtk_hdmi_conf_mt2701 = { + .tz_disabled = true, +}; + static const struct of_device_id mtk_drm_hdmi_of_ids[] = { - { .compatible = "mediatek,mt8173-hdmi", }, + { .compatible = "mediatek,mt2701-hdmi", + .data = &mtk_hdmi_conf_mt2701, + }, + { .compatible = "mediatek,mt8173-hdmi", + }, {} }; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h index 2d8b3182470dc..fc1c2efd11284 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h @@ -20,7 +20,6 @@ struct mtk_hdmi_phy; struct mtk_hdmi_phy_conf { - bool tz_disabled; unsigned long flags; const struct clk_ops *hdmi_phy_clk_ops; void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy); diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c index d3cc4022e9884..99fe05cd3598c 100644 --- a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c +++ b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c @@ -237,7 +237,6 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy) } struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = { - .tz_disabled = true, .flags = CLK_SET_RATE_GATE, .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops, .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds, -- GitLab From a481bf2f0ca43c6476229d5bc4c3f6b9404de863 Mon Sep 17 00:00:00 2001 From: CK Hu <ck.hu@mediatek.com> Date: Fri, 10 May 2019 16:47:15 +0800 Subject: [PATCH 0767/1494] drm/mediatek: Separate mtk_hdmi_phy to an independent module mtk_hdmi_phy is a part of mtk_hdmi module, but phy driver should be an independent module rather than be part of drm module, so separate the phy driver to an independent module. Signed-off-by: CK Hu <ck.hu@mediatek.com> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> Tested-by: Frank Wunderlich <frank-w@public-files.de> --- drivers/gpu/drm/mediatek/Kconfig | 9 ++++++++- drivers/gpu/drm/mediatek/Makefile | 11 +++++++---- drivers/gpu/drm/mediatek/mtk_hdmi.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi.h | 1 - drivers/gpu/drm/mediatek/mtk_hdmi_phy.c | 1 + drivers/gpu/drm/mediatek/mtk_hdmi_phy.h | 1 - 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index aa74aac3cbccd..6363f2c1cdbc2 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -24,6 +24,13 @@ config DRM_MEDIATEK_HDMI tristate "DRM HDMI Support for Mediatek SoCs" depends on DRM_MEDIATEK select SND_SOC_HDMI_CODEC if SND_SOC - select GENERIC_PHY + select PHY_MTK_HDMI help DRM/KMS HDMI driver for Mediatek SoCs + +config PHY_MTK_HDMI + tristate "MediaTek HDMI-PHY Driver" + depends on ARCH_MEDIATEK && OF + select GENERIC_PHY + help + Support HDMI PHY for Mediatek SoCs. diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index b7a82ed5788f7..fcbef23aa6cec 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -19,9 +19,12 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi.o \ - mtk_hdmi_ddc.o \ - mtk_mt2701_hdmi_phy.o \ - mtk_mt8173_hdmi_phy.o \ - mtk_hdmi_phy.o + mtk_hdmi_ddc.o obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o + +phy-mtk-hdmi-drv-objs := mtk_hdmi_phy.o \ + mtk_mt2701_hdmi_phy.o \ + mtk_mt8173_hdmi_phy.o + +obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index d44348c7ecbef..0ed7b0b1a022a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> +#include <linux/module.h> #include <linux/mutex.h> #include <linux/of_platform.h> #include <linux/of.h> @@ -1832,7 +1833,6 @@ static struct platform_driver mtk_hdmi_driver = { }; static struct platform_driver * const mtk_hdmi_drivers[] = { - &mtk_hdmi_phy_driver, &mtk_hdmi_ddc_driver, &mtk_cec_driver, &mtk_hdmi_driver, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h index bb3653de6bd15..472bf141c92bb 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h @@ -5,7 +5,6 @@ */ #ifndef _MTK_HDMI_CTRL_H #define _MTK_HDMI_CTRL_H -#include "mtk_hdmi_phy.h" struct platform_driver; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c index 5223498502c49..fe022acddbef2 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c @@ -205,6 +205,7 @@ struct platform_driver mtk_hdmi_phy_driver = { .of_match_table = mtk_hdmi_phy_match, }, }; +module_platform_driver(mtk_hdmi_phy_driver); MODULE_DESCRIPTION("MediaTek HDMI PHY Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h index fc1c2efd11284..b13e1d5f8e785 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h @@ -49,7 +49,6 @@ void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset, u32 val, u32 mask); struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw); -extern struct platform_driver mtk_hdmi_phy_driver; extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf; extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf; -- GitLab From b28be59a2e2668b35507553e0de135c29ebd71ef Mon Sep 17 00:00:00 2001 From: CK Hu <ck.hu@mediatek.com> Date: Mon, 13 May 2019 10:22:25 +0800 Subject: [PATCH 0768/1494] phy: mediatek: Move mtk_hdmi_phy driver into drivers/phy/mediatek folder mtk_hdmi_phy is currently placed inside mediatek drm driver, but it's more suitable to place a phy driver into phy driver folder, so move mtk_hdmi_phy driver into phy driver folder. Signed-off-by: CK Hu <ck.hu@mediatek.com> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> Acked-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Tested-by: Frank Wunderlich <frank-w@public-files.de> --- drivers/gpu/drm/mediatek/Kconfig | 7 ------- drivers/gpu/drm/mediatek/Makefile | 6 ------ drivers/phy/mediatek/Kconfig | 7 +++++++ drivers/phy/mediatek/Makefile | 5 +++++ .../mediatek/phy-mtk-hdmi-mt2701.c} | 2 +- .../mediatek/phy-mtk-hdmi-mt8173.c} | 2 +- .../mtk_hdmi_phy.c => phy/mediatek/phy-mtk-hdmi.c} | 2 +- .../mtk_hdmi_phy.h => phy/mediatek/phy-mtk-hdmi.h} | 0 8 files changed, 15 insertions(+), 16 deletions(-) rename drivers/{gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c => phy/mediatek/phy-mtk-hdmi-mt2701.c} (99%) rename drivers/{gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c => phy/mediatek/phy-mtk-hdmi-mt8173.c} (99%) rename drivers/{gpu/drm/mediatek/mtk_hdmi_phy.c => phy/mediatek/phy-mtk-hdmi.c} (99%) rename drivers/{gpu/drm/mediatek/mtk_hdmi_phy.h => phy/mediatek/phy-mtk-hdmi.h} (100%) diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 6363f2c1cdbc2..65cd03a4be294 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -27,10 +27,3 @@ config DRM_MEDIATEK_HDMI select PHY_MTK_HDMI help DRM/KMS HDMI driver for Mediatek SoCs - -config PHY_MTK_HDMI - tristate "MediaTek HDMI-PHY Driver" - depends on ARCH_MEDIATEK && OF - select GENERIC_PHY - help - Support HDMI PHY for Mediatek SoCs. diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index fcbef23aa6cec..77b0fd86063d3 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -22,9 +22,3 @@ mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi_ddc.o obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o - -phy-mtk-hdmi-drv-objs := mtk_hdmi_phy.o \ - mtk_mt2701_hdmi_phy.o \ - mtk_mt8173_hdmi_phy.o - -obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig index dee757c957f2f..50c5e9306e19b 100644 --- a/drivers/phy/mediatek/Kconfig +++ b/drivers/phy/mediatek/Kconfig @@ -35,3 +35,10 @@ config PHY_MTK_XSPHY Enable this to support the SuperSpeedPlus XS-PHY transceiver for USB3.1 GEN2 controllers on MediaTek chips. The driver supports multiple USB2.0, USB3.1 GEN2 ports. + +config PHY_MTK_HDMI + tristate "MediaTek HDMI-PHY Driver" + depends on ARCH_MEDIATEK && OF + select GENERIC_PHY + help + Support HDMI PHY for Mediatek SoCs. diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index 08a8e6a97b1ed..6325e38709eda 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile @@ -6,3 +6,8 @@ obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_MTK_UFS) += phy-mtk-ufs.o obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o + +phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o +phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o +phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8173.o +obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c similarity index 99% rename from drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c rename to drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c index 99fe05cd3598c..a6cb1dea3d0ce 100644 --- a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c @@ -4,7 +4,7 @@ * Author: Chunhui Dai <chunhui.dai@mediatek.com> */ -#include "mtk_hdmi_phy.h" +#include "phy-mtk-hdmi.h" #define HDMI_CON0 0x00 #define RG_HDMITX_DRV_IBIAS 0 diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c similarity index 99% rename from drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c rename to drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c index 827b93786facb..6cdfdf5a698a4 100644 --- a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8173.c @@ -4,7 +4,7 @@ * Author: Jie Qiu <jie.qiu@mediatek.com> */ -#include "mtk_hdmi_phy.h" +#include "phy-mtk-hdmi.h" #define HDMI_CON0 0x00 #define RG_HDMITX_PLL_EN BIT(31) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/phy/mediatek/phy-mtk-hdmi.c similarity index 99% rename from drivers/gpu/drm/mediatek/mtk_hdmi_phy.c rename to drivers/phy/mediatek/phy-mtk-hdmi.c index fe022acddbef2..8fc83f01a7206 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c @@ -4,7 +4,7 @@ * Author: Jie Qiu <jie.qiu@mediatek.com> */ -#include "mtk_hdmi_phy.h" +#include "phy-mtk-hdmi.h" static int mtk_hdmi_phy_power_on(struct phy *phy); static int mtk_hdmi_phy_power_off(struct phy *phy); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/phy/mediatek/phy-mtk-hdmi.h similarity index 100% rename from drivers/gpu/drm/mediatek/mtk_hdmi_phy.h rename to drivers/phy/mediatek/phy-mtk-hdmi.h -- GitLab From 1b0ce63bc08eb65c85b3546c21e7715ccfbd6107 Mon Sep 17 00:00:00 2001 From: Chun-Kuang Hu <chunkuang.hu@kernel.org> Date: Sun, 22 Mar 2020 22:56:06 +0800 Subject: [PATCH 0769/1494] MAINTAINERS: add files for Mediatek DRM drivers Mediatek HDMI phy driver is moved from drivers/gpu/drm/mediatek to drivers/phy/mediatek, so add the new folder to the Mediatek DRM drivers' information. Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> Acked-by: Chunfeng Yun <chunfeng.yun@mediatek.com> --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index deaafb617361c..191bacf02209f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5793,6 +5793,7 @@ L: dri-devel@lists.freedesktop.org S: Supported F: Documentation/devicetree/bindings/display/mediatek/ F: drivers/gpu/drm/mediatek/ +F: drivers/phy/mediatek/phy-mtk-hdmi* DRM DRIVERS FOR NVIDIA TEGRA M: Thierry Reding <thierry.reding@gmail.com> -- GitLab From 5e31ee84c05239c2eb08250ed9858af117b55fe9 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:21 +0200 Subject: [PATCH 0770/1494] ACPI / LPSS: Resume Cherry Trail PWM controller in no-irq phase The DSDTs on most Cherry Trail devices have an ugly clutch where the PWM controller gets poked from the _PS0 method of the graphics-card device: Local0 = PSAT /* \_SB_.PCI0.GFX0.PSAT */ If (((Local0 & 0x03) == 0x03)) { PSAT &= 0xFFFFFFFC Local1 = PSAT /* \_SB_.PCI0.GFX0.PSAT */ RSTA = Zero RSTF = Zero RSTA = One RSTF = One PWMB |= 0xC0000000 PWMC = PWMB /* \_SB_.PCI0.GFX0.PWMB */ } Where PSAT is the power-status register of the PWM controller, so if it is in D3 when the GFX0 device's PS0 method runs then it will turn it on and restore the PWM ctrl register value it saved from its PS3 handler. Note not only does it restore it, it ors it with 0xC0000000 turning it on at a time where we may not want it to get turned on at all. The pwm_get call which the i915 driver does to get a reference to the PWM controller, already adds a device-link making the GFX0 device a consumer of the PWM device. So it should already have been resumed when the above AML runs and the AML should thus not do its undesirable poking of the PWM controller register. But the PCI core powers on PCI devices in the no-irq resume phase and thus calls the troublesome PS0 method in the no-irq resume phase. Where as LPSS devices by default are resumed in the early resume phase. This commit sets the resume_from_noirq flag in the bsw_pwm_dev_desc struct, so that Cherry Trail PWM controllers will be resumed in the no-irq phase. Together with the device-link added by the pwm-get this ensures that the PWM controller will be on when the troublesome PS0 method runs, which stops it from poking the PWM controller. Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-2-hdegoede@redhat.com --- drivers/acpi/acpi_lpss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 5e2bfbcf526f3..67892fc0b822f 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -257,6 +257,7 @@ static const struct lpss_device_desc bsw_pwm_dev_desc = { .flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, .prv_offset = 0x800, .setup = bsw_pwm_setup, + .resume_from_noirq = true, }; static const struct lpss_device_desc byt_uart_dev_desc = { -- GitLab From 15aa5e4c4328c4060cc662105a7b4c107a072ff3 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:22 +0200 Subject: [PATCH 0771/1494] ACPI / LPSS: Save Cherry Trail PWM ctx registers only once (at activation) The DSDTs on most Cherry Trail devices have an ugly clutch where the PWM controller gets turned off from the _PS3 method of the graphics-card dev: Method (_PS3, 0, Serialized) // _PS3: Power State 3 { ... PWMB = PWMC /* \_SB_.PCI0.GFX0.PWMC */ PSAT |= 0x03 Local0 = PSAT /* \_SB_.PCI0.GFX0.PSAT */ ... } Where PSAT is the power-status register of the PWM controller. Since the i915 driver will do a pwm_get on the pwm device as it uses it to control the LCD panel backlight, there is a device-link marking the i915 device as a consumer of the pwm device. So that the PWM controller will always be suspended after the i915 driver suspends (which is the right thing to do). This causes the above GFX0 PS3 AML code to run before acpi_lpss.c calls acpi_lpss_save_ctx(). So on these devices the PWM controller will already be off when acpi_lpss_save_ctx() runs. This causes it to read/save all 1-s (0xffffffff) as ctx register values. When these bogus values get restored on resume the PWM controller actually keeps working, since most bits are reserved, but this does set bit 3 of the LPSS General purpose register, which for the PWM controller has the following function: "This bit is re-used to support 32kHz slow mode. Default is 19.2MHz as PWM source clock". This causes the clock of the PWM controller to switch from 19.2MHz to 32KHz, which is a slow-down of a factor 600. Surprisingly enough so far there have been few bug reports about this. This is likely because the i915 driver was hardcoding the PWM frequency to 46 KHz, which divided by 600 would result in a PWM frequency of approx. 78 Hz, which mostly still works fine. There are some bug reports about the LCD backlight flickering after suspend/resume which are likely caused by this issue. But with the upcoming patch-series to finally switch the i915 drivers code for external PWM controllers to use the atomic API and to honor the PWM frequency specified in the video BIOS (VBT), this becomes a much bigger problem. On most cases the VBT specifies either 200 Hz or 20 KHz as PWM frequency, which with the mentioned issue ends up being either 1/3 Hz, where the backlight actually visible blinks on and off every 3s, or in 33 Hz and horrible flickering of the backlight. There are a number of possible solutions to this problem: 1. Make acpi_lpss_save_ctx() run before GFX0._PS3 Pro: Clean solution from pov of not medling with save/restore ctx code Con: As mentioned the current ordering is the right thing to do Con: Requires assymmetry in at what suspend/resume phase we do the save vs restore, requiring more suspend/resume ordering hacks in already convoluted acpi_lpss.c suspend/resume code. 2. Do some sort of save once mode for the LPSS ctx Pro: Reasonably clean Con: Needs a new LPSS flag + code changes to handle the flag 3. Detect we have failed to save the ctx registers and do not restore them Pro: Not PWM specific, might help with issues on other LPSS devices too Con: If we can get away with not restoring the ctx why bother with it at all? 4. Do not save the ctx for CHT PWM controllers Pro: Clean, as simple as dropping a flag? Con: Not so simple as dropping a flag, needs a new flag to ensure that we still do lpss_deassert_reset() on device activation. 5. Make the pwm-lpss code fixup the LPSS-context registers Pro: Keeps acpi_lpss.c code clean Con: Moves knowledge of LPSS-context into the pwm-lpss.c code 1 and 5 both do not seem to be a desirable way forward. 3 and 4 seem ok, but they both assume that restoring the LPSS-context registers is not necessary. I have done a couple of test and those do show that restoring the LPSS-context indeed does not seem to be necessary on devices using s2idle suspend (and successfully reaching S0i3). But I have no hardware to test deep / S3 suspend. So I'm not sure that not restoring the context is safe. That leaves solution 2, which is about as simple / clean as 3 and 4, so this commit fixes the described problem by implementing a new LPSS_SAVE_CTX_ONCE flag and setting that for the CHT PWM controllers. Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-3-hdegoede@redhat.com --- drivers/acpi/acpi_lpss.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 67892fc0b822f..a8d7d83ac7615 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -67,7 +67,15 @@ ACPI_MODULE_NAME("acpi_lpss"); #define LPSS_CLK_DIVIDER BIT(2) #define LPSS_LTR BIT(3) #define LPSS_SAVE_CTX BIT(4) -#define LPSS_NO_D3_DELAY BIT(5) +/* + * For some devices the DSDT AML code for another device turns off the device + * before our suspend handler runs, causing us to read/save all 1-s (0xffffffff) + * as ctx register values. + * Luckily these devices always use the same ctx register values, so we can + * work around this by saving the ctx registers once on activation. + */ +#define LPSS_SAVE_CTX_ONCE BIT(5) +#define LPSS_NO_D3_DELAY BIT(6) struct lpss_private_data; @@ -254,7 +262,7 @@ static const struct lpss_device_desc byt_pwm_dev_desc = { }; static const struct lpss_device_desc bsw_pwm_dev_desc = { - .flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, + .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, .prv_offset = 0x800, .setup = bsw_pwm_setup, .resume_from_noirq = true, @@ -885,9 +893,14 @@ static int acpi_lpss_activate(struct device *dev) * we have to deassert reset line to be sure that ->probe() will * recognize the device. */ - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) lpss_deassert_reset(pdata); +#ifdef CONFIG_PM + if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) + acpi_lpss_save_ctx(dev, pdata); +#endif + return 0; } @@ -1031,7 +1044,7 @@ static int acpi_lpss_resume(struct device *dev) acpi_lpss_d3_to_d0_delay(pdata); - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) acpi_lpss_restore_ctx(dev, pdata); return 0; -- GitLab From 181f4d2f44463fe09fe4df02e03095cb87151c29 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:23 +0200 Subject: [PATCH 0772/1494] pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the data-sheet the way the PWM controller works is that each input clock-cycle the base_unit gets added to a N bit counter and that counter overflowing determines the PWM output frequency. So assuming e.g. a 16 bit counter this means that if base_unit is set to 1, after 65535 input clock-cycles the counter has been increased from 0 to 65535 and it will overflow on the next cycle, so it will overflow after every 65536 clock cycles and thus the calculations done in pwm_lpss_prepare() should use 65536 and not 65535. This commit fixes this. Note this also aligns the calculations in pwm_lpss_prepare() with those in pwm_lpss_get_state(). Note this effectively reverts commit 684309e5043e ("pwm: lpss: Avoid potential overflow of base_unit"). The next patch in this series really fixes the potential overflow of the base_unit value. Fixes: 684309e5043e ("pwm: lpss: Avoid potential overflow of base_unit") Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-4-hdegoede@redhat.com --- drivers/pwm/pwm-lpss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 9d965ffe66d1e..43b1fc634af1a 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -93,7 +93,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, * The equation is: * base_unit = round(base_unit_range * freq / c) */ - base_unit_range = BIT(lpwm->info->base_unit_bits) - 1; + base_unit_range = BIT(lpwm->info->base_unit_bits); freq *= base_unit_range; base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); @@ -104,8 +104,8 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, orig_ctrl = ctrl = pwm_lpss_read(pwm); ctrl &= ~PWM_ON_TIME_DIV_MASK; - ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); - base_unit &= base_unit_range; + ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); + base_unit &= (base_unit_range - 1); ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; ctrl |= on_time_div; -- GitLab From ef9f60daab309558c8bb3e086a9a11ee40bd6061 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:24 +0200 Subject: [PATCH 0773/1494] pwm: lpss: Add range limit check for the base_unit register value When the user requests a high enough period ns value, then the calculations in pwm_lpss_prepare() might result in a base_unit value of 0. But according to the data-sheet the way the PWM controller works is that each input clock-cycle the base_unit gets added to a N bit counter and that counter overflowing determines the PWM output frequency. Adding 0 to the counter is a no-op. The data-sheet even explicitly states that writing 0 to the base_unit bits will result in the PWM outputting a continuous 0 signal. When the user requestes a low enough period ns value, then the calculations in pwm_lpss_prepare() might result in a base_unit value which is bigger then base_unit_range - 1. Currently the codes for this deals with this by applying a mask: base_unit &= (base_unit_range - 1); But this means that we let the value overflow the range, we throw away the higher bits and store whatever value is left in the lower bits into the register leading to a random output frequency, rather then clamping the output frequency to the highest frequency which the hardware can do. This commit fixes both issues by clamping the base_unit value to be between 1 and (base_unit_range - 1). Fixes: 684309e5043e ("pwm: lpss: Avoid potential overflow of base_unit") Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-5-hdegoede@redhat.com --- drivers/pwm/pwm-lpss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 43b1fc634af1a..da9bc3d10104a 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -97,6 +97,8 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, freq *= base_unit_range; base_unit = DIV_ROUND_CLOSEST_ULL(freq, c); + /* base_unit must not be 0 and we also want to avoid overflowing it */ + base_unit = clamp_val(base_unit, 1, base_unit_range - 1); on_time_div = 255ULL * duty_ns; do_div(on_time_div, period_ns); @@ -105,7 +107,6 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, orig_ctrl = ctrl = pwm_lpss_read(pwm); ctrl &= ~PWM_ON_TIME_DIV_MASK; ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); - base_unit &= (base_unit_range - 1); ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; ctrl |= on_time_div; -- GitLab From 092d83e3f513a4a7b9f189b34e28b71c9edcedbd Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:25 +0200 Subject: [PATCH 0774/1494] pwm: lpss: Add pwm_lpss_prepare_enable() helper In the not-enabled -> enabled path pwm_lpss_apply() needs to get a runtime-pm reference; and then on any errors it needs to release it again. This leads to somewhat hard to read code. This commit introduces a new pwm_lpss_prepare_enable() helper and moves all the steps necessary for the not-enabled -> enabled transition there, so that we can error check the entire transition in a single place and only have one pm_runtime_put() on failure call site. While working on this I noticed that the enabled -> enabled (update settings) path was quite similar, so I've added an enable parameter to the new pwm_lpss_prepare_enable() helper, which allows using it in that path too. Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-6-hdegoede@redhat.com --- drivers/pwm/pwm-lpss.c | 45 ++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index da9bc3d10104a..8a136ba2a5831 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -122,41 +122,48 @@ static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_ENABLE); } +static int pwm_lpss_prepare_enable(struct pwm_lpss_chip *lpwm, + struct pwm_device *pwm, + const struct pwm_state *state, + bool enable) +{ + int ret; + + ret = pwm_lpss_is_updating(pwm); + if (ret) + return ret; + + pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); + pwm_lpss_cond_enable(pwm, enable && lpwm->info->bypass == false); + ret = pwm_lpss_wait_for_update(pwm); + if (ret) + return ret; + + pwm_lpss_cond_enable(pwm, enable && lpwm->info->bypass == true); + return 0; +} + static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { struct pwm_lpss_chip *lpwm = to_lpwm(chip); - int ret; + int ret = 0; if (state->enabled) { if (!pwm_is_enabled(pwm)) { pm_runtime_get_sync(chip->dev); - ret = pwm_lpss_is_updating(pwm); - if (ret) { - pm_runtime_put(chip->dev); - return ret; - } - pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); - pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); - ret = pwm_lpss_wait_for_update(pwm); - if (ret) { + ret = pwm_lpss_prepare_enable(lpwm, pwm, state, true); + if (ret) pm_runtime_put(chip->dev); - return ret; - } - pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true); } else { - ret = pwm_lpss_is_updating(pwm); - if (ret) - return ret; - pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); - return pwm_lpss_wait_for_update(pwm); + ret = pwm_lpss_prepare_enable(lpwm, pwm, state, false); } } else if (pwm_is_enabled(pwm)) { pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE); pm_runtime_put(chip->dev); } - return 0; + return ret; } static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, -- GitLab From d6d54bacb1dd02a31ed9d8e3db028639da292615 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:26 +0200 Subject: [PATCH 0775/1494] pwm: lpss: Make pwm_lpss_apply() not rely on existing hardware state Before this commit pwm_lpss_apply() was assuming 2 pre-conditions were met by the existing hardware state: 1. That the base-unit and on-time-div read back from the control register are those actually in use, so that it can skip setting the update bit if the read-back value matches the desired values. 2. That the controller is enabled when the cached pwm_state.enabled says that the controller is enabled. As the long history of fixes for subtle (often suspend/resume) lpss-pwm issues shows, these assumptions are not necessary always true. 1. Specifically is not true on some (*) Cherry Trail devices with a nasty GFX0._PS3 method which: a. saves the ctrl reg value. b. sets the base-unit to 0 and writes the update bit to apply/commit c. restores the original ctrl value without setting the update bit, so that the 0 base-unit value is still in use. 2. Assumption 2. currently is true, but only because of the code which saves/restores the state on suspend/resume. By convention restoring the PWM state should be done by the PWM consumer and the presence of this code in the pmw-lpss driver is a bug. Therefor the save/restore code will be dropped in the next patch in this series, after which this assumption also is no longer true. This commit changes the pwm_lpss_apply() to not make any assumptions about the state the hardware is in. Instead it makes pwm_lpss_apply() always fully program the PWM controller, making it much less fragile. *) Seen on the Acer One 10 S1003, Lenovo Ideapad Miix 310 and 320 models and various Medion models. Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-7-hdegoede@redhat.com --- drivers/pwm/pwm-lpss.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 8a136ba2a5831..9c5c7217c9b6d 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -85,7 +85,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, unsigned long long on_time_div; unsigned long c = lpwm->info->clk_rate, base_unit_range; unsigned long long base_unit, freq = NSEC_PER_SEC; - u32 orig_ctrl, ctrl; + u32 ctrl; do_div(freq, period_ns); @@ -104,16 +104,14 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, do_div(on_time_div, period_ns); on_time_div = 255ULL - on_time_div; - orig_ctrl = ctrl = pwm_lpss_read(pwm); + ctrl = pwm_lpss_read(pwm); ctrl &= ~PWM_ON_TIME_DIV_MASK; ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT); ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; ctrl |= on_time_div; - if (orig_ctrl != ctrl) { - pwm_lpss_write(pwm, ctrl); - pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); - } + pwm_lpss_write(pwm, ctrl); + pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); } static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) @@ -124,8 +122,7 @@ static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) static int pwm_lpss_prepare_enable(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, - const struct pwm_state *state, - bool enable) + const struct pwm_state *state) { int ret; @@ -134,12 +131,12 @@ static int pwm_lpss_prepare_enable(struct pwm_lpss_chip *lpwm, return ret; pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); - pwm_lpss_cond_enable(pwm, enable && lpwm->info->bypass == false); + pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); ret = pwm_lpss_wait_for_update(pwm); if (ret) return ret; - pwm_lpss_cond_enable(pwm, enable && lpwm->info->bypass == true); + pwm_lpss_cond_enable(pwm, lpwm->info->bypass == true); return 0; } @@ -152,11 +149,11 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->enabled) { if (!pwm_is_enabled(pwm)) { pm_runtime_get_sync(chip->dev); - ret = pwm_lpss_prepare_enable(lpwm, pwm, state, true); + ret = pwm_lpss_prepare_enable(lpwm, pwm, state); if (ret) pm_runtime_put(chip->dev); } else { - ret = pwm_lpss_prepare_enable(lpwm, pwm, state, false); + ret = pwm_lpss_prepare_enable(lpwm, pwm, state); } } else if (pwm_is_enabled(pwm)) { pwm_lpss_write(pwm, pwm_lpss_read(pwm) & ~PWM_ENABLE); -- GitLab From 547d9e9261d294f0a2597d9e9c55ba48f80716ab Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:27 +0200 Subject: [PATCH 0776/1494] pwm: lpss: Remove suspend/resume handlers PWM controller drivers should not restore the PWM state on resume. The convention is that PWM consumers do this by calling pwm_apply_state(), so that it can be done at the exact moment when the consumer needs the state to be stored, avoiding e.g. backlight flickering. The only in kernel consumers of the pwm-lpss code, the i915 driver and the pwm-class sysfs interface code both correctly restore the state on resume, so there is no need to do this in the pwm-lpss code. More-over the removed resume handler is buggy, since it blindly restores the ctrl-register contents without setting the update bit, which is necessary to get the controller to actually use/apply the restored base-unit and on-time-div values. Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-8-hdegoede@redhat.com --- drivers/pwm/pwm-lpss-platform.c | 1 - drivers/pwm/pwm-lpss.c | 24 ------------------------ drivers/pwm/pwm-lpss.h | 3 --- 3 files changed, 28 deletions(-) diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 48f34d20aecd7..c6502cf7a7af1 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c @@ -89,7 +89,6 @@ static int pwm_lpss_prepare(struct device *dev) static const struct dev_pm_ops pwm_lpss_platform_pm_ops = { .prepare = pwm_lpss_prepare, - SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume) }; static const struct acpi_device_id pwm_lpss_acpi_match[] = { diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 9c5c7217c9b6d..3444c56b4bede 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c @@ -260,30 +260,6 @@ int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) } EXPORT_SYMBOL_GPL(pwm_lpss_remove); -int pwm_lpss_suspend(struct device *dev) -{ - struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); - int i; - - for (i = 0; i < lpwm->info->npwm; i++) - lpwm->saved_ctrl[i] = readl(lpwm->regs + i * PWM_SIZE + PWM); - - return 0; -} -EXPORT_SYMBOL_GPL(pwm_lpss_suspend); - -int pwm_lpss_resume(struct device *dev) -{ - struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); - int i; - - for (i = 0; i < lpwm->info->npwm; i++) - writel(lpwm->saved_ctrl[i], lpwm->regs + i * PWM_SIZE + PWM); - - return 0; -} -EXPORT_SYMBOL_GPL(pwm_lpss_resume); - MODULE_DESCRIPTION("PWM driver for Intel LPSS"); MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 7909fa12fca2c..70db7e389d66b 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h @@ -19,7 +19,6 @@ struct pwm_lpss_chip { struct pwm_chip chip; void __iomem *regs; const struct pwm_lpss_boardinfo *info; - u32 saved_ctrl[MAX_PWMS]; }; struct pwm_lpss_boardinfo { @@ -37,7 +36,5 @@ struct pwm_lpss_boardinfo { struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, const struct pwm_lpss_boardinfo *info); int pwm_lpss_remove(struct pwm_lpss_chip *lpwm); -int pwm_lpss_suspend(struct device *dev); -int pwm_lpss_resume(struct device *dev); #endif /* __PWM_LPSS_H */ -- GitLab From 79e0899275e527ac187693528ba7a39a645e2832 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:28 +0200 Subject: [PATCH 0777/1494] pwm: crc: Fix period / duty_cycle times being off by a factor of 256 While looking into adding atomic-pwm support to the pwm-crc driver I noticed something odd, there is a PWM_BASE_CLK define of 6 MHz and there is a clock-divider which divides this with a value between 1-128, and there are 256 duty-cycle steps. The pwm-crc code before this commit assumed that a clock-divider setting of 1 means that the PWM output is running at 6 MHZ, if that is true, where do these 256 duty-cycle steps come from? This would require an internal frequency of 256 * 6 MHz = 1.5 GHz, that seems unlikely for a PMIC which is using a silicon process optimized for power-switching transistors. It is way more likely that there is an 8 bit counter for the duty cycle which acts as an extra fixed divider wrt the PWM output frequency. The main user of the pwm-crc driver is the i915 GPU driver which uses it for backlight control. Lets compare the PWM register values set by the video-BIOS (the GOP), assuming the extra fixed divider is present versus the PWM frequency specified in the Video-BIOS-Tables: Device: PWM Hz set by BIOS PWM Hz specified in VBT Asus T100TA 200 200 Asus T100HA 200 200 Lenovo Miix 2 8 23437 20000 Toshiba WT8-A 23437 20000 So as we can see if we assume the extra division by 256 then the register values set by the GOP are an exact match for the VBT values, where as otherwise the values would be of by a factor of 256. This commit fixes the period / duty_cycle calculations to take the extra division by 256 into account. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-9-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 272eeb0711475..c056eb9b858c1 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -21,8 +21,8 @@ #define PWM_MAX_LEVEL 0xFF -#define PWM_BASE_CLK 6000000 /* 6 MHz */ -#define PWM_MAX_PERIOD_NS 21333 /* 46.875KHz */ +#define PWM_BASE_CLK_MHZ 6 /* 6 MHz */ +#define PWM_MAX_PERIOD_NS 5461333 /* 183 Hz */ /** * struct crystalcove_pwm - Crystal Cove PWM controller @@ -72,7 +72,7 @@ static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, /* changing the clk divisor, need to disable fisrt */ crc_pwm_disable(c, pwm); - clk_div = PWM_BASE_CLK * period_ns / NSEC_PER_SEC; + clk_div = PWM_BASE_CLK_MHZ * period_ns / (256 * NSEC_PER_USEC); regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, clk_div | PWM_OUTPUT_ENABLE); -- GitLab From a05af71f0dd3a31c4036f34e3e85fbcc56e80050 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:29 +0200 Subject: [PATCH 0778/1494] pwm: crc: Fix off-by-one error in the clock-divider calculations The CRC PWM controller has a clock-divider which divides the clock with a value between 1-128. But as can seen from the PWM_DIV_CLK_xxx defines, this range maps to a register value of 0-127. So after calculating the clock-divider we must subtract 1 to get the register value, unless the requested frequency was so high that the calculation has already resulted in a (rounded) divider value of 0. Note that before this fix, setting a period of PWM_MAX_PERIOD_NS which corresponds to the max. divider value of 128 could have resulted in a bug where the code would use 128 as divider-register value which would have resulted in an actual divider value of 0 (and the enable bit being set). A rounding error stopped this bug from actually happen. This same rounding error means that after the subtraction of 1 it is impossible to set the divider to 128. Also bump PWM_MAX_PERIOD_NS by 1 ns to allow setting a divider of 128 (register-value 127). Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-10-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index c056eb9b858c1..44ec7d5b63e16 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -22,7 +22,7 @@ #define PWM_MAX_LEVEL 0xFF #define PWM_BASE_CLK_MHZ 6 /* 6 MHz */ -#define PWM_MAX_PERIOD_NS 5461333 /* 183 Hz */ +#define PWM_MAX_PERIOD_NS 5461334 /* 183 Hz */ /** * struct crystalcove_pwm - Crystal Cove PWM controller @@ -39,6 +39,18 @@ static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) return container_of(pc, struct crystalcove_pwm, chip); } +static int crc_pwm_calc_clk_div(int period_ns) +{ + int clk_div; + + clk_div = PWM_BASE_CLK_MHZ * period_ns / (256 * NSEC_PER_USEC); + /* clk_div 1 - 128, maps to register values 0-127 */ + if (clk_div > 0) + clk_div--; + + return clk_div; +} + static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) { struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); @@ -68,11 +80,10 @@ static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, } if (pwm_get_period(pwm) != period_ns) { - int clk_div; + int clk_div = crc_pwm_calc_clk_div(period_ns); /* changing the clk divisor, need to disable fisrt */ crc_pwm_disable(c, pwm); - clk_div = PWM_BASE_CLK_MHZ * period_ns / (256 * NSEC_PER_USEC); regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, clk_div | PWM_OUTPUT_ENABLE); -- GitLab From 6158231a84224ed0d826bbf62c992ce9c73101c1 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:30 +0200 Subject: [PATCH 0779/1494] pwm: crc: Fix period changes not having any effect The pwm-crc code is using 2 different enable bits: 1. bit 7 of the PWM0_CLK_DIV (PWM_OUTPUT_ENABLE) 2. bit 0 of the BACKLIGHT_EN register The BACKLIGHT_EN register at address 0x51 really controls a separate output-only GPIO which is earmarked to be used as output connected to the backlight-enable pin for LCD panels, this GPO is part of the PMIC's "Display Panel Control Block." . This pin should probably be moved over to a GPIO provider driver (and consumers modified accordingly), but that is something for an(other) patch. Enabling / disabling the actual PWM output is controlled by the PWM_OUTPUT_ENABLE bit of the PWM0_CLK_DIV register. As the comment in the old code already indicates we must disable the PWM before we can change the clock divider. But the crc_pwm_disable() and crc_pwm_enable() calls the old code make for this only change the BACKLIGHT_EN register; and the value of that register does not matter for changing the period / the divider. What does matter is that the PWM_OUTPUT_ENABLE bit must be cleared before a new value can be written. This commit modifies crc_pwm_config() to clear PWM_OUTPUT_ENABLE instead when changing the period, so that period changes actually work. Note this fix will cause a significant behavior change on some devices using the CRC PWM output to drive their backlight. Before the PWM would always run with the output frequency configured by the BIOS at boot, now the period time specified by the i915 driver will actually be honored. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-11-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 44ec7d5b63e16..81232da0c7679 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -82,14 +82,11 @@ static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, if (pwm_get_period(pwm) != period_ns) { int clk_div = crc_pwm_calc_clk_div(period_ns); - /* changing the clk divisor, need to disable fisrt */ - crc_pwm_disable(c, pwm); + /* changing the clk divisor, clear PWM_OUTPUT_ENABLE first */ + regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, 0); regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, clk_div | PWM_OUTPUT_ENABLE); - - /* enable back */ - crc_pwm_enable(c, pwm); } /* change the pwm duty cycle */ -- GitLab From 6fdefe60898ad4506456d8117c7f81cbc5d13468 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:31 +0200 Subject: [PATCH 0780/1494] pwm: crc: Enable/disable PWM output on enable/disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pwm-crc code is using 2 different enable bits: 1. bit 7 of the PWM0_CLK_DIV (PWM_OUTPUT_ENABLE) 2. bit 0 of the BACKLIGHT_EN register So far we've kept the PWM_OUTPUT_ENABLE bit set when disabling the PWM, this commit makes crc_pwm_disable() clear it on disable and makes crc_pwm_enable() set it again on re-enable. Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-12-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 81232da0c7679..b72008c9b0724 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -54,7 +54,9 @@ static int crc_pwm_calc_clk_div(int period_ns) static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) { struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + int div = crc_pwm_calc_clk_div(pwm_get_period(pwm)); + regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, div | PWM_OUTPUT_ENABLE); regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 1); return 0; @@ -63,8 +65,10 @@ static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) { struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); + int div = crc_pwm_calc_clk_div(pwm_get_period(pwm)); regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 0); + regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, div); } static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, -- GitLab From 9fccec821904b5f2a44b0c7b522a058ad0590a2c Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:32 +0200 Subject: [PATCH 0781/1494] pwm: crc: Implement apply() method to support the new atomic PWM API Replace the enable, disable and config pwm_ops with an apply op, to support the new atomic PWM API. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-13-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 89 ++++++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index b72008c9b0724..27dc308824245 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -51,59 +51,78 @@ static int crc_pwm_calc_clk_div(int period_ns) return clk_div; } -static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) +static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) { - struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); - int div = crc_pwm_calc_clk_div(pwm_get_period(pwm)); + struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip); + struct device *dev = crc_pwm->chip.dev; + int err; - regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, div | PWM_OUTPUT_ENABLE); - regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 1); + if (state->period > PWM_MAX_PERIOD_NS) { + dev_err(dev, "un-supported period_ns\n"); + return -EINVAL; + } - return 0; -} + if (state->polarity != PWM_POLARITY_NORMAL) + return -EOPNOTSUPP; -static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) -{ - struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); - int div = crc_pwm_calc_clk_div(pwm_get_period(pwm)); + if (pwm_is_enabled(pwm) && !state->enabled) { + err = regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 0); + if (err) { + dev_err(dev, "Error writing BACKLIGHT_EN %d\n", err); + return err; + } + } - regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 0); - regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, div); -} + if (pwm_get_duty_cycle(pwm) != state->duty_cycle || + pwm_get_period(pwm) != state->period) { + u64 level = state->duty_cycle * PWM_MAX_LEVEL; -static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, - int duty_ns, int period_ns) -{ - struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); - struct device *dev = crc_pwm->chip.dev; - int level; + do_div(level, state->period); - if (period_ns > PWM_MAX_PERIOD_NS) { - dev_err(dev, "un-supported period_ns\n"); - return -EINVAL; + err = regmap_write(crc_pwm->regmap, PWM0_DUTY_CYCLE, level); + if (err) { + dev_err(dev, "Error writing PWM0_DUTY_CYCLE %d\n", err); + return err; + } } - if (pwm_get_period(pwm) != period_ns) { - int clk_div = crc_pwm_calc_clk_div(period_ns); - + if (pwm_is_enabled(pwm) && state->enabled && + pwm_get_period(pwm) != state->period) { /* changing the clk divisor, clear PWM_OUTPUT_ENABLE first */ - regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, 0); + err = regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, 0); + if (err) { + dev_err(dev, "Error writing PWM0_CLK_DIV %d\n", err); + return err; + } + } - regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, - clk_div | PWM_OUTPUT_ENABLE); + if (pwm_get_period(pwm) != state->period || + pwm_is_enabled(pwm) != state->enabled) { + int clk_div = crc_pwm_calc_clk_div(state->period); + int pwm_output_enable = state->enabled ? PWM_OUTPUT_ENABLE : 0; + + err = regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, + clk_div | pwm_output_enable); + if (err) { + dev_err(dev, "Error writing PWM0_CLK_DIV %d\n", err); + return err; + } } - /* change the pwm duty cycle */ - level = duty_ns * PWM_MAX_LEVEL / period_ns; - regmap_write(crc_pwm->regmap, PWM0_DUTY_CYCLE, level); + if (!pwm_is_enabled(pwm) && state->enabled) { + err = regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 1); + if (err) { + dev_err(dev, "Error writing BACKLIGHT_EN %d\n", err); + return err; + } + } return 0; } static const struct pwm_ops crc_pwm_ops = { - .config = crc_pwm_config, - .enable = crc_pwm_enable, - .disable = crc_pwm_disable, + .apply = crc_pwm_apply, }; static int crystalcove_pwm_probe(struct platform_device *pdev) -- GitLab From c86b155da7d0700032eed00d37ee02310eb8a0b7 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:33 +0200 Subject: [PATCH 0782/1494] pwm: crc: Implement get_state() method Implement the pwm_ops.get_state() method to complete the support for the new atomic PWM API. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-14-hdegoede@redhat.com --- drivers/pwm/pwm-crc.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/pwm/pwm-crc.c b/drivers/pwm/pwm-crc.c index 27dc308824245..ecfdfac0c2d93 100644 --- a/drivers/pwm/pwm-crc.c +++ b/drivers/pwm/pwm-crc.c @@ -121,8 +121,39 @@ static int crc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static void crc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct crystalcove_pwm *crc_pwm = to_crc_pwm(chip); + struct device *dev = crc_pwm->chip.dev; + unsigned int clk_div, clk_div_reg, duty_cycle_reg; + int error; + + error = regmap_read(crc_pwm->regmap, PWM0_CLK_DIV, &clk_div_reg); + if (error) { + dev_err(dev, "Error reading PWM0_CLK_DIV %d\n", error); + return; + } + + error = regmap_read(crc_pwm->regmap, PWM0_DUTY_CYCLE, &duty_cycle_reg); + if (error) { + dev_err(dev, "Error reading PWM0_DUTY_CYCLE %d\n", error); + return; + } + + clk_div = (clk_div_reg & ~PWM_OUTPUT_ENABLE) + 1; + + state->period = + DIV_ROUND_UP(clk_div * NSEC_PER_USEC * 256, PWM_BASE_CLK_MHZ); + state->duty_cycle = + DIV_ROUND_UP_ULL(duty_cycle_reg * state->period, PWM_MAX_LEVEL); + state->polarity = PWM_POLARITY_NORMAL; + state->enabled = !!(clk_div_reg & PWM_OUTPUT_ENABLE); +} + static const struct pwm_ops crc_pwm_ops = { .apply = crc_pwm_apply, + .get_state = crc_pwm_get_state, }; static int crystalcove_pwm_probe(struct platform_device *pdev) -- GitLab From 27a79cbc17e39b34f2fa9d3829e39ca50418c7f2 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:34 +0200 Subject: [PATCH 0783/1494] drm/i915: panel: Add get_vbt_pwm_freq() helper Factor the code which checks and drm_dbg_kms-s the VBT PWM frequency out of get_backlight_max_vbt(). This is a preparation patch for honering the VBT PWM frequency for devices which use an external PWM controller (devices using pwm_setup_backlight()). Acked-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-15-hdegoede@redhat.com --- drivers/gpu/drm/i915/display/intel_panel.c | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index aaed9eb3b56ce..0cbb73baabf12 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1543,18 +1543,9 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul); } -static u32 get_backlight_max_vbt(struct intel_connector *connector) +static u16 get_vbt_pwm_freq(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_panel *panel = &connector->panel; u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; - u32 pwm; - - if (!panel->backlight.hz_to_pwm) { - drm_dbg_kms(&dev_priv->drm, - "backlight frequency conversion not supported\n"); - return 0; - } if (pwm_freq_hz) { drm_dbg_kms(&dev_priv->drm, @@ -1567,6 +1558,22 @@ static u32 get_backlight_max_vbt(struct intel_connector *connector) pwm_freq_hz); } + return pwm_freq_hz; +} + +static u32 get_backlight_max_vbt(struct intel_connector *connector) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_panel *panel = &connector->panel; + u16 pwm_freq_hz = get_vbt_pwm_freq(dev_priv); + u32 pwm; + + if (!panel->backlight.hz_to_pwm) { + drm_dbg_kms(&dev_priv->drm, + "backlight frequency conversion not supported\n"); + return 0; + } + pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz); if (!pwm) { drm_dbg_kms(&dev_priv->drm, -- GitLab From 6b51e7d23aa8591557d742c96e2f87c09ff54a48 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:35 +0200 Subject: [PATCH 0784/1494] drm/i915: panel: Honor the VBT PWM frequency for devs with an external PWM controller So far for devices using an external PWM controller (devices using pwm_setup_backlight()), we have been hardcoding the period-time passed to pwm_config() to 21333 ns. I suspect this was done because many VBTs set the PWM frequency to 200 which corresponds to a period-time of 5000000 ns, which greatly exceeds the PWM_MAX_PERIOD_NS define in the Crystal Cove PMIC PWM driver, which used to be 21333. This PWM_MAX_PERIOD_NS define was actually based on a bug in the PWM driver where its period and duty-cycle times where off by a factor of 256. Due to this bug the hardcoded CRC_PMIC_PWM_PERIOD_NS value of 21333 would result in the PWM driver using its divider of 128, which would result in a PWM output frequency of 6000000 Hz / 256 / 128 = 183 Hz. So actually pretty close to the default VBT value of 200 Hz. Now that this bug in the pwm-crc driver is fixed, we can actually use the VBT defined frequency. This is important because: a) With the pwm-crc driver fixed it will now translate the hardcoded CRC_PMIC_PWM_PERIOD_NS value of 21333 ns / 46 Khz to a PWM output frequency of 23 KHz (the max it can do). b) The pwm-lpss driver used on many models has always honored the 21333 ns / 46 Khz request Some panels do not like such high output frequencies. E.g. on a Terra Pad 1061 tablet, using the LPSS PWM controller, the backlight would go from off to max, when changing the sysfs backlight brightness value from 90-100%, anything under aprox. 90% would turn the backlight fully off. Honoring the VBT specified PWM frequency will also hopefully fix the various bug reports which we have received about users perceiving the backlight to flicker after a suspend/resume cycle. Acked-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-16-hdegoede@redhat.com --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_panel.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 413b60337a0b7..5648ec58a32bc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -223,6 +223,7 @@ struct intel_panel { bool util_pin_active_low; /* bxt+ */ u8 controller; /* bxt+ only */ struct pwm_device *pwm; + int pwm_period_ns; /* DPCD backlight */ u8 pwmgen_bit_count; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 0cbb73baabf12..d54dd26bd0665 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -40,8 +40,6 @@ #include "intel_dsi_dcs_backlight.h" #include "intel_panel.h" -#define CRC_PMIC_PWM_PERIOD_NS 21333 - void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode) @@ -597,7 +595,7 @@ static u32 pwm_get_backlight(struct intel_connector *connector) int duty_ns; duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); - return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); + return DIV_ROUND_UP(duty_ns * 100, panel->backlight.pwm_period_ns); } static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -671,9 +669,10 @@ static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel; - int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + int duty_ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100); - pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); + pwm_config(panel->backlight.pwm, duty_ns, + panel->backlight.pwm_period_ns); } static void @@ -1917,6 +1916,9 @@ static int pwm_setup_backlight(struct intel_connector *connector, return -ENODEV; } + panel->backlight.pwm_period_ns = NSEC_PER_SEC / + get_vbt_pwm_freq(dev_priv); + /* * FIXME: pwm_apply_args() should be removed when switching to * the atomic PWM API. @@ -1926,9 +1928,10 @@ static int pwm_setup_backlight(struct intel_connector *connector, panel->backlight.min = 0; /* 0% */ panel->backlight.max = 100; /* 100% */ level = intel_panel_compute_brightness(connector, 100); - ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); + ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100); - retval = pwm_config(panel->backlight.pwm, ns, CRC_PMIC_PWM_PERIOD_NS); + retval = pwm_config(panel->backlight.pwm, ns, + panel->backlight.pwm_period_ns); if (retval < 0) { drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n"); pwm_put(panel->backlight.pwm); @@ -1937,7 +1940,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, } level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100, - CRC_PMIC_PWM_PERIOD_NS); + panel->backlight.pwm_period_ns); panel->backlight.level = intel_panel_compute_brightness(connector, level); panel->backlight.enabled = panel->backlight.level != 0; -- GitLab From 9a6ae5b354ed09f61cfa3acbb19fecd64f46b097 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:36 +0200 Subject: [PATCH 0785/1494] drm/i915: panel: Honor the VBT PWM min setting for devs with an external PWM controller So far for devices using an external PWM controller (devices using pwm_setup_backlight()), we have been hardcoding the minimum allowed PWM level to 0. But several of these devices specify a non 0 minimum setting in their VBT. Change pwm_setup_backlight() to use get_backlight_min_vbt() to get the minimum level. Acked-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-17-hdegoede@redhat.com --- drivers/gpu/drm/i915/display/intel_panel.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index d54dd26bd0665..1e98d2dab0edb 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -1925,8 +1925,8 @@ static int pwm_setup_backlight(struct intel_connector *connector, */ pwm_apply_args(panel->backlight.pwm); - panel->backlight.min = 0; /* 0% */ panel->backlight.max = 100; /* 100% */ + panel->backlight.min = get_backlight_min_vbt(connector); level = intel_panel_compute_brightness(connector, 100); ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100); @@ -1941,8 +1941,9 @@ static int pwm_setup_backlight(struct intel_connector *connector, level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100, panel->backlight.pwm_period_ns); - panel->backlight.level = - intel_panel_compute_brightness(connector, level); + level = intel_panel_compute_brightness(connector, level); + panel->backlight.level = clamp(level, panel->backlight.min, + panel->backlight.max); panel->backlight.enabled = panel->backlight.level != 0; drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", -- GitLab From f8bd54d2190469e2244ade66cc1551b2a8f4f138 Mon Sep 17 00:00:00 2001 From: Hans de Goede <hdegoede@redhat.com> Date: Thu, 3 Sep 2020 13:23:37 +0200 Subject: [PATCH 0786/1494] drm/i915: panel: Use atomic PWM API for devs with an external PWM controller Now that the PWM drivers which we use have been converted to the atomic PWM API, we can move the i915 panel code over to using the atomic PWM API. The removes a long standing FIXME and this removes a flicker where the backlight brightness would jump to 100% when i915 loads even if using the fastset path. Note that this commit also simplifies pwm_disable_backlight(), by dropping the intel_panel_actually_set_backlight(..., 0) call. This call sets the PWM to 0% duty-cycle. I believe that this call was only present as a workaround for a bug in the pwm-crc.c driver where it failed to clear the PWM_OUTPUT_ENABLE bit. This is fixed by an earlier patch in this series. After the dropping of this workaround, the usleep call, which seems unnecessary to begin with, has no useful effect anymore, so drop that too. Acked-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200903112337.4113-18-hdegoede@redhat.com --- .../drm/i915/display/intel_display_types.h | 3 +- drivers/gpu/drm/i915/display/intel_panel.c | 70 ++++++++----------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5648ec58a32bc..b2d0edacc58c9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -28,6 +28,7 @@ #include <linux/async.h> #include <linux/i2c.h> +#include <linux/pwm.h> #include <linux/sched/clock.h> #include <drm/drm_atomic.h> @@ -223,7 +224,7 @@ struct intel_panel { bool util_pin_active_low; /* bxt+ */ u8 controller; /* bxt+ only */ struct pwm_device *pwm; - int pwm_period_ns; + struct pwm_state pwm_state; /* DPCD backlight */ u8 pwmgen_bit_count; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 1e98d2dab0edb..5a201fe8de11c 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -592,10 +592,10 @@ static u32 bxt_get_backlight(struct intel_connector *connector) static u32 pwm_get_backlight(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; - int duty_ns; + struct pwm_state state; - duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); - return DIV_ROUND_UP(duty_ns * 100, panel->backlight.pwm_period_ns); + pwm_get_state(panel->backlight.pwm, &state); + return pwm_get_relative_duty_cycle(&state, 100); } static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) @@ -669,10 +669,9 @@ static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel; - int duty_ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100); - pwm_config(panel->backlight.pwm, duty_ns, - panel->backlight.pwm_period_ns); + pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100); + pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); } static void @@ -841,10 +840,8 @@ static void pwm_disable_backlight(const struct drm_connector_state *old_conn_sta struct intel_connector *connector = to_intel_connector(old_conn_state->connector); struct intel_panel *panel = &connector->panel; - /* Disable the backlight */ - intel_panel_actually_set_backlight(old_conn_state, 0); - usleep_range(2000, 3000); - pwm_disable(panel->backlight.pwm); + panel->backlight.pwm_state.enabled = false; + pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); } void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state) @@ -1176,9 +1173,12 @@ static void pwm_enable_backlight(const struct intel_crtc_state *crtc_state, { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = &connector->panel; + int level = panel->backlight.level; - pwm_enable(panel->backlight.pwm); - intel_panel_actually_set_backlight(conn_state, panel->backlight.level); + level = intel_panel_compute_brightness(connector, level); + pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100); + panel->backlight.pwm_state.enabled = true; + pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); } static void __intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, @@ -1897,8 +1897,7 @@ static int pwm_setup_backlight(struct intel_connector *connector, struct drm_i915_private *dev_priv = to_i915(dev); struct intel_panel *panel = &connector->panel; const char *desc; - u32 level, ns; - int retval; + u32 level; /* Get the right PWM chip for DSI backlight according to VBT */ if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { @@ -1916,35 +1915,28 @@ static int pwm_setup_backlight(struct intel_connector *connector, return -ENODEV; } - panel->backlight.pwm_period_ns = NSEC_PER_SEC / - get_vbt_pwm_freq(dev_priv); - - /* - * FIXME: pwm_apply_args() should be removed when switching to - * the atomic PWM API. - */ - pwm_apply_args(panel->backlight.pwm); - panel->backlight.max = 100; /* 100% */ panel->backlight.min = get_backlight_min_vbt(connector); - level = intel_panel_compute_brightness(connector, 100); - ns = DIV_ROUND_UP(level * panel->backlight.pwm_period_ns, 100); - retval = pwm_config(panel->backlight.pwm, ns, - panel->backlight.pwm_period_ns); - if (retval < 0) { - drm_err(&dev_priv->drm, "Failed to configure the pwm chip\n"); - pwm_put(panel->backlight.pwm); - panel->backlight.pwm = NULL; - return retval; - } + if (pwm_is_enabled(panel->backlight.pwm)) { + /* PWM is already enabled, use existing settings */ + pwm_get_state(panel->backlight.pwm, &panel->backlight.pwm_state); - level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100, - panel->backlight.pwm_period_ns); - level = intel_panel_compute_brightness(connector, level); - panel->backlight.level = clamp(level, panel->backlight.min, - panel->backlight.max); - panel->backlight.enabled = panel->backlight.level != 0; + level = pwm_get_relative_duty_cycle(&panel->backlight.pwm_state, + 100); + level = intel_panel_compute_brightness(connector, level); + panel->backlight.level = clamp(level, panel->backlight.min, + panel->backlight.max); + panel->backlight.enabled = true; + + drm_dbg_kms(&dev_priv->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n", + NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period, + get_vbt_pwm_freq(dev_priv), level); + } else { + /* Set period from VBT frequency, leave other settings at 0. */ + panel->backlight.pwm_state.period = + NSEC_PER_SEC / get_vbt_pwm_freq(dev_priv); + } drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n", desc); -- GitLab From d2024cdf0f02b9bdad2adb8ce220e30c6424e247 Mon Sep 17 00:00:00 2001 From: Linus Walleij <linus.walleij@linaro.org> Date: Sun, 6 Sep 2020 15:29:03 +0200 Subject: [PATCH 0787/1494] drm/panel: s6e63m0: Fix up DRM_DEV* regression Ooops the panel drivers stopped to use DRM_DEV* messages and we predictably create errors by merging code that still use it. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Sam Ravnborg <sam@ravnborg.org> Acked-by: David Airlie <airlied@linux.ie> Link: https://patchwork.freedesktop.org/patch/msgid/20200906132903.5739-1-linus.walleij@linaro.org --- .../gpu/drm/panel/panel-samsung-s6e63m0-dsi.c | 22 +++++++------------ .../gpu/drm/panel/panel-samsung-s6e63m0-spi.c | 8 +++---- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 14 +++++------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c index 2ec9e7900791e..eec74c10dddaf 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c @@ -23,11 +23,11 @@ static int s6e63m0_dsi_dcs_read(struct device *dev, const u8 cmd, u8 *data) ret = mipi_dsi_dcs_read(dsi, cmd, data, 1); if (ret < 0) { - DRM_DEV_ERROR(dev, "could not read DCS CMD %02x\n", cmd); + dev_err(dev, "could not read DCS CMD %02x\n", cmd); return ret; } - DRM_DEV_INFO(dev, "DSI read CMD %02x = %02x\n", cmd, *data); + dev_info(dev, "DSI read CMD %02x = %02x\n", cmd, *data); return 0; } @@ -42,7 +42,7 @@ static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len) int chunk; int ret; - DRM_DEV_INFO(dev, "DSI writing dcs seq: %*ph\n", (int)len, data); + dev_info(dev, "DSI writing dcs seq: %*ph\n", (int)len, data); /* Pick out and skip past the DCS command */ cmd = *seqp; @@ -56,9 +56,7 @@ static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len) chunk = S6E63M0_DSI_MAX_CHUNK; ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk); if (ret < 0) { - DRM_DEV_ERROR(dev, - "error sending DCS command seq cmd %02x\n", - cmd); + dev_err(dev, "error sending DCS command seq cmd %02x\n", cmd); return ret; } cmdwritten += chunk; @@ -70,23 +68,19 @@ static int s6e63m0_dsi_dcs_write(struct device *dev, const u8 *data, size_t len) chunk = S6E63M0_DSI_MAX_CHUNK; ret = mipi_dsi_dcs_write(dsi, MCS_GLOBAL_PARAM, &cmdwritten, 1); if (ret < 0) { - DRM_DEV_ERROR(dev, - "error sending CMD %02x global param %02x\n", - cmd, cmdwritten); + dev_err(dev, "error sending CMD %02x global param %02x\n", + cmd, cmdwritten); return ret; } ret = mipi_dsi_dcs_write(dsi, cmd, seqp, chunk); if (ret < 0) { - DRM_DEV_ERROR(dev, - "error sending CMD %02x chunk\n", - cmd); + dev_err(dev, "error sending CMD %02x chunk\n", cmd); return ret; } cmdwritten += chunk; seqp += chunk; } - DRM_DEV_INFO(dev, "sent command %02x %02x bytes\n", - cmd, cmdwritten); + dev_info(dev, "sent command %02x %02x bytes\n", cmd, cmdwritten); usleep_range(8000, 9000); diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index 3b1a2a3a44ea5..d298d780220db 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -41,7 +41,7 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len) { int ret = 0; - DRM_DEV_DEBUG(dev, "SPI writing dcs seq: %*ph\n", (int)len, data); + dev_dbg(dev, "SPI writing dcs seq: %*ph\n", (int)len, data); ret = s6e63m0_spi_write_word(dev, *data); while (!ret && --len) { @@ -50,8 +50,8 @@ static int s6e63m0_spi_dcs_write(struct device *dev, const u8 *data, size_t len) } if (ret) { - DRM_DEV_ERROR(dev, "SPI error %d writing dcs seq: %*ph\n", ret, - (int)len, data); + dev_err(dev, "SPI error %d writing dcs seq: %*ph\n", ret, + (int)len, data); } usleep_range(300, 310); @@ -68,7 +68,7 @@ static int s6e63m0_spi_probe(struct spi_device *spi) spi->mode = SPI_MODE_3; ret = spi_setup(spi); if (ret < 0) { - DRM_DEV_ERROR(dev, "spi setup failed.\n"); + dev_err(dev, "spi setup failed.\n"); return ret; } return s6e63m0_probe(dev, s6e63m0_spi_dcs_read, s6e63m0_spi_dcs_write, diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index c9472b2ae0cd1..044294aafe278 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -179,28 +179,24 @@ static int s6e63m0_check_lcd_type(struct s6e63m0 *ctx) ret = s6e63m0_clear_error(ctx); if (ret) { - DRM_DEV_ERROR(ctx->dev, "error checking LCD type (%d)\n", - ret); + dev_err(ctx->dev, "error checking LCD type (%d)\n", ret); ctx->lcd_type = 0x00; return ret; } - DRM_DEV_INFO(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3); + dev_info(ctx->dev, "MTP ID: %02x %02x %02x\n", id1, id2, id3); /* We attempt to detect what panel is mounted on the controller */ switch (id2) { case S6E63M0_LCD_ID_VALUE_M2: - DRM_DEV_INFO(ctx->dev, - "detected LCD panel AMS397GE MIPI M2\n"); + dev_info(ctx->dev, "detected LCD panel AMS397GE MIPI M2\n"); break; case S6E63M0_LCD_ID_VALUE_SM2: case S6E63M0_LCD_ID_VALUE_SM2_1: - DRM_DEV_INFO(ctx->dev, - "detected LCD panel AMS397GE MIPI SM2\n"); + dev_info(ctx->dev, "detected LCD panel AMS397GE MIPI SM2\n"); break; default: - DRM_DEV_INFO(ctx->dev, - "unknown LCD panel type %02x\n", id2); + dev_info(ctx->dev, "unknown LCD panel type %02x\n", id2); break; } -- GitLab From d4a197f4047e01d1e0b06e0390d513f253350c62 Mon Sep 17 00:00:00 2001 From: "Kristian H. Kristensen" <hoegsberg@google.com> Date: Thu, 3 Sep 2020 18:16:52 +0000 Subject: [PATCH 0788/1494] udmabuf: Add missing compact_ioctl Make sure we can use this on mixed systems. Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200903181652.432067-1-hoegsberg@google.com Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/dma-buf/udmabuf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index acb26c627d27b..5ee1e93997105 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -308,6 +308,9 @@ static long udmabuf_ioctl(struct file *filp, unsigned int ioctl, static const struct file_operations udmabuf_fops = { .owner = THIS_MODULE, .unlocked_ioctl = udmabuf_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = udmabuf_ioctl, +#endif }; static struct miscdevice udmabuf_misc = { -- GitLab From 6188b06e0357b3bc3b91d0b67783681d34ff2b64 Mon Sep 17 00:00:00 2001 From: Antonio Borneo <antonio.borneo@st.com> Date: Wed, 8 Jul 2020 16:08:36 +0200 Subject: [PATCH 0789/1494] drm/bridge/synopsys: dsi: allow LP commands in video mode Current code only sends LP commands in command mode. Allows sending LP commands also in video mode by setting the proper flag in DSI_VID_MODE_CFG. Signed-off-by: Antonio Borneo <antonio.borneo@st.com> Tested-by: Philippe Cornu <philippe.cornu@st.com> Reviewed-by: Philippe Cornu <philippe.cornu@st.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200708140836.32418-1-yannick.fertre@st.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index d580b2aa4ce98..d41ce1de10678 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -89,6 +89,7 @@ #define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1 #define VID_MODE_TYPE_BURST 0x2 #define VID_MODE_TYPE_MASK 0x3 +#define ENABLE_LOW_POWER_CMD BIT(15) #define VID_MODE_VPG_ENABLE BIT(16) #define VID_MODE_VPG_HORIZONTAL BIT(24) @@ -367,6 +368,13 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : PHY_TXREQUESTCLKHS); dsi_write(dsi, DSI_CMD_MODE_CFG, val); + + val = dsi_read(dsi, DSI_VID_MODE_CFG); + if (lpm) + val |= ENABLE_LOW_POWER_CMD; + else + val &= ~ENABLE_LOW_POWER_CMD; + dsi_write(dsi, DSI_VID_MODE_CFG, val); } static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) -- GitLab From 9e025e80660fe35432c81e67d401109d8e7b0ff4 Mon Sep 17 00:00:00 2001 From: Antonio Borneo <antonio.borneo@st.com> Date: Wed, 1 Jul 2020 16:31:31 +0200 Subject: [PATCH 0790/1494] drm/bridge/synopsys: dsi: allow sending longer LP commands Current code does not properly computes the max length of LP commands that can be send during H or V sync, and rely on static values. Limiting the max LP length to 4 byte during the V-sync is overly conservative. Relax the limit and allows longer LP commands (16 bytes) to be sent during V-sync. Signed-off-by: Antonio Borneo <antonio.borneo@st.com> Tested-by: Philippe Cornu <philippe.cornu@st.com> Reviewed-by: Philippe Cornu <philippe.cornu@st.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200701143131.841-1-yannick.fertre@st.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index d41ce1de10678..e9a0f42ff99fa 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -361,6 +361,15 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, bool lpm = msg->flags & MIPI_DSI_MSG_USE_LPM; u32 val = 0; + /* + * TODO dw drv improvements + * largest packet sizes during hfp or during vsa/vpb/vfp + * should be computed according to byte lane, lane number and only + * if sending lp cmds in high speed is enable (PHY_TXREQUESTCLKHS) + */ + dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(16) + | INVACT_LPCMD_TIME(4)); + if (msg->flags & MIPI_DSI_MSG_REQ_ACK) val |= ACK_RQST_EN; if (lpm) @@ -619,14 +628,6 @@ static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, dsi_write(dsi, DSI_DPI_VCID, DPI_VCID(dsi->channel)); dsi_write(dsi, DSI_DPI_COLOR_CODING, color); dsi_write(dsi, DSI_DPI_CFG_POL, val); - /* - * TODO dw drv improvements - * largest packet sizes during hfp or during vsa/vpb/vfp - * should be computed according to byte lane, lane number and only - * if sending lp cmds in high speed is enable (PHY_TXREQUESTCLKHS) - */ - dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(4) - | INVACT_LPCMD_TIME(4)); } static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi) -- GitLab From c6d94e37bdbb6dfe7e581e937a915ab58399b8a5 Mon Sep 17 00:00:00 2001 From: Antonio Borneo <antonio.borneo@st.com> Date: Wed, 1 Jul 2020 21:42:34 +0200 Subject: [PATCH 0791/1494] drm/bridge/synopsys: dsi: add support for non-continuous HS clock Current code enables the HS clock when video mode is started or to send out a HS command, and disables the HS clock to send out a LP command. This is not what DSI spec specify. Enable HS clock either in command and in video mode. Set automatic HS clock management for panels and devices that support non-continuous HS clock. Signed-off-by: Antonio Borneo <antonio.borneo@st.com> Tested-by: Philippe Cornu <philippe.cornu@st.com> Reviewed-by: Philippe Cornu <philippe.cornu@st.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200701194234.18123-1-yannick.fertre@st.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index e9a0f42ff99fa..8510a84c4c635 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -375,7 +375,6 @@ static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, if (lpm) val |= CMD_MODE_ALL_LP; - dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : PHY_TXREQUESTCLKHS); dsi_write(dsi, DSI_CMD_MODE_CFG, val); val = dsi_read(dsi, DSI_VID_MODE_CFG); @@ -558,16 +557,22 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi, unsigned long mode_flags) { + u32 val; + dsi_write(dsi, DSI_PWR_UP, RESET); if (mode_flags & MIPI_DSI_MODE_VIDEO) { dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE); dw_mipi_dsi_video_mode_config(dsi); - dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS); } else { dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); } + val = PHY_TXREQUESTCLKHS; + if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) + val |= AUTO_CLKLANE_CTRL; + dsi_write(dsi, DSI_LPCLK_CTRL, val); + dsi_write(dsi, DSI_PWR_UP, POWERUP); } -- GitLab From e2435d69204c1f041e5742cac9af301021afa46f Mon Sep 17 00:00:00 2001 From: Angelo Ribeiro <Angelo.Ribeiro@synopsys.com> Date: Mon, 6 Apr 2020 15:49:03 +0200 Subject: [PATCH 0792/1494] drm/bridge: dw-mipi-dsi.c: Add VPG runtime config through debugfs Add support for the video pattern generator (VPG) BER pattern mode and configuration in runtime. This enables using the debugfs interface to manipulate the VPG after the pipeline is set. Also, enables the usage of the VPG BER pattern. Changes in v2: - Added VID_MODE_VPG_MODE - Solved incompatible return type on __get and __set Reported-by: kbuild test robot <lkp@intel.com> Reported-by: Adrian Pop <pop.adrian61@gmail.com> Signed-off-by: Angelo Ribeiro <angelo.ribeiro@synopsys.com> Tested-by: Yannick Fertre <yannick.fertre@st.com> Tested-by: Adrian Pop <pop.adrian61@gmail.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com> Cc: Joao Pinto <jpinto@synopsys.com> Cc: Jose Abreu <jose.abreu@synopsys.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/a809feb7d7153a92e323416f744f1565e995da01.1586180592.git.angelo.ribeiro@synopsys.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 98 +++++++++++++++++-- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 8510a84c4c635..0b3825a4fbdb5 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -91,6 +91,7 @@ #define VID_MODE_TYPE_MASK 0x3 #define ENABLE_LOW_POWER_CMD BIT(15) #define VID_MODE_VPG_ENABLE BIT(16) +#define VID_MODE_VPG_MODE BIT(20) #define VID_MODE_VPG_HORIZONTAL BIT(24) #define DSI_VID_PKT_SIZE 0x3c @@ -221,6 +222,21 @@ #define PHY_STATUS_TIMEOUT_US 10000 #define CMD_PKT_STATUS_TIMEOUT_US 20000 +#ifdef CONFIG_DEBUG_FS +#define VPG_DEFS(name, dsi) \ + ((void __force *)&((*dsi).vpg_defs.name)) + +#define REGISTER(name, mask, dsi) \ + { #name, VPG_DEFS(name, dsi), mask, dsi } + +struct debugfs_entries { + const char *name; + bool *reg; + u32 mask; + struct dw_mipi_dsi *dsi; +}; +#endif /* CONFIG_DEBUG_FS */ + struct dw_mipi_dsi { struct drm_bridge bridge; struct mipi_dsi_host dsi_host; @@ -238,9 +254,12 @@ struct dw_mipi_dsi { #ifdef CONFIG_DEBUG_FS struct dentry *debugfs; - - bool vpg; - bool vpg_horizontal; + struct debugfs_entries *debugfs_vpg; + struct { + bool vpg; + bool vpg_horizontal; + bool vpg_ber_pattern; + } vpg_defs; #endif /* CONFIG_DEBUG_FS */ struct dw_mipi_dsi *master; /* dual-dsi master ptr */ @@ -545,9 +564,11 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS; #ifdef CONFIG_DEBUG_FS - if (dsi->vpg) { + if (dsi->vpg_defs.vpg) { val |= VID_MODE_VPG_ENABLE; - val |= dsi->vpg_horizontal ? VID_MODE_VPG_HORIZONTAL : 0; + val |= dsi->vpg_defs.vpg_horizontal ? + VID_MODE_VPG_HORIZONTAL : 0; + val |= dsi->vpg_defs.vpg_ber_pattern ? VID_MODE_VPG_MODE : 0; } #endif /* CONFIG_DEBUG_FS */ @@ -978,6 +999,68 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = { #ifdef CONFIG_DEBUG_FS +int dw_mipi_dsi_debugfs_write(void *data, u64 val) +{ + struct debugfs_entries *vpg = data; + struct dw_mipi_dsi *dsi; + u32 mode_cfg; + + if (!vpg) + return -ENODEV; + + dsi = vpg->dsi; + + *vpg->reg = (bool)val; + + mode_cfg = dsi_read(dsi, DSI_VID_MODE_CFG); + + if (*vpg->reg) + mode_cfg |= vpg->mask; + else + mode_cfg &= ~vpg->mask; + + dsi_write(dsi, DSI_VID_MODE_CFG, mode_cfg); + + return 0; +} + +int dw_mipi_dsi_debugfs_show(void *data, u64 *val) +{ + struct debugfs_entries *vpg = data; + + if (!vpg) + return -ENODEV; + + *val = *vpg->reg; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_mipi_dsi_debugfs_show, + dw_mipi_dsi_debugfs_write, "%llu\n"); + +static void debugfs_create_files(void *data) +{ + struct dw_mipi_dsi *dsi = data; + struct debugfs_entries debugfs[] = { + REGISTER(vpg, VID_MODE_VPG_ENABLE, dsi), + REGISTER(vpg_horizontal, VID_MODE_VPG_HORIZONTAL, dsi), + REGISTER(vpg_ber_pattern, VID_MODE_VPG_MODE, dsi), + }; + int i; + + dsi->debugfs_vpg = kmalloc(sizeof(debugfs), GFP_KERNEL); + if (!dsi->debugfs_vpg) + return; + + memcpy(dsi->debugfs_vpg, debugfs, sizeof(debugfs)); + + for (i = 0; i < ARRAY_SIZE(debugfs); i++) + debugfs_create_file(dsi->debugfs_vpg[i].name, 0644, + dsi->debugfs, &dsi->debugfs_vpg[i], + &fops_x32); +} + static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) { dsi->debugfs = debugfs_create_dir(dev_name(dsi->dev), NULL); @@ -986,14 +1069,13 @@ static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) return; } - debugfs_create_bool("vpg", 0660, dsi->debugfs, &dsi->vpg); - debugfs_create_bool("vpg_horizontal", 0660, dsi->debugfs, - &dsi->vpg_horizontal); + debugfs_create_files(dsi); } static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { debugfs_remove_recursive(dsi->debugfs); + kfree(dsi->debugfs_vpg); } #else -- GitLab From 3f6a6f343c57a773ed146e54de8c626f72dd2be7 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 16 Jul 2020 11:07:54 +0100 Subject: [PATCH 0793/1494] drm/i915: Reduce i915_request.lock contention for i915_request_wait Currently, we use i915_request_completed() directly in i915_request_wait() and follow up with a manual invocation of dma_fence_signal(). This appears to cause a large number of contentions on i915_request.lock as when the process is woken up after the fence is signaled by an interrupt, we will then try and call dma_fence_signal() ourselves while the signaler is still holding the lock. dma_fence_is_signaled() has the benefit of checking the DMA_FENCE_FLAG_SIGNALED_BIT prior to calling dma_fence_signal() and so avoids most of that contention. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716100754.5670-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_request.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 7a05850ca9318..0ec0beb1a83e5 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1640,7 +1640,7 @@ static bool busywait_stop(unsigned long timeout, unsigned int cpu) return this_cpu != cpu; } -static bool __i915_spin_request(const struct i915_request * const rq, int state) +static bool __i915_spin_request(struct i915_request * const rq, int state) { unsigned long timeout_ns; unsigned int cpu; @@ -1673,7 +1673,7 @@ static bool __i915_spin_request(const struct i915_request * const rq, int state) timeout_ns = READ_ONCE(rq->engine->props.max_busywait_duration_ns); timeout_ns += local_clock_ns(&cpu); do { - if (i915_request_completed(rq)) + if (dma_fence_is_signaled(&rq->fence)) return true; if (signal_pending_state(state, current)) @@ -1697,7 +1697,7 @@ static void request_wait_wake(struct dma_fence *fence, struct dma_fence_cb *cb) { struct request_wait *wait = container_of(cb, typeof(*wait), cb); - wake_up_process(wait->tsk); + wake_up_process(fetch_and_zero(&wait->tsk)); } /** @@ -1766,10 +1766,8 @@ long i915_request_wait(struct i915_request *rq, * duration, which we currently lack. */ if (IS_ACTIVE(CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT) && - __i915_spin_request(rq, state)) { - dma_fence_signal(&rq->fence); + __i915_spin_request(rq, state)) goto out; - } /* * This client is about to stall waiting for the GPU. In many cases @@ -1793,10 +1791,8 @@ long i915_request_wait(struct i915_request *rq, for (;;) { set_current_state(state); - if (i915_request_completed(rq)) { - dma_fence_signal(&rq->fence); + if (dma_fence_is_signaled(&rq->fence)) break; - } intel_engine_flush_submission(rq->engine); @@ -1814,7 +1810,9 @@ long i915_request_wait(struct i915_request *rq, } __set_current_state(TASK_RUNNING); - dma_fence_remove_callback(&rq->fence, &wait.cb); + if (READ_ONCE(wait.tsk)) + dma_fence_remove_callback(&rq->fence, &wait.cb); + GEM_BUG_ON(!list_empty(&wait.cb.node)); out: mutex_release(&rq->engine->gt->reset.mutex.dep_map, _THIS_IP_); -- GitLab From e3d0e213960ece147954ea86a340329361d10e5b Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 15 Jul 2020 16:58:58 +0100 Subject: [PATCH 0794/1494] drm/i915/selftests: Mock the status_page.vma for the kernel_context Since we assert that the kernel_context is using the perma-pinned HWSP, make it so. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2179 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200715155858.16410-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/mock_engine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index b8dd3cbc8696b..06303ba98c191 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -332,6 +332,9 @@ int mock_engine_init(struct intel_engine_cs *engine) if (IS_ERR(ce)) goto err_breadcrumbs; + /* We insist the kernel context is using the status_page */ + engine->status_page.vma = ce->timeline->hwsp_ggtt; + engine->kernel_context = ce; return 0; -- GitLab From 3adee4ac2922e30d2fe0583c0126c1e5fee4cc54 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 15 Jul 2020 12:50:51 +0100 Subject: [PATCH 0795/1494] drm/i915: Soften the tasklet flush frequency before waits We include a tasklet flush before waiting on a request as a precaution against the HW being lax in event signaling. We now have a precautionary flush in the engine's heartbeat and so do not need to be quite so zealous on every request wait. If we focus on the request, the only tasklet flush that matters is if there is a delay in submitting this request to HW, so if the request is not ready to be executed, no advantage in reducing this wait can be gained by running the tasklet. And there is little point in doing busy work for no result. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200715115147.11866-10-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_request.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 0ec0beb1a83e5..44c759490641a 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1788,14 +1788,30 @@ long i915_request_wait(struct i915_request *rq, if (dma_fence_add_callback(&rq->fence, &wait.cb, request_wait_wake)) goto out; + /* + * Flush the submission tasklet, but only if it may help this request. + * + * We sometimes experience some latency between the HW interrupts and + * tasklet execution (mostly due to ksoftirqd latency, but it can also + * be due to lazy CS events), so lets run the tasklet manually if there + * is a chance it may submit this request. If the request is not ready + * to run, as it is waiting for other fences to be signaled, flushing + * the tasklet is busy work without any advantage for this client. + * + * If the HW is being lazy, this is the last chance before we go to + * sleep to catch any pending events. We will check periodically in + * the heartbeat to flush the submission tasklets as a last resort + * for unhappy HW. + */ + if (i915_request_is_ready(rq)) + intel_engine_flush_submission(rq->engine); + for (;;) { set_current_state(state); if (dma_fence_is_signaled(&rq->fence)) break; - intel_engine_flush_submission(rq->engine); - if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; -- GitLab From 27a5dcfe73f4b696b3de8c23a560199bb1c193a4 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:20:10 +0100 Subject: [PATCH 0796/1494] drm/i915/gem: Remove disordered per-file request list for throttling I915_GEM_THROTTLE dates back to the time before contexts where there was just a single engine, and therefore a single timeline and request list globally. That request list was in execution/retirement order, and so walking it to find a particular aged request made sense and could be split per file. That is no more. We now have many timelines with a file, as many as the user wants to construct (essentially per-engine, per-context). Each of those run independently and so make the single list futile. Remove the disordered list, and iterate over all the timelines to find a request to wait on in each to satisfy the criteria that the CPU is no more than 20ms ahead of its oldest request. It should go without saying that the I915_GEM_THROTTLE ioctl is no longer used as the primary means of throttling, so it makes sense to push the complication into the ioctl where it only impacts upon its few irregular users, rather than the execbuf/retire where everybody has to pay the cost. Fortunately, the few users do not create vast amount of contexts, so the loops over contexts/engines should be concise. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728152010.30701-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 13 ---- drivers/gpu/drm/i915/gem/i915_gem_throttle.c | 67 +++++++++++++------ drivers/gpu/drm/i915/gt/selftest_lrc.c | 5 +- drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 6 -- drivers/gpu/drm/i915/i915_gem.c | 18 ----- drivers/gpu/drm/i915/i915_request.c | 21 ------ drivers/gpu/drm/i915/i915_request.h | 4 -- 8 files changed, 50 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 02b1630f513e8..90d77cdc6f661 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1928,18 +1928,6 @@ static int eb_parse(struct i915_execbuffer *eb) return err; } -static void -add_to_client(struct i915_request *rq, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv = file->driver_priv; - - rq->file_priv = file_priv; - - spin_lock(&file_priv->mm.lock); - list_add_tail(&rq->client_link, &file_priv->mm.request_list); - spin_unlock(&file_priv->mm.lock); -} - static int eb_submit(struct i915_execbuffer *eb, struct i915_vma *batch) { int err; @@ -2772,7 +2760,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, trace_i915_request_queue(eb.request, eb.batch_flags); err = eb_submit(&eb, batch); err_request: - add_to_client(eb.request, file); i915_request_get(eb.request); eb_request_add(&eb); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_throttle.c b/drivers/gpu/drm/i915/gem/i915_gem_throttle.c index 540ef0551789f..1929d6cf41508 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_throttle.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_throttle.c @@ -9,6 +9,7 @@ #include <drm/drm_file.h> #include "i915_drv.h" +#include "i915_gem_context.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" @@ -35,9 +36,10 @@ int i915_gem_throttle_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { + const unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; struct drm_i915_file_private *file_priv = file->driver_priv; - unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; - struct i915_request *request, *target = NULL; + struct i915_gem_context *ctx; + unsigned long idx; long ret; /* ABI: return -EIO if already wedged */ @@ -45,27 +47,54 @@ i915_gem_throttle_ioctl(struct drm_device *dev, void *data, if (ret) return ret; - spin_lock(&file_priv->mm.lock); - list_for_each_entry(request, &file_priv->mm.request_list, client_link) { - if (time_after_eq(request->emitted_jiffies, recent_enough)) - break; + rcu_read_lock(); + xa_for_each(&file_priv->context_xa, idx, ctx) { + struct i915_gem_engines_iter it; + struct intel_context *ce; - if (target && xchg(&target->file_priv, NULL)) - list_del(&target->client_link); + if (!kref_get_unless_zero(&ctx->ref)) + continue; + rcu_read_unlock(); - target = request; - } - if (target) - i915_request_get(target); - spin_unlock(&file_priv->mm.lock); + for_each_gem_engine(ce, + i915_gem_context_lock_engines(ctx), + it) { + struct i915_request *rq, *target = NULL; + + if (!ce->timeline) + continue; + + mutex_lock(&ce->timeline->mutex); + list_for_each_entry_reverse(rq, + &ce->timeline->requests, + link) { + if (i915_request_completed(rq)) + break; - if (!target) - return 0; + if (time_after(rq->emitted_jiffies, + recent_enough)) + continue; - ret = i915_request_wait(target, - I915_WAIT_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); - i915_request_put(target); + target = i915_request_get(rq); + break; + } + mutex_unlock(&ce->timeline->mutex); + if (!target) + continue; + + ret = i915_request_wait(target, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); + i915_request_put(target); + if (ret < 0) + break; + } + i915_gem_context_unlock_engines(ctx); + i915_gem_context_put(ctx); + + rcu_read_lock(); + } + rcu_read_unlock(); return ret < 0 ? ret : 0; } diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 3fc5de961280e..f749071f54a7f 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -2729,7 +2729,7 @@ static int create_gang(struct intel_engine_cs *engine, i915_gem_object_put(obj); intel_context_put(ce); - rq->client_link.next = &(*prev)->client_link; + rq->mock.link.next = &(*prev)->mock.link; *prev = rq; return 0; @@ -2970,8 +2970,7 @@ static int live_preempt_gang(void *arg) } while (rq) { /* wait for each rq from highest to lowest prio */ - struct i915_request *n = - list_next_entry(rq, client_link); + struct i915_request *n = list_next_entry(rq, mock.link); if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0) { struct drm_printer p = diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e6918c7c07098..d8aaa882560bd 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1119,7 +1119,6 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; i915_gem_context_close(file); - i915_gem_release(dev, file); kfree_rcu(file_priv, rcu); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1314e0e92c411..0fb83a780b218 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -203,11 +203,6 @@ struct drm_i915_file_private { struct rcu_head rcu; }; - struct { - spinlock_t lock; - struct list_head request_list; - } mm; - struct xarray context_xa; struct xarray vm_xa; @@ -1867,7 +1862,6 @@ void i915_gem_suspend_late(struct drm_i915_private *dev_priv); void i915_gem_resume(struct drm_i915_private *dev_priv); int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file); -void i915_gem_release(struct drm_device *dev, struct drm_file *file); int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, enum i915_cache_level cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9aa3066cb75d9..e1de50780ed50 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1301,21 +1301,6 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) return 0; } -void i915_gem_release(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv = file->driver_priv; - struct i915_request *request; - - /* Clean up our request list when the client is going away, so that - * later retire_requests won't dereference our soon-to-be-gone - * file_priv. - */ - spin_lock(&file_priv->mm.lock); - list_for_each_entry(request, &file_priv->mm.request_list, client_link) - request->file_priv = NULL; - spin_unlock(&file_priv->mm.lock); -} - int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv; @@ -1331,9 +1316,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) file_priv->dev_priv = i915; file_priv->file = file; - spin_lock_init(&file_priv->mm.lock); - INIT_LIST_HEAD(&file_priv->mm.request_list); - file_priv->bsd_engine = -1; file_priv->hang_timestamp = jiffies; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 44c759490641a..bb0cf8199c2d9 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -212,24 +212,6 @@ static void __notify_execute_cb(struct i915_request *rq) init_llist_head(&rq->execute_cb); } -static inline void -remove_from_client(struct i915_request *request) -{ - struct drm_i915_file_private *file_priv; - - if (!READ_ONCE(request->file_priv)) - return; - - rcu_read_lock(); - file_priv = xchg(&request->file_priv, NULL); - if (file_priv) { - spin_lock(&file_priv->mm.lock); - list_del(&request->client_link); - spin_unlock(&file_priv->mm.lock); - } - rcu_read_unlock(); -} - static void free_capture_list(struct i915_request *request) { struct i915_capture_list *capture; @@ -330,7 +312,6 @@ bool i915_request_retire(struct i915_request *rq) GEM_BUG_ON(!llist_empty(&rq->execute_cb)); spin_unlock_irq(&rq->lock); - remove_from_client(rq); __list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */ intel_context_exit(rq->context); @@ -757,7 +738,6 @@ static void __i915_request_ctor(void *arg) dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0); - rq->file_priv = NULL; rq->capture_list = NULL; init_llist_head(&rq->execute_cb); @@ -847,7 +827,6 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) /* No zalloc, everything must be cleared after use */ rq->batch = NULL; - GEM_BUG_ON(rq->file_priv); GEM_BUG_ON(rq->capture_list); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 5907628207611..fc18378c685d8 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -284,10 +284,6 @@ struct i915_request { /** timeline->request entry for this request */ struct list_head link; - struct drm_i915_file_private *file_priv; - /** file_priv list entry for this request */ - struct list_head client_link; - I915_SELFTEST_DECLARE(struct { struct list_head link; unsigned long delay; -- GitLab From a817c891c12471ce9fc285c1246372474c39a3f2 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:21:09 +0100 Subject: [PATCH 0797/1494] drm/i915/gt: Disable preparser around xcs invalidations on tgl Unlike rcs where we have conclusive evidence from our selftesting that disabling the preparser before performing the TLB invalidate and relocations does impact upon the GPU execution, the evidence for the same requirement on xcs is much more circumstantial. Let's apply the preparser disable between batches as we invalidate the TLB as a dose of healthy paranoia, just in case. References: https://gitlab.freedesktop.org/drm/intel/-/issues/2169 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728152110.830-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index d03da2f64a49d..1138b5c56e2f8 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4757,14 +4757,21 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode) intel_engine_mask_t aux_inv = 0; u32 cmd, *cs; + cmd = 4; + if (mode & EMIT_INVALIDATE) + cmd += 2; if (mode & EMIT_INVALIDATE) aux_inv = request->engine->mask & ~BIT(BCS0); + if (aux_inv) + cmd += 2 * hweight8(aux_inv) + 2; - cs = intel_ring_begin(request, - 4 + (aux_inv ? 2 * hweight8(aux_inv) + 2 : 0)); + cs = intel_ring_begin(request, cmd); if (IS_ERR(cs)) return PTR_ERR(cs); + if (mode & EMIT_INVALIDATE) + *cs++ = preparser_disable(true); + cmd = MI_FLUSH_DW + 1; /* We always require a command barrier so that subsequent @@ -4797,6 +4804,10 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode) } *cs++ = MI_NOOP; } + + if (mode & EMIT_INVALIDATE) + *cs++ = preparser_disable(false); + intel_ring_advance(request, cs); return 0; -- GitLab From 06b73c2d0b65f17e698f6a662affd7a08853c86f Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 09:02:45 +0100 Subject: [PATCH 0798/1494] drm/i915/gt: Delay taking the spinlock for grabbing from the buffer pool Some very low hanging fruit, but contention on the pool->lock is noticeable between intel_gt_get_buffer_pool() and pool_retire(), with the majority of the hold time due to the locked list iteration. If we make the node itself RCU protected, we can perform the search for an suitable node just under RCU, reserving taking the lock itself for claiming the node and manipulating the list. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729080245.8070-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gt/intel_gt_buffer_pool.c | 100 +++++++++++------- .../drm/i915/gt/intel_gt_buffer_pool_types.h | 6 +- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 418ae184cecf8..16dbf54361795 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -35,39 +35,62 @@ static void node_free(struct intel_gt_buffer_pool_node *node) { i915_gem_object_put(node->obj); i915_active_fini(&node->active); - kfree(node); + kfree_rcu(node, rcu); } -static void pool_free_work(struct work_struct *wrk) +static bool +pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) { - struct intel_gt_buffer_pool *pool = - container_of(wrk, typeof(*pool), work.work); - struct intel_gt_buffer_pool_node *node, *next; - unsigned long old = jiffies - HZ; + struct intel_gt_buffer_pool_node *node, *stale = NULL; bool active = false; - LIST_HEAD(stale); int n; /* Free buffers that have not been used in the past second */ - spin_lock_irq(&pool->lock); for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) { struct list_head *list = &pool->cache_list[n]; - /* Most recent at head; oldest at tail */ - list_for_each_entry_safe_reverse(node, next, list, link) { - if (time_before(node->age, old)) - break; + if (list_empty(list)) + continue; + + if (spin_trylock_irq(&pool->lock)) { + struct list_head *pos; - list_move(&node->link, &stale); + /* Most recent at head; oldest at tail */ + list_for_each_prev(pos, list) { + node = list_entry(pos, typeof(*node), link); + if (time_before(node->age, old)) + break; + + /* Check we are the first to claim this node */ + if (!xchg(&node->age, 0)) + break; + + node->free = stale; + stale = node; + } + if (!list_is_last(pos, list)) + __list_del_many(pos, list); + + spin_unlock_irq(&pool->lock); } + active |= !list_empty(list); } - spin_unlock_irq(&pool->lock); - list_for_each_entry_safe(node, next, &stale, link) + while ((node = stale)) { + stale = stale->free; node_free(node); + } + + return active; +} + +static void pool_free_work(struct work_struct *wrk) +{ + struct intel_gt_buffer_pool *pool = + container_of(wrk, typeof(*pool), work.work); - if (active) + if (pool_free_older_than(pool, jiffies - HZ)) schedule_delayed_work(&pool->work, round_jiffies_up_relative(HZ)); } @@ -108,9 +131,9 @@ static void pool_retire(struct i915_active *ref) /* Return this object to the shrinker pool */ i915_gem_object_make_purgeable(node->obj); + WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_lock_irqsave(&pool->lock, flags); - node->age = jiffies; - list_add(&node->link, list); + list_add_rcu(&node->link, list); spin_unlock_irqrestore(&pool->lock, flags); schedule_delayed_work(&pool->work, @@ -151,20 +174,30 @@ intel_gt_get_buffer_pool(struct intel_gt *gt, size_t size) struct intel_gt_buffer_pool *pool = >->buffer_pool; struct intel_gt_buffer_pool_node *node; struct list_head *list; - unsigned long flags; int ret; size = PAGE_ALIGN(size); list = bucket_for_size(pool, size); - spin_lock_irqsave(&pool->lock, flags); - list_for_each_entry(node, list, link) { + rcu_read_lock(); + list_for_each_entry_rcu(node, list, link) { + unsigned long age; + if (node->obj->base.size < size) continue; - list_del(&node->link); - break; + + age = READ_ONCE(node->age); + if (!age) + continue; + + if (cmpxchg(&node->age, age, 0) == age) { + spin_lock_irq(&pool->lock); + list_del_rcu(&node->link); + spin_unlock_irq(&pool->lock); + break; + } } - spin_unlock_irqrestore(&pool->lock, flags); + rcu_read_unlock(); if (&node->link == list) { node = node_create(pool, size); @@ -192,28 +225,13 @@ void intel_gt_init_buffer_pool(struct intel_gt *gt) INIT_DELAYED_WORK(&pool->work, pool_free_work); } -static void pool_free_imm(struct intel_gt_buffer_pool *pool) -{ - int n; - - spin_lock_irq(&pool->lock); - for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) { - struct intel_gt_buffer_pool_node *node, *next; - struct list_head *list = &pool->cache_list[n]; - - list_for_each_entry_safe(node, next, list, link) - node_free(node); - INIT_LIST_HEAD(list); - } - spin_unlock_irq(&pool->lock); -} - void intel_gt_flush_buffer_pool(struct intel_gt *gt) { struct intel_gt_buffer_pool *pool = >->buffer_pool; do { - pool_free_imm(pool); + while (pool_free_older_than(pool, jiffies + 1)) + ; } while (cancel_delayed_work_sync(&pool->work)); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h index e28bdda771ed1..bcf1658c96338 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h @@ -25,7 +25,11 @@ struct intel_gt_buffer_pool_node { struct i915_active active; struct drm_i915_gem_object *obj; struct list_head link; - struct intel_gt_buffer_pool *pool; + union { + struct intel_gt_buffer_pool *pool; + struct intel_gt_buffer_pool_node *free; + struct rcu_head rcu; + }; unsigned long age; }; -- GitLab From 62b1522cc3217e75478b607562c678b052d9179a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:33:25 +0100 Subject: [PATCH 0799/1494] drm/i915/selftests: Flush the active barriers before asserting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before we peek at the barrier status for an assert, first serialise with its callbacks so that we see a stable value. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728153325.28351-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/selftest_context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 52af1cee9a94e..1f4020e906a8a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -68,6 +68,8 @@ static int context_sync(struct intel_context *ce) } while (!err); mutex_unlock(&tl->mutex); + /* Wait for all barriers to complete (remote CPU) before we check */ + i915_active_unlock_wait(&ce->active); return err; } -- GitLab From a30e4ec176c823fb1f3fed51483c07e813c4c9c5 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 12:07:56 +0100 Subject: [PATCH 0800/1494] drm/i915/gt: Fix termination condition for freeing all buffer objects A last minute change, that unfortunately broke CI so badly it declared SUCCESS, was to refactor the debug free all buffer pool code to reuse the normal worker, inverted the termination condition so that it instead of discarding the nodes, they were all declared young enough and eligible for reuse. Fixes: 06b73c2d0b65 ("drm/i915/gt: Delay taking the spinlock for grabbing from the buffer pool") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729110756.2344-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Updating Fixes: link after rebasing and reordering into drm-intel-gt-next] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 16dbf54361795..9e938d4f6bfe1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -38,8 +38,7 @@ static void node_free(struct intel_gt_buffer_pool_node *node) kfree_rcu(node, rcu); } -static bool -pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) +static bool pool_free_older_than(struct intel_gt_buffer_pool *pool, long keep) { struct intel_gt_buffer_pool_node *node, *stale = NULL; bool active = false; @@ -57,8 +56,12 @@ pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) /* Most recent at head; oldest at tail */ list_for_each_prev(pos, list) { + unsigned long age; + node = list_entry(pos, typeof(*node), link); - if (time_before(node->age, old)) + + age = READ_ONCE(node->age); + if (!age || jiffies - age < keep) break; /* Check we are the first to claim this node */ @@ -90,7 +93,7 @@ static void pool_free_work(struct work_struct *wrk) struct intel_gt_buffer_pool *pool = container_of(wrk, typeof(*pool), work.work); - if (pool_free_older_than(pool, jiffies - HZ)) + if (pool_free_older_than(pool, HZ)) schedule_delayed_work(&pool->work, round_jiffies_up_relative(HZ)); } @@ -230,7 +233,7 @@ void intel_gt_flush_buffer_pool(struct intel_gt *gt) struct intel_gt_buffer_pool *pool = >->buffer_pool; do { - while (pool_free_older_than(pool, jiffies + 1)) + while (pool_free_older_than(pool, 0)) ; } while (cancel_delayed_work_sync(&pool->work)); } -- GitLab From eb4dedae920a07c485328af3da2202ec5184fb17 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 30 Jul 2020 10:28:56 +0100 Subject: [PATCH 0801/1494] drm/i915/gem: Delay tracking the GEM context until it is registered Avoid exposing a partially constructed context by deferring the list_add() from the initial construction to the end of registration. Otherwise, if we peek into the list of contexts from inside debugfs, we may see the partially constructed context and chase down some dangling incomplete pointers. Reported-by: CQ Tang <cq.tang@intel.com> Fixes: 3aa9945a528e ("drm/i915: Separate GEM context construction and registration to userspace") References: f6e8aa387171 ("drm/i915: Report the number of closed vma held by each context in debugfs") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: CQ Tang <cq.tang@intel.com> Cc: <stable@vger.kernel.org> # v5.2+ Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730092856.23615-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d0bdb6d447ed4..efc4ba34c06e8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -713,6 +713,7 @@ __create_context(struct drm_i915_private *i915) ctx->i915 = i915; ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL); mutex_init(&ctx->mutex); + INIT_LIST_HEAD(&ctx->link); spin_lock_init(&ctx->stale.lock); INIT_LIST_HEAD(&ctx->stale.engines); @@ -740,10 +741,6 @@ __create_context(struct drm_i915_private *i915) for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; - spin_lock(&i915->gem.contexts.lock); - list_add_tail(&ctx->link, &i915->gem.contexts.list); - spin_unlock(&i915->gem.contexts.lock); - return ctx; err_free: @@ -931,6 +928,7 @@ static int gem_context_register(struct i915_gem_context *ctx, struct drm_i915_file_private *fpriv, u32 *id) { + struct drm_i915_private *i915 = ctx->i915; struct i915_address_space *vm; int ret; @@ -949,8 +947,16 @@ static int gem_context_register(struct i915_gem_context *ctx, /* And finally expose ourselves to userspace via the idr */ ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL); if (ret) - put_pid(fetch_and_zero(&ctx->pid)); + goto err_pid; + + spin_lock(&i915->gem.contexts.lock); + list_add_tail(&ctx->link, &i915->gem.contexts.list); + spin_unlock(&i915->gem.contexts.lock); + + return 0; +err_pid: + put_pid(fetch_and_zero(&ctx->pid)); return ret; } -- GitLab From d1bf5dd8f6d510999b8a12687ee2662e26ab720c Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 30 Jul 2020 19:39:06 +0100 Subject: [PATCH 0802/1494] drm/i915/gt: Support multiple pinned timelines We may need to allocate more than one pinned context/timeline for each engine which can utilise the per-engine HWSP, so we need to give each a different offset within it. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730183906.25422-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 18 +++++++++++++--- drivers/gpu/drm/i915/gt/intel_lrc.c | 20 +++++++++++------- .../gpu/drm/i915/gt/intel_ring_submission.c | 3 ++- drivers/gpu/drm/i915/gt/intel_timeline.c | 12 ++++++----- drivers/gpu/drm/i915/gt/intel_timeline.h | 21 +++++++++++++++++-- drivers/gpu/drm/i915/gt/mock_engine.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 6 +++--- 8 files changed, 61 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index efc4ba34c06e8..d8cccbab7a51d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -886,7 +886,7 @@ i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags) if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) { struct intel_timeline *timeline; - timeline = intel_timeline_create(&i915->gt, NULL); + timeline = intel_timeline_create(&i915->gt); if (IS_ERR(timeline)) { context_close(ctx); return ERR_CAST(timeline); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index dd1a42c4d344e..86651bbef3a02 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -785,9 +785,11 @@ intel_engine_init_active(struct intel_engine_cs *engine, unsigned int subclass) } static struct intel_context * -create_kernel_context(struct intel_engine_cs *engine) +create_pinned_context(struct intel_engine_cs *engine, + unsigned int hwsp, + struct lock_class_key *key, + const char *name) { - static struct lock_class_key kernel; struct intel_context *ce; int err; @@ -796,6 +798,7 @@ create_kernel_context(struct intel_engine_cs *engine) return ce; __set_bit(CONTEXT_BARRIER_BIT, &ce->flags); + ce->timeline = page_pack_bits(NULL, hwsp); err = intel_context_pin(ce); /* perma-pin so it is always available */ if (err) { @@ -809,11 +812,20 @@ create_kernel_context(struct intel_engine_cs *engine) * should we need to inject GPU operations during their request * construction. */ - lockdep_set_class(&ce->timeline->mutex, &kernel); + lockdep_set_class_and_name(&ce->timeline->mutex, key, name); return ce; } +static struct intel_context * +create_kernel_context(struct intel_engine_cs *engine) +{ + static struct lock_class_key kernel; + + return create_pinned_context(engine, I915_GEM_HWS_SEQNO_ADDR, + &kernel, "kernel_context"); +} + /** * intel_engines_init_common - initialize cengine state which might require hw access * @engine: Engine to initialize. diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 1138b5c56e2f8..4cc385e1e77ea 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -5306,6 +5306,14 @@ populate_lr_context(struct intel_context *ce, return 0; } +static struct intel_timeline *pinned_timeline(struct intel_context *ce) +{ + struct intel_timeline *tl = fetch_and_zero(&ce->timeline); + + return intel_timeline_create_from_engine(ce->engine, + page_unmask_bits(tl)); +} + static int __execlists_context_alloc(struct intel_context *ce, struct intel_engine_cs *engine) { @@ -5336,19 +5344,17 @@ static int __execlists_context_alloc(struct intel_context *ce, goto error_deref_obj; } - if (!ce->timeline) { + if (!page_mask_bits(ce->timeline)) { struct intel_timeline *tl; - struct i915_vma *hwsp; /* * Use the static global HWSP for the kernel context, and * a dynamically allocated cacheline for everyone else. */ - hwsp = NULL; - if (unlikely(intel_context_is_barrier(ce))) - hwsp = engine->status_page.vma; - - tl = intel_timeline_create(engine->gt, hwsp); + if (unlikely(ce->timeline)) + tl = pinned_timeline(ce); + else + tl = intel_timeline_create(engine->gt); if (IS_ERR(tl)) { ret = PTR_ERR(tl); goto error_deref_obj; diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 94915f668715d..87cef6d011418 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1250,7 +1250,8 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) return -ENODEV; } - timeline = intel_timeline_create(engine->gt, engine->status_page.vma); + timeline = intel_timeline_create_from_engine(engine, + I915_GEM_HWS_SEQNO_ADDR); if (IS_ERR(timeline)) { err = PTR_ERR(timeline); goto err; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 46d20f5f3ddcc..4f446534bad07 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -215,7 +215,8 @@ static void cacheline_free(struct intel_timeline_cacheline *cl) static int intel_timeline_init(struct intel_timeline *timeline, struct intel_gt *gt, - struct i915_vma *hwsp) + struct i915_vma *hwsp, + unsigned int offset) { void *vaddr; @@ -246,8 +247,7 @@ static int intel_timeline_init(struct intel_timeline *timeline, vaddr = page_mask_bits(cl->vaddr); } else { - timeline->hwsp_offset = I915_GEM_HWS_SEQNO_ADDR; - + timeline->hwsp_offset = offset; vaddr = i915_gem_object_pin_map(hwsp->obj, I915_MAP_WB); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -297,7 +297,9 @@ static void intel_timeline_fini(struct intel_timeline *timeline) } struct intel_timeline * -intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp) +__intel_timeline_create(struct intel_gt *gt, + struct i915_vma *global_hwsp, + unsigned int offset) { struct intel_timeline *timeline; int err; @@ -306,7 +308,7 @@ intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp) if (!timeline) return ERR_PTR(-ENOMEM); - err = intel_timeline_init(timeline, gt, global_hwsp); + err = intel_timeline_init(timeline, gt, global_hwsp, offset); if (err) { kfree(timeline); return ERR_PTR(err); diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.h b/drivers/gpu/drm/i915/gt/intel_timeline.h index 4298b9ac7327e..06bd06c6595fe 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline.h @@ -29,10 +29,27 @@ #include "i915_active.h" #include "i915_syncmap.h" -#include "gt/intel_timeline_types.h" +#include "intel_timeline_types.h" struct intel_timeline * -intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp); +__intel_timeline_create(struct intel_gt *gt, + struct i915_vma *global_hwsp, + unsigned int offset); + +static inline struct intel_timeline * +intel_timeline_create(struct intel_gt *gt) +{ + return __intel_timeline_create(gt, NULL, 0); +} + +static inline struct intel_timeline * +intel_timeline_create_from_engine(struct intel_engine_cs *engine, + unsigned int offset) +{ + return __intel_timeline_create(engine->gt, + engine->status_page.vma, + offset); +} static inline struct intel_timeline * intel_timeline_get(struct intel_timeline *timeline) diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 06303ba98c191..d5beb116261f0 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -153,7 +153,7 @@ static int mock_context_alloc(struct intel_context *ce) return -ENOMEM; GEM_BUG_ON(ce->timeline); - ce->timeline = intel_timeline_create(ce->engine->gt, NULL); + ce->timeline = intel_timeline_create(ce->engine->gt); if (IS_ERR(ce->timeline)) { kfree(ce->engine); return PTR_ERR(ce->timeline); diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 6564c989dbee4..98ceac2fb77de 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -72,7 +72,7 @@ static int __mock_hwsp_timeline(struct mock_hwsp_freelist *state, unsigned long cacheline; int err; - tl = intel_timeline_create(state->gt, NULL); + tl = intel_timeline_create(state->gt); if (IS_ERR(tl)) return PTR_ERR(tl); @@ -487,7 +487,7 @@ checked_intel_timeline_create(struct intel_gt *gt) { struct intel_timeline *tl; - tl = intel_timeline_create(gt, NULL); + tl = intel_timeline_create(gt); if (IS_ERR(tl)) return tl; @@ -660,7 +660,7 @@ static int live_hwsp_wrap(void *arg) * foreign GPU references. */ - tl = intel_timeline_create(gt, NULL); + tl = intel_timeline_create(gt); if (IS_ERR(tl)) return PTR_ERR(tl); -- GitLab From 13106019f79bee105af1d3afdcb38b38771d81b9 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 30 Jul 2020 14:40:49 +0100 Subject: [PATCH 0803/1494] drm/i915/gt: Pull release of node->age under the spinlock We need to ensure that the list is valid prior to marking the node as retrievable, otherwise we may see two threads compete over the same node in intel_gt_get_buffer_pool(). If the first thread acquires and releases the node in the same jiffie, the second thread may then acquire it (as the jiffie now again matches the expected value) and claim the node before it is put back into the list. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200730134049.8822-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 9e938d4f6bfe1..4b7671ac5dca4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -134,9 +134,9 @@ static void pool_retire(struct i915_active *ref) /* Return this object to the shrinker pool */ i915_gem_object_make_purgeable(node->obj); - WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_lock_irqsave(&pool->lock, flags); list_add_rcu(&node->link, list); + WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_unlock_irqrestore(&pool->lock, flags); schedule_delayed_work(&pool->work, -- GitLab From bde246d893fca22cf84f6fb044395ab0a47589b7 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 11:22:06 +0100 Subject: [PATCH 0804/1494] drm/i915/selftests: Drop stale timeline constructor assert Since we pass around encoded parameters to the kernel context constructor using the ce->timeline pointer, we can no longer assert that it should be zero for mock timeline construction. Fixes: d1bf5dd8f6d5 ("drm/i915/gt: Support multiple pinned timelines") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731102206.6793-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Updated Fixes: link after rebasing and reordering into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/mock_engine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index d5beb116261f0..027de53cd05b8 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -152,7 +152,6 @@ static int mock_context_alloc(struct intel_context *ce) if (!ce->ring) return -ENOMEM; - GEM_BUG_ON(ce->timeline); ce->timeline = intel_timeline_create(ce->engine->gt); if (IS_ERR(ce->timeline)) { kfree(ce->engine); -- GitLab From 04240e30ed06498c02dd43e57dfef9433e5f1ced Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:10 +0100 Subject: [PATCH 0805/1494] drm/i915: Skip taking acquire mutex for no ref->active callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If no active callback is defined for i915_active, we do not need to serialise its enabling with the mutex. We still do only want to call the debug activate once, and must still serialise with a concurrent retire. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_active.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 1e12532074258..8c6197f8dd0b1 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -416,6 +416,14 @@ bool i915_active_acquire_if_busy(struct i915_active *ref) return atomic_add_unless(&ref->count, 1, 0); } +static void __i915_active_activate(struct i915_active *ref) +{ + spin_lock_irq(&ref->tree_lock); /* __active_retire() */ + if (!atomic_fetch_inc(&ref->count)) + debug_active_activate(ref); + spin_unlock_irq(&ref->tree_lock); +} + int i915_active_acquire(struct i915_active *ref) { int err; @@ -423,19 +431,19 @@ int i915_active_acquire(struct i915_active *ref) if (i915_active_acquire_if_busy(ref)) return 0; + if (!ref->active) { + __i915_active_activate(ref); + return 0; + } + err = mutex_lock_interruptible(&ref->mutex); if (err) return err; if (likely(!i915_active_acquire_if_busy(ref))) { - if (ref->active) - err = ref->active(ref); - if (!err) { - spin_lock_irq(&ref->tree_lock); /* __active_retire() */ - debug_active_activate(ref); - atomic_inc(&ref->count); - spin_unlock_irq(&ref->tree_lock); - } + err = ref->active(ref); + if (!err) + __i915_active_activate(ref); } mutex_unlock(&ref->mutex); -- GitLab From 5d9341370f57c058a8d880490ba9e79e761b2d7a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:11 +0100 Subject: [PATCH 0806/1494] drm/i915: Export a preallocate variant of i915_active_acquire() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes we have to be very careful not to allocate underneath a mutex (or spinlock) and yet still want to track activity. Enter i915_active_acquire_for_context(). This raises the activity counter on i915_active prior to use and ensures that the fence-tree contains a slot for the context. v2: Refactor active_lookup() so it can be called again before/after locking to resolve contention. Since we protect the rbtree until we idle, we can do a lockfree lookup, with the caveat that if another thread performs a concurrent insertion, the rotations from the insert may cause us to not find our target. A second pass holding the treelock will find the target if it exists, or the place to perform our insertion. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/gt/intel_timeline.c | 4 +- drivers/gpu/drm/i915/i915_active.c | 150 ++++++++++++++---- drivers/gpu/drm/i915/i915_active.h | 12 +- 4 files changed, 130 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 90d77cdc6f661..9ce114d672887 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1741,7 +1741,7 @@ __parser_mark_active(struct i915_vma *vma, { struct intel_gt_buffer_pool_node *node = vma->private; - return i915_active_ref(&node->active, tl, fence); + return i915_active_ref(&node->active, tl->fence_context, fence); } static int diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 4f446534bad07..2baecf414acb4 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -486,7 +486,9 @@ __intel_timeline_get_seqno(struct intel_timeline *tl, * free it after the current request is retired, which ensures that * all writes into the cacheline from previous requests are complete. */ - err = i915_active_ref(&tl->hwsp_cacheline->active, tl, &rq->fence); + err = i915_active_ref(&tl->hwsp_cacheline->active, + tl->fence_context, + &rq->fence); if (err) goto err_cacheline; diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 8c6197f8dd0b1..9890db303fed1 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -28,12 +28,14 @@ static struct i915_global_active { } global; struct active_node { + struct rb_node node; struct i915_active_fence base; struct i915_active *ref; - struct rb_node node; u64 timeline; }; +#define fetch_node(x) rb_entry(READ_ONCE(x), typeof(struct active_node), node) + static inline struct active_node * node_from_active(struct i915_active_fence *active) { @@ -216,12 +218,9 @@ excl_retire(struct dma_fence *fence, struct dma_fence_cb *cb) active_retire(container_of(cb, struct i915_active, excl.cb)); } -static struct i915_active_fence * -active_instance(struct i915_active *ref, struct intel_timeline *tl) +static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) { - struct active_node *node, *prealloc; - struct rb_node **p, *parent; - u64 idx = tl->fence_context; + struct active_node *it; /* * We track the most recently used timeline to skip a rbtree search @@ -230,8 +229,39 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) * after the previous activity has been retired, or if it matches the * current timeline. */ - node = READ_ONCE(ref->cache); - if (node && node->timeline == idx) + it = READ_ONCE(ref->cache); + if (it && it->timeline == idx) + return it; + + BUILD_BUG_ON(offsetof(typeof(*it), node)); + + /* While active, the tree can only be built; not destroyed */ + GEM_BUG_ON(i915_active_is_idle(ref)); + + it = fetch_node(ref->tree.rb_node); + while (it) { + if (it->timeline < idx) { + it = fetch_node(it->node.rb_right); + } else if (it->timeline > idx) { + it = fetch_node(it->node.rb_left); + } else { + WRITE_ONCE(ref->cache, it); + break; + } + } + + /* NB: If the tree rotated beneath us, we may miss our target. */ + return it; +} + +static struct i915_active_fence * +active_instance(struct i915_active *ref, u64 idx) +{ + struct active_node *node, *prealloc; + struct rb_node **p, *parent; + + node = __active_lookup(ref, idx); + if (likely(node)) return &node->base; /* Preallocate a replacement, just in case */ @@ -268,10 +298,9 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) rb_insert_color(&node->node, &ref->tree); out: - ref->cache = node; + WRITE_ONCE(ref->cache, node); spin_unlock_irq(&ref->tree_lock); - BUILD_BUG_ON(offsetof(typeof(*node), base)); return &node->base; } @@ -353,63 +382,102 @@ __active_del_barrier(struct i915_active *ref, struct active_node *node) return ____active_del_barrier(ref, node, barrier_to_engine(node)); } -int i915_active_ref(struct i915_active *ref, - struct intel_timeline *tl, - struct dma_fence *fence) +static bool +replace_barrier(struct i915_active *ref, struct i915_active_fence *active) +{ + if (!is_barrier(active)) /* proto-node used by our idle barrier? */ + return false; + + /* + * This request is on the kernel_context timeline, and so + * we can use it to substitute for the pending idle-barrer + * request that we want to emit on the kernel_context. + */ + __active_del_barrier(ref, node_from_active(active)); + return true; +} + +int i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence) { struct i915_active_fence *active; int err; - lockdep_assert_held(&tl->mutex); - /* Prevent reaping in case we malloc/wait while building the tree */ err = i915_active_acquire(ref); if (err) return err; - active = active_instance(ref, tl); + active = active_instance(ref, idx); if (!active) { err = -ENOMEM; goto out; } - if (is_barrier(active)) { /* proto-node used by our idle barrier */ - /* - * This request is on the kernel_context timeline, and so - * we can use it to substitute for the pending idle-barrer - * request that we want to emit on the kernel_context. - */ - __active_del_barrier(ref, node_from_active(active)); + if (replace_barrier(ref, active)) { RCU_INIT_POINTER(active->fence, NULL); atomic_dec(&ref->count); } if (!__i915_active_fence_set(active, fence)) - atomic_inc(&ref->count); + __i915_active_acquire(ref); out: i915_active_release(ref); return err; } -struct dma_fence * -i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f) +static struct dma_fence * +__i915_active_set_fence(struct i915_active *ref, + struct i915_active_fence *active, + struct dma_fence *fence) { struct dma_fence *prev; - /* We expect the caller to manage the exclusive timeline ordering */ - GEM_BUG_ON(i915_active_is_idle(ref)); + if (replace_barrier(ref, active)) { + RCU_INIT_POINTER(active->fence, fence); + return NULL; + } rcu_read_lock(); - prev = __i915_active_fence_set(&ref->excl, f); + prev = __i915_active_fence_set(active, fence); if (prev) prev = dma_fence_get_rcu(prev); else - atomic_inc(&ref->count); + __i915_active_acquire(ref); rcu_read_unlock(); return prev; } +static struct i915_active_fence * +__active_fence(struct i915_active *ref, u64 idx) +{ + struct active_node *it; + + it = __active_lookup(ref, idx); + if (unlikely(!it)) { /* Contention with parallel tree builders! */ + spin_lock_irq(&ref->tree_lock); + it = __active_lookup(ref, idx); + spin_unlock_irq(&ref->tree_lock); + } + GEM_BUG_ON(!it); /* slot must be preallocated */ + + return &it->base; +} + +struct dma_fence * +__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence) +{ + /* Only valid while active, see i915_active_acquire_for_context() */ + return __i915_active_set_fence(ref, __active_fence(ref, idx), fence); +} + +struct dma_fence * +i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f) +{ + /* We expect the caller to manage the exclusive timeline ordering */ + return __i915_active_set_fence(ref, &ref->excl, f); +} + bool i915_active_acquire_if_busy(struct i915_active *ref) { debug_active_assert(ref); @@ -451,6 +519,24 @@ int i915_active_acquire(struct i915_active *ref) return err; } +int i915_active_acquire_for_context(struct i915_active *ref, u64 idx) +{ + struct i915_active_fence *active; + int err; + + err = i915_active_acquire(ref); + if (err) + return err; + + active = active_instance(ref, idx); + if (!active) { + i915_active_release(ref); + return -ENOMEM; + } + + return 0; /* return with active ref */ +} + void i915_active_release(struct i915_active *ref) { debug_active_assert(ref); @@ -754,7 +840,7 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) match: rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */ if (p == &ref->cache->node) - ref->cache = NULL; + WRITE_ONCE(ref->cache, NULL); spin_unlock_irq(&ref->tree_lock); return rb_entry(p, struct active_node, node); @@ -809,7 +895,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, */ RCU_INIT_POINTER(node->base.fence, ERR_PTR(-EAGAIN)); node->base.cb.node.prev = (void *)engine; - atomic_inc(&ref->count); + __i915_active_acquire(ref); } GEM_BUG_ON(rcu_access_pointer(node->base.fence) != ERR_PTR(-EAGAIN)); diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index cf40581509667..73ded3c52a04b 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -163,14 +163,16 @@ void __i915_active_init(struct i915_active *ref, __i915_active_init(ref, active, retire, &__mkey, &__wkey); \ } while (0) -int i915_active_ref(struct i915_active *ref, - struct intel_timeline *tl, - struct dma_fence *fence); +struct dma_fence * +__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence); +int i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence); static inline int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) { - return i915_active_ref(ref, i915_request_timeline(rq), &rq->fence); + return i915_active_ref(ref, + i915_request_timeline(rq)->fence_context, + &rq->fence); } struct dma_fence * @@ -198,7 +200,9 @@ int i915_request_await_active(struct i915_request *rq, #define I915_ACTIVE_AWAIT_BARRIER BIT(2) int i915_active_acquire(struct i915_active *ref); +int i915_active_acquire_for_context(struct i915_active *ref, u64 idx); bool i915_active_acquire_if_busy(struct i915_active *ref); + void i915_active_release(struct i915_active *ref); static inline void __i915_active_acquire(struct i915_active *ref) -- GitLab From 99a7f4dae7ee6081df04741e0c4ea5e49b139540 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:12 +0100 Subject: [PATCH 0807/1494] drm/i915: Keep the most recently used active-fence upon discard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever an i915_active idles, we prune its tree of old fence slots to prevent a gradual leak should it be used to track many, many timelines. The downside is that we then have to frequently reallocate the rbtree. A compromise is that we keep the most recently used fence slot, and reuse that for the next active reference as that is the most likely timeline to be reused. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-4-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_active.c | 27 ++++++++++++++++++++------- drivers/gpu/drm/i915/i915_active.h | 4 ---- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 9890db303fed1..e63578c80f534 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -130,8 +130,8 @@ static inline void debug_active_assert(struct i915_active *ref) { } static void __active_retire(struct i915_active *ref) { + struct rb_root root = RB_ROOT; struct active_node *it, *n; - struct rb_root root; unsigned long flags; GEM_BUG_ON(i915_active_is_idle(ref)); @@ -143,9 +143,21 @@ __active_retire(struct i915_active *ref) GEM_BUG_ON(rcu_access_pointer(ref->excl.fence)); debug_active_deactivate(ref); - root = ref->tree; - ref->tree = RB_ROOT; - ref->cache = NULL; + /* Even if we have not used the cache, we may still have a barrier */ + if (!ref->cache) + ref->cache = fetch_node(ref->tree.rb_node); + + /* Keep the MRU cached node for reuse */ + if (ref->cache) { + /* Discard all other nodes in the tree */ + rb_erase(&ref->cache->node, &ref->tree); + root = ref->tree; + + /* Rebuild the tree with only the cached node */ + rb_link_node(&ref->cache->node, NULL, &ref->tree.rb_node); + rb_insert_color(&ref->cache->node, &ref->tree); + GEM_BUG_ON(ref->tree.rb_node != &ref->cache->node); + } spin_unlock_irqrestore(&ref->tree_lock, flags); @@ -156,6 +168,7 @@ __active_retire(struct i915_active *ref) /* ... except if you wait on it, you must manage your own references! */ wake_up_var(ref); + /* Finally free the discarded timeline tree */ rbtree_postorder_for_each_entry_safe(it, n, &root, node) { GEM_BUG_ON(i915_active_fence_isset(&it->base)); kmem_cache_free(global.slab_cache, it); @@ -745,16 +758,16 @@ int i915_sw_fence_await_active(struct i915_sw_fence *fence, return await_active(ref, flags, sw_await_fence, fence, fence); } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) void i915_active_fini(struct i915_active *ref) { debug_active_fini(ref); GEM_BUG_ON(atomic_read(&ref->count)); GEM_BUG_ON(work_pending(&ref->work)); - GEM_BUG_ON(!RB_EMPTY_ROOT(&ref->tree)); mutex_destroy(&ref->mutex); + + if (ref->cache) + kmem_cache_free(global.slab_cache, ref->cache); } -#endif static inline bool is_idle_barrier(struct active_node *node, u64 idx) { diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index 73ded3c52a04b..b9e0394e29752 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -217,11 +217,7 @@ i915_active_is_idle(const struct i915_active *ref) return !atomic_read(&ref->count); } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) void i915_active_fini(struct i915_active *ref); -#else -static inline void i915_active_fini(struct i915_active *ref) { } -#endif int i915_active_acquire_preallocate_barrier(struct i915_active *ref, struct intel_engine_cs *engine); -- GitLab From e28860ae21da258a1f983b52941a3f581281d114 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:13 +0100 Subject: [PATCH 0808/1494] drm/i915: Make the stale cached active node available for any timeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than require the next timeline after idling to match the MRU before idling, reset the index on the node and allow it to match the first request. However, this requires cmpxchg(u64) and so is not trivial on 32b, so for compatibility we just fallback to keeping the cached node pointing to the MRU timeline. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-5-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_active.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index e63578c80f534..89c34a69a2eaa 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -157,6 +157,10 @@ __active_retire(struct i915_active *ref) rb_link_node(&ref->cache->node, NULL, &ref->tree.rb_node); rb_insert_color(&ref->cache->node, &ref->tree); GEM_BUG_ON(ref->tree.rb_node != &ref->cache->node); + + /* Make the cached node available for reuse with any timeline */ + if (IS_ENABLED(CONFIG_64BIT)) + ref->cache->timeline = 0; /* needs cmpxchg(u64) */ } spin_unlock_irqrestore(&ref->tree_lock, flags); @@ -235,6 +239,8 @@ static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) { struct active_node *it; + GEM_BUG_ON(idx == 0); /* 0 is the unordered timeline, rsvd for cache */ + /* * We track the most recently used timeline to skip a rbtree search * for the common case, under typical loads we never need the rbtree @@ -243,8 +249,28 @@ static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) * current timeline. */ it = READ_ONCE(ref->cache); - if (it && it->timeline == idx) - return it; + if (it) { + u64 cached = READ_ONCE(it->timeline); + + /* Once claimed, this slot will only belong to this idx */ + if (cached == idx) + return it; + +#ifdef CONFIG_64BIT /* for cmpxchg(u64) */ + /* + * An unclaimed cache [.timeline=0] can only be claimed once. + * + * If the value is already non-zero, some other thread has + * claimed the cache and we know that is does not match our + * idx. If, and only if, the timeline is currently zero is it + * worth competing to claim it atomically for ourselves (for + * only the winner of that race will cmpxchg return the old + * value of 0). + */ + if (!cached && !cmpxchg(&it->timeline, 0, idx)) + return it; +#endif + } BUILD_BUG_ON(offsetof(typeof(*it), node)); -- GitLab From 9ff33bbcda259a7d1d4df8c977b32cf431972387 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:14 +0100 Subject: [PATCH 0809/1494] drm/i915: Reduce locking around i915_active_acquire_preallocate_barrier() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the conversion between idle-barrier and full i915_active_fence is already serialised by explicit memory barriers, we can reduce the spinlock in i915_active_acquire_preallocate_barrier() for finding an idle-barrier to reuse to an RCU read lock to ensure the fence remains valid, only taking the spinlock for the update of the rbtree itself. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-6-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_active.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 89c34a69a2eaa..b0a6522be3d14 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -807,7 +807,6 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) if (RB_EMPTY_ROOT(&ref->tree)) return NULL; - spin_lock_irq(&ref->tree_lock); GEM_BUG_ON(i915_active_is_idle(ref)); /* @@ -833,9 +832,9 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) prev = p; if (node->timeline < idx) - p = p->rb_right; + p = READ_ONCE(p->rb_right); else - p = p->rb_left; + p = READ_ONCE(p->rb_left); } /* @@ -872,11 +871,10 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) goto match; } - spin_unlock_irq(&ref->tree_lock); - return NULL; match: + spin_lock_irq(&ref->tree_lock); rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */ if (p == &ref->cache->node) WRITE_ONCE(ref->cache, NULL); @@ -910,7 +908,9 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, struct llist_node *prev = first; struct active_node *node; + rcu_read_lock(); node = reuse_idle_barrier(ref, idx); + rcu_read_unlock(); if (!node) { node = kmem_cache_alloc(global.slab_cache, GFP_KERNEL); if (!node) -- GitLab From af5c6fcf403288e8656143549881c3eb716cae53 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 09:50:15 +0100 Subject: [PATCH 0810/1494] drm/i915: Provide a fastpath for waiting on vma bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before we can execute a request, we must wait for all of its vma to be bound. This is a frequent operation for which we can optimise away a few atomic operations (notably a cmpxchg) in lieu of the RCU protection. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-7-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_active.h | 15 +++++++++++++++ drivers/gpu/drm/i915/i915_vma.c | 9 +++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index b9e0394e29752..fb165d3f01cf3 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -231,4 +231,19 @@ struct i915_active *i915_active_create(void); struct i915_active *i915_active_get(struct i915_active *ref); void i915_active_put(struct i915_active *ref); +static inline int __i915_request_await_exclusive(struct i915_request *rq, + struct i915_active *active) +{ + struct dma_fence *fence; + int err = 0; + + fence = i915_active_fence_get(&active->excl); + if (fence) { + err = i915_request_await_dma_fence(rq, fence); + dma_fence_put(fence); + } + + return err; +} + #endif /* _I915_ACTIVE_H_ */ diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index bc64f773dcdb4..cd12047c77911 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1167,6 +1167,12 @@ void i915_vma_revoke_mmap(struct i915_vma *vma) list_del(&vma->obj->userfault_link); } +static int +__i915_request_await_bind(struct i915_request *rq, struct i915_vma *vma) +{ + return __i915_request_await_exclusive(rq, &vma->active); +} + int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq) { int err; @@ -1174,8 +1180,7 @@ int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq) GEM_BUG_ON(!i915_vma_is_pinned(vma)); /* Wait for the vma to be bound before we start! */ - err = i915_request_await_active(rq, &vma->active, - I915_ACTIVE_AWAIT_EXCL); + err = __i915_request_await_bind(rq, vma); if (err) return err; -- GitLab From c18636f76344fd544c5b444d030a2d1d74bb0103 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 16:48:31 +0100 Subject: [PATCH 0811/1494] drm/i915: Remove requirement for holding i915_request.lock for breadcrumbs Since the breadcrumb enabling/cancelling itself is serialised by the breadcrumbs.irq_lock, with a bit of care we can remove the outer serialisation with i915_request.lock for concurrent dma_fence_enable_signaling(). This has the important side-effect of eliminating the nested i915_request.lock within request submission. The challenge in serialisation is around the unsubmission where we take an active request that wants a breadcrumb on the signaling engine and put it to sleep. We do not want a concurrent dma_fence_enable_signaling() to attach a breadcrumb as we unsubmit, so we must mark the request as no longer active before serialising with the concurrent enable-signaling. On retire, we serialise with the concurrent enable-signaling, but instead of clearing ACTIVE, we mark it as SIGNALED. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Rebased and reordered into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 130 +++++++++++++------- drivers/gpu/drm/i915/gt/intel_lrc.c | 14 --- drivers/gpu/drm/i915/i915_request.c | 66 ++++++---- 3 files changed, 123 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 91786310c1148..3d211a0c2b5a1 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -220,17 +220,17 @@ static void signal_irq_work(struct irq_work *work) } } -static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) +static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { struct intel_engine_cs *engine = container_of(b, struct intel_engine_cs, breadcrumbs); lockdep_assert_held(&b->irq_lock); if (b->irq_armed) - return true; + return; if (!intel_gt_pm_get_if_awake(engine->gt)) - return false; + return; /* * The breadcrumb irq will be disarmed on the interrupt after the @@ -250,8 +250,6 @@ static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) if (!b->irq_enabled++) irq_enable(engine); - - return true; } void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) @@ -310,57 +308,99 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) { } -bool i915_request_enable_breadcrumb(struct i915_request *rq) +static void insert_breadcrumb(struct i915_request *rq, + struct intel_breadcrumbs *b) { - lockdep_assert_held(&rq->lock); + struct intel_context *ce = rq->context; + struct list_head *pos; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) - return true; + if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) + return; - if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) { - struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; - struct intel_context *ce = rq->context; - struct list_head *pos; + __intel_breadcrumbs_arm_irq(b); - spin_lock(&b->irq_lock); + /* + * We keep the seqno in retirement order, so we can break + * inside intel_engine_signal_breadcrumbs as soon as we've + * passed the last completed request (or seen a request that + * hasn't event started). We could walk the timeline->requests, + * but keeping a separate signalers_list has the advantage of + * hopefully being much smaller than the full list and so + * provides faster iteration and detection when there are no + * more interrupts required for this context. + * + * We typically expect to add new signalers in order, so we + * start looking for our insertion point from the tail of + * the list. + */ + list_for_each_prev(pos, &ce->signals) { + struct i915_request *it = + list_entry(pos, typeof(*it), signal_link); - if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) - goto unlock; + if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) + break; + } + list_add(&rq->signal_link, pos); + if (pos == &ce->signals) /* catch transitions from empty list */ + list_move_tail(&ce->signal_link, &b->signalers); + GEM_BUG_ON(!check_signal_order(ce, rq)); - if (!__intel_breadcrumbs_arm_irq(b)) - goto unlock; + set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); +} - /* - * We keep the seqno in retirement order, so we can break - * inside intel_engine_signal_breadcrumbs as soon as we've - * passed the last completed request (or seen a request that - * hasn't event started). We could walk the timeline->requests, - * but keeping a separate signalers_list has the advantage of - * hopefully being much smaller than the full list and so - * provides faster iteration and detection when there are no - * more interrupts required for this context. - * - * We typically expect to add new signalers in order, so we - * start looking for our insertion point from the tail of - * the list. - */ - list_for_each_prev(pos, &ce->signals) { - struct i915_request *it = - list_entry(pos, typeof(*it), signal_link); +bool i915_request_enable_breadcrumb(struct i915_request *rq) +{ + struct intel_breadcrumbs *b; - if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) - break; - } - list_add(&rq->signal_link, pos); - if (pos == &ce->signals) /* catch transitions from empty list */ - list_move_tail(&ce->signal_link, &b->signalers); - GEM_BUG_ON(!check_signal_order(ce, rq)); + /* Serialises with i915_request_retire() using rq->lock */ + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) + return true; - set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); -unlock: + /* + * Peek at i915_request_submit()/i915_request_unsubmit() status. + * + * If the request is not yet active (and not signaled), we will + * attach the breadcrumb later. + */ + if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) + return true; + + /* + * rq->engine is locked by rq->engine->active.lock. That however + * is not known until after rq->engine has been dereferenced and + * the lock acquired. Hence we acquire the lock and then validate + * that rq->engine still matches the lock we hold for it. + * + * Here, we are using the breadcrumb lock as a proxy for the + * rq->engine->active.lock, and we know that since the breadcrumb + * will be serialised within i915_request_submit/i915_request_unsubmit, + * the engine cannot change while active as long as we hold the + * breadcrumb lock on that engine. + * + * From the dma_fence_enable_signaling() path, we are outside of the + * request submit/unsubmit path, and so we must be more careful to + * acquire the right lock. + */ + b = &READ_ONCE(rq->engine)->breadcrumbs; + spin_lock(&b->irq_lock); + while (unlikely(b != &READ_ONCE(rq->engine)->breadcrumbs)) { spin_unlock(&b->irq_lock); + b = &READ_ONCE(rq->engine)->breadcrumbs; + spin_lock(&b->irq_lock); } + /* + * Now that we are finally serialised with request submit/unsubmit, + * [with b->irq_lock] and with i915_request_retire() [via checking + * SIGNALED with rq->lock] confirm the request is indeed active. If + * it is no longer active, the breadcrumb will be attached upon + * i915_request_submit(). + */ + if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) + insert_breadcrumb(rq, b); + + spin_unlock(&b->irq_lock); + return !__request_completed(rq); } @@ -368,8 +408,6 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) { struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; - lockdep_assert_held(&rq->lock); - /* * We must wait for b->irq_lock so that we know the interrupt handler * has released its reference to the intel_context and has completed diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4cc385e1e77ea..35174bf332075 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1148,20 +1148,6 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine) } else { struct intel_engine_cs *owner = rq->context->engine; - /* - * Decouple the virtual breadcrumb before moving it - * back to the virtual engine -- we don't want the - * request to complete in the background and try - * and cancel the breadcrumb on the virtual engine - * (instead of the old engine where it is linked)! - */ - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, - &rq->fence.flags)) { - spin_lock_nested(&rq->lock, - SINGLE_DEPTH_NESTING); - i915_request_cancel_breadcrumb(rq); - spin_unlock(&rq->lock); - } WRITE_ONCE(rq->engine, owner); owner->submit_request(rq); active = NULL; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index bb0cf8199c2d9..956edbe5b196e 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -301,14 +301,24 @@ bool i915_request_retire(struct i915_request *rq) dma_fence_signal_locked(&rq->fence); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags)) i915_request_cancel_breadcrumb(rq); + spin_unlock_irq(&rq->lock); + if (i915_request_has_waitboost(rq)) { GEM_BUG_ON(!atomic_read(&rq->engine->gt->rps.num_waiters)); atomic_dec(&rq->engine->gt->rps.num_waiters); } - if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) { - set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags); - __notify_execute_cb(rq); - } + + /* + * We only loosely track inflight requests across preemption, + * and so we may find ourselves attempting to retire a _completed_ + * request that we have removed from the HW and put back on a run + * queue. + * + * As we set I915_FENCE_FLAG_ACTIVE on the request, this should be + * after removing the breadcrumb and signaling it, so that we do not + * inadvertently attach the breadcrumb to a completed request. + */ + remove_from_engine(rq); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); spin_unlock_irq(&rq->lock); @@ -547,19 +557,21 @@ bool __i915_request_submit(struct i915_request *request) clear_bit(I915_FENCE_FLAG_PQUEUE, &request->fence.flags); } - /* We may be recursing from the signal callback of another i915 fence */ - if (!i915_request_signaled(request)) { - spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); - - __notify_execute_cb(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, - &request->fence.flags) && - !i915_request_enable_breadcrumb(request)) - intel_engine_signal_breadcrumbs(engine); + /* + * XXX Rollback bonded-execution on __i915_request_unsubmit()? + * + * In the future, perhaps when we have an active time-slicing scheduler, + * it will be interesting to unsubmit parallel execution and remove + * busywaits from the GPU until their master is restarted. This is + * quite hairy, we have to carefully rollback the fence and do a + * preempt-to-idle cycle on the target engine, all the while the + * master execute_cb may refire. + */ + __notify_execute_cb(request); - spin_unlock(&request->lock); - GEM_BUG_ON(!llist_empty(&request->execute_cb)); - } + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && + !i915_request_enable_breadcrumb(request)) + intel_engine_signal_breadcrumbs(engine); return result; } @@ -581,27 +593,27 @@ void __i915_request_unsubmit(struct i915_request *request) { struct intel_engine_cs *engine = request->engine; + /* + * Only unwind in reverse order, required so that the per-context list + * is kept in seqno/ring order. + */ RQ_TRACE(request, "\n"); GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->active.lock); /* - * Only unwind in reverse order, required so that the per-context list - * is kept in seqno/ring order. + * Before we remove this breadcrumb from the signal list, we have + * to ensure that a concurrent dma_fence_enable_signaling() does not + * attach itself. We first mark the request as no longer active and + * make sure that is visible to other cores, and then remove the + * breadcrumb if attached. */ - - /* We may be recursing from the signal callback of another i915 fence */ - spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); - + GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags)); + clear_bit_unlock(I915_FENCE_FLAG_ACTIVE, &request->fence.flags); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) i915_request_cancel_breadcrumb(request); - GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags)); - clear_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags); - - spin_unlock(&request->lock); - /* We've already spun, don't charge on resubmitting. */ if (request->sched.semaphores && i915_request_started(request)) request->sched.semaphores = 0; -- GitLab From 2854d866327a390540c71ca3f76ce516ae7af66f Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 16:48:32 +0100 Subject: [PATCH 0812/1494] drm/i915/gt: Replace intel_engine_transfer_stale_breadcrumbs After staring at the breadcrumb enabling/cancellation and coming to the conclusion that the cause of the mysterious stale breadcrumbs must the act of submitting a completed requests, we can then redirect those completed requests onto a dedicated signaled_list at the time of construction and so eliminate intel_engine_transfer_stale_breadcrumbs(). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 50 ++++++++------------- drivers/gpu/drm/i915/gt/intel_engine.h | 3 -- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 ------- drivers/gpu/drm/i915/i915_request.c | 5 +-- 4 files changed, 21 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 3d211a0c2b5a1..fbdc465a58700 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -142,16 +142,16 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) intel_engine_add_retire(engine, tl); } -static void __signal_request(struct i915_request *rq, struct list_head *signals) +static bool __signal_request(struct i915_request *rq, struct list_head *signals) { - GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)); clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); if (!__dma_fence_signal(&rq->fence)) - return; + return false; i915_request_get(rq); list_add_tail(&rq->signal_link, signals); + return true; } static void signal_irq_work(struct irq_work *work) @@ -278,32 +278,6 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) spin_unlock_irqrestore(&b->irq_lock, flags); } -void intel_engine_transfer_stale_breadcrumbs(struct intel_engine_cs *engine, - struct intel_context *ce) -{ - struct intel_breadcrumbs *b = &engine->breadcrumbs; - unsigned long flags; - - spin_lock_irqsave(&b->irq_lock, flags); - if (!list_empty(&ce->signals)) { - struct i915_request *rq, *next; - - /* Queue for executing the signal callbacks in the irq_work */ - list_for_each_entry_safe(rq, next, &ce->signals, signal_link) { - GEM_BUG_ON(rq->engine != engine); - GEM_BUG_ON(!__request_completed(rq)); - - __signal_request(rq, &b->signaled_requests); - } - - INIT_LIST_HEAD(&ce->signals); - list_del_init(&ce->signal_link); - - irq_work_queue(&b->irq_work); - } - spin_unlock_irqrestore(&b->irq_lock, flags); -} - void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) { } @@ -317,6 +291,17 @@ static void insert_breadcrumb(struct i915_request *rq, if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) return; + /* + * If the request is already completed, we can transfer it + * straight onto a signaled list, and queue the irq worker for + * its signal completion. + */ + if (__request_completed(rq)) { + if (__signal_request(rq, &b->signaled_requests)) + irq_work_queue(&b->irq_work); + return; + } + __intel_breadcrumbs_arm_irq(b); /* @@ -344,8 +329,11 @@ static void insert_breadcrumb(struct i915_request *rq, if (pos == &ce->signals) /* catch transitions from empty list */ list_move_tail(&ce->signal_link, &b->signalers); GEM_BUG_ON(!check_signal_order(ce, rq)); - set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); + + /* Check after attaching to irq, interrupt may have already fired. */ + if (__request_completed(rq)) + irq_work_queue(&b->irq_work); } bool i915_request_enable_breadcrumb(struct i915_request *rq) @@ -401,7 +389,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) spin_unlock(&b->irq_lock); - return !__request_completed(rq); + return true; } void i915_request_cancel_breadcrumb(struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index a9249a23903a9..faf00a353e253 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -237,9 +237,6 @@ intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_transfer_stale_breadcrumbs(struct intel_engine_cs *engine, - struct intel_context *ce); - void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, struct drm_printer *p); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 35174bf332075..17e70778bf9d2 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1805,18 +1805,6 @@ static bool virtual_matches(const struct virtual_engine *ve, return true; } -static void virtual_xfer_breadcrumbs(struct virtual_engine *ve) -{ - /* - * All the outstanding signals on ve->siblings[0] must have - * been completed, just pending the interrupt handler. As those - * signals still refer to the old sibling (via rq->engine), we must - * transfer those to the old irq_worker to keep our locking - * consistent. - */ - intel_engine_transfer_stale_breadcrumbs(ve->siblings[0], &ve->context); -} - #define for_each_waiter(p__, rq__) \ list_for_each_entry_lockless(p__, \ &(rq__)->sched.waiters_list, \ @@ -2267,9 +2255,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) virtual_update_register_offsets(regs, engine); - if (!list_empty(&ve->context.signals)) - virtual_xfer_breadcrumbs(ve); - /* * Move the bound engine to the top of the list * for future execution. We then kick this diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 956edbe5b196e..e9d5ce247ae98 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -569,9 +569,8 @@ bool __i915_request_submit(struct i915_request *request) */ __notify_execute_cb(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && - !i915_request_enable_breadcrumb(request)) - intel_engine_signal_breadcrumbs(engine); + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) + i915_request_enable_breadcrumb(request); return result; } -- GitLab From 56f581bad4bf25b336593a7f7531b24424b1ecf8 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 16:48:33 +0100 Subject: [PATCH 0813/1494] drm/i915/gt: Only transfer the virtual context to the new engine if active One more complication of preempt-to-busy with respect to the virtual engine is that we may have retired the last request along the virtual engine at the same time as preparing to submit the completed request to a new engine. That submit will be shortcircuited, but not before we have updated the context with the new register offsets and marked the virtual engine as bound to the new engine (by calling swap on ve->siblings[]). As we may have just retired the completed request, we may also be in the middle of calling virtual_context_exit() to turn off the power management associated with the virtual engine, and that in turn walks the ve->siblings[]. If we happen to call swap() on the array as we walk, we will call intel_engine_pm_put() twice on the same engine. In this patch, we prevent this by only updating the bound engine after a successful submission which weeds out the already completed requests. Alternatively, we could walk a non-volatile array for the pm, such as using the engine->mask. The small advantage to performing the update after the submit is that we then only have to do a swap for active requests. Fixes: 22b7a426bbe1 ("drm/i915/execlists: Preempt-to-busy") References: 6d06779e8672 ("drm/i915: Load balancing across a virtual engine" Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: "Nayana, Venkata Ramana" <venkata.ramana.nayana@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_lrc.c | 65 ++++++++++++++++++----------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 17e70778bf9d2..e5a37d14bce80 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1805,6 +1805,33 @@ static bool virtual_matches(const struct virtual_engine *ve, return true; } +static void virtual_xfer_context(struct virtual_engine *ve, + struct intel_engine_cs *engine) +{ + unsigned int n; + + if (likely(engine == ve->siblings[0])) + return; + + GEM_BUG_ON(READ_ONCE(ve->context.inflight)); + if (!intel_engine_has_relative_mmio(engine)) + virtual_update_register_offsets(ve->context.lrc_reg_state, + engine); + + /* + * Move the bound engine to the top of the list for + * future execution. We then kick this tasklet first + * before checking others, so that we preferentially + * reuse this set of bound registers. + */ + for (n = 1; n < ve->num_siblings; n++) { + if (ve->siblings[n] == engine) { + swap(ve->siblings[n], ve->siblings[0]); + break; + } + } +} + #define for_each_waiter(p__, rq__) \ list_for_each_entry_lockless(p__, \ &(rq__)->sched.waiters_list, \ @@ -2245,35 +2272,23 @@ static void execlists_dequeue(struct intel_engine_cs *engine) GEM_BUG_ON(!(rq->execution_mask & engine->mask)); WRITE_ONCE(rq->engine, engine); - if (engine != ve->siblings[0]) { - u32 *regs = ve->context.lrc_reg_state; - unsigned int n; - - GEM_BUG_ON(READ_ONCE(ve->context.inflight)); - - if (!intel_engine_has_relative_mmio(engine)) - virtual_update_register_offsets(regs, - engine); - + if (__i915_request_submit(rq)) { /* - * Move the bound engine to the top of the list - * for future execution. We then kick this - * tasklet first before checking others, so that - * we preferentially reuse this set of bound - * registers. + * Only after we confirm that we will submit + * this request (i.e. it has not already + * completed), do we want to update the context. + * + * This serves two purposes. It avoids + * unnecessary work if we are resubmitting an + * already completed request after timeslicing. + * But more importantly, it prevents us altering + * ve->siblings[] on an idle context, where + * we may be using ve->siblings[] in + * virtual_context_enter / virtual_context_exit. */ - for (n = 1; n < ve->num_siblings; n++) { - if (ve->siblings[n] == engine) { - swap(ve->siblings[n], - ve->siblings[0]); - break; - } - } - + virtual_xfer_context(ve, engine); GEM_BUG_ON(ve->siblings[0] != engine); - } - if (__i915_request_submit(rq)) { submit = true; last = rq; } -- GitLab From b3786b29379c0e5d1e4e162ad5464d77aa4bc4db Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 31 Jul 2020 16:48:34 +0100 Subject: [PATCH 0814/1494] drm/i915/gt: Distinguish the virtual breadcrumbs from the irq breadcrumbs On the virtual engines, we only use the intel_breadcrumbs for tracking signaling of stale breadcrumbs from the irq_workers. They do not have any associated interrupt handling, active requests are passed to a physical engine and associated breadcrumb interrupt handler. This causes issues for us as we need to ensure that we do not actually try and enable interrupts and the powermanagement required for them on the virtual engine, as they will never be disabled. Instead, let's specify the physical engine used for interrupt handler on a particular breadcrumb. v2: Drop b->irq_armed = true mocking for no interrupt HW Fixes: 4fe6abb8f513 ("drm/i915/gt: Ignore irq enabling on the virtual engines") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-4-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 76 ++++++++++--------- drivers/gpu/drm/i915/gt/intel_breadcrumbs.h | 36 +++++++++ .../gpu/drm/i915/gt/intel_breadcrumbs_types.h | 47 ++++++++++++ drivers/gpu/drm/i915/gt/intel_engine.h | 17 ----- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 14 +++- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 3 +- drivers/gpu/drm/i915/gt/intel_engine_types.h | 31 +------- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 1 + drivers/gpu/drm/i915/gt/intel_lrc.c | 11 ++- drivers/gpu/drm/i915/gt/intel_reset.c | 1 + .../gpu/drm/i915/gt/intel_ring_submission.c | 3 +- drivers/gpu/drm/i915/gt/intel_rps.c | 1 + drivers/gpu/drm/i915/gt/mock_engine.c | 10 ++- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_request.c | 1 + drivers/gpu/drm/i915/i915_request.h | 4 - 16 files changed, 162 insertions(+), 95 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/intel_breadcrumbs.h create mode 100644 drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index fbdc465a58700..2ffd47a86656c 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -28,6 +28,7 @@ #include "i915_drv.h" #include "i915_trace.h" +#include "intel_breadcrumbs.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" @@ -55,30 +56,28 @@ static void irq_disable(struct intel_engine_cs *engine) static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - lockdep_assert_held(&b->irq_lock); + if (!b->irq_engine || !b->irq_armed) + return; + GEM_BUG_ON(!b->irq_enabled); if (!--b->irq_enabled) - irq_disable(engine); + irq_disable(b->irq_engine); WRITE_ONCE(b->irq_armed, false); - intel_gt_pm_put_async(engine->gt); + intel_gt_pm_put_async(b->irq_engine->gt); } -void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_park(struct intel_breadcrumbs *b) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; unsigned long flags; if (!READ_ONCE(b->irq_armed)) return; spin_lock_irqsave(&b->irq_lock, flags); - if (b->irq_armed) - __intel_breadcrumbs_disarm_irq(b); + __intel_breadcrumbs_disarm_irq(b); spin_unlock_irqrestore(&b->irq_lock, flags); } @@ -133,13 +132,8 @@ __dma_fence_signal__notify(struct dma_fence *fence, static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - - if (unlikely(intel_engine_is_virtual(engine))) - engine = intel_virtual_engine_get_sibling(engine, 0); - - intel_engine_add_retire(engine, tl); + if (b->irq_engine) + intel_engine_add_retire(b->irq_engine, tl); } static bool __signal_request(struct i915_request *rq, struct list_head *signals) @@ -164,7 +158,7 @@ static void signal_irq_work(struct irq_work *work) spin_lock(&b->irq_lock); - if (b->irq_armed && list_empty(&b->signalers)) + if (list_empty(&b->signalers)) __intel_breadcrumbs_disarm_irq(b); list_splice_init(&b->signaled_requests, &signal); @@ -222,14 +216,12 @@ static void signal_irq_work(struct irq_work *work) static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - lockdep_assert_held(&b->irq_lock); - if (b->irq_armed) + + if (!b->irq_engine || b->irq_armed) return; - if (!intel_gt_pm_get_if_awake(engine->gt)) + if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) return; /* @@ -249,37 +241,49 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) */ if (!b->irq_enabled++) - irq_enable(engine); + irq_enable(b->irq_engine); } -void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) +struct intel_breadcrumbs * +intel_breadcrumbs_create(struct intel_engine_cs *irq_engine) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct intel_breadcrumbs *b; + + b = kzalloc(sizeof(*b), GFP_KERNEL); + if (!b) + return NULL; spin_lock_init(&b->irq_lock); INIT_LIST_HEAD(&b->signalers); INIT_LIST_HEAD(&b->signaled_requests); init_irq_work(&b->irq_work, signal_irq_work); + + b->irq_engine = irq_engine; + + return b; } -void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_reset(struct intel_breadcrumbs *b) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; unsigned long flags; + if (!b->irq_engine) + return; + spin_lock_irqsave(&b->irq_lock, flags); if (b->irq_enabled) - irq_enable(engine); + irq_enable(b->irq_engine); else - irq_disable(engine); + irq_disable(b->irq_engine); spin_unlock_irqrestore(&b->irq_lock, flags); } -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_free(struct intel_breadcrumbs *b) { + kfree(b); } static void insert_breadcrumb(struct i915_request *rq, @@ -369,11 +373,11 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) * request submit/unsubmit path, and so we must be more careful to * acquire the right lock. */ - b = &READ_ONCE(rq->engine)->breadcrumbs; + b = READ_ONCE(rq->engine)->breadcrumbs; spin_lock(&b->irq_lock); - while (unlikely(b != &READ_ONCE(rq->engine)->breadcrumbs)) { + while (unlikely(b != READ_ONCE(rq->engine)->breadcrumbs)) { spin_unlock(&b->irq_lock); - b = &READ_ONCE(rq->engine)->breadcrumbs; + b = READ_ONCE(rq->engine)->breadcrumbs; spin_lock(&b->irq_lock); } @@ -394,7 +398,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) void i915_request_cancel_breadcrumb(struct i915_request *rq) { - struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; + struct intel_breadcrumbs *b = rq->engine->breadcrumbs; /* * We must wait for b->irq_lock so that we know the interrupt handler @@ -418,11 +422,11 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, struct drm_printer *p) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct intel_breadcrumbs *b = engine->breadcrumbs; struct intel_context *ce; struct i915_request *rq; - if (list_empty(&b->signalers)) + if (!b || list_empty(&b->signalers)) return; drm_printf(p, "Signals:\n"); diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h new file mode 100644 index 0000000000000..ed3d1deabfbd8 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_BREADCRUMBS__ +#define __INTEL_BREADCRUMBS__ + +#include <linux/irq_work.h> + +#include "intel_engine_types.h" + +struct drm_printer; +struct i915_request; +struct intel_breadcrumbs; + +struct intel_breadcrumbs * +intel_breadcrumbs_create(struct intel_engine_cs *irq_engine); +void intel_breadcrumbs_free(struct intel_breadcrumbs *b); + +void intel_breadcrumbs_reset(struct intel_breadcrumbs *b); +void intel_breadcrumbs_park(struct intel_breadcrumbs *b); + +static inline void +intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) +{ + irq_work_queue(&engine->breadcrumbs->irq_work); +} + +void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, + struct drm_printer *p); + +bool i915_request_enable_breadcrumb(struct i915_request *request); +void i915_request_cancel_breadcrumb(struct i915_request *request); + +#endif /* __INTEL_BREADCRUMBS__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h new file mode 100644 index 0000000000000..8e53b99426958 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_BREADCRUMBS_TYPES__ +#define __INTEL_BREADCRUMBS_TYPES__ + +#include <linux/irq_work.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +/* + * Rather than have every client wait upon all user interrupts, + * with the herd waking after every interrupt and each doing the + * heavyweight seqno dance, we delegate the task (of being the + * bottom-half of the user interrupt) to the first client. After + * every interrupt, we wake up one client, who does the heavyweight + * coherent seqno read and either goes back to sleep (if incomplete), + * or wakes up all the completed clients in parallel, before then + * transferring the bottom-half status to the next client in the queue. + * + * Compared to walking the entire list of waiters in a single dedicated + * bottom-half, we reduce the latency of the first waiter by avoiding + * a context switch, but incur additional coherent seqno reads when + * following the chain of request breadcrumbs. Since it is most likely + * that we have a single client waiting on each seqno, then reducing + * the overhead of waking that client is much preferred. + */ +struct intel_breadcrumbs { + spinlock_t irq_lock; /* protects the lists used in hardirq context */ + + /* Not all breadcrumbs are attached to physical HW */ + struct intel_engine_cs *irq_engine; + + struct list_head signalers; + struct list_head signaled_requests; + + struct irq_work irq_work; /* for use from inside irq_lock */ + + unsigned int irq_enabled; + + bool irq_armed; +}; + +#endif /* __INTEL_BREADCRUMBS_TYPES__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index faf00a353e253..08e2c000dcc3b 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -223,23 +223,6 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine, void intel_engine_init_execlists(struct intel_engine_cs *engine); -void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); - -void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); - -static inline void -intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) -{ - irq_work_queue(&engine->breadcrumbs.irq_work); -} - -void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); - -void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, - struct drm_printer *p); - static inline u32 *__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) { memset(batch, 0, 6 * sizeof(u32)); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 86651bbef3a02..ea4ba2afe9f96 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -28,6 +28,7 @@ #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine.h" #include "intel_engine_pm.h" @@ -700,8 +701,13 @@ static int engine_setup_common(struct intel_engine_cs *engine) if (err) return err; + engine->breadcrumbs = intel_breadcrumbs_create(engine); + if (!engine->breadcrumbs) { + err = -ENOMEM; + goto err_status; + } + intel_engine_init_active(engine, ENGINE_PHYSICAL); - intel_engine_init_breadcrumbs(engine); intel_engine_init_execlists(engine); intel_engine_init_cmd_parser(engine); intel_engine_init__pm(engine); @@ -716,6 +722,10 @@ static int engine_setup_common(struct intel_engine_cs *engine) intel_engine_init_ctx_wa(engine); return 0; + +err_status: + cleanup_status_page(engine); + return err; } struct measure_breadcrumb { @@ -914,9 +924,9 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) tasklet_kill(&engine->execlists.tasklet); /* flush the callback */ cleanup_status_page(engine); + intel_breadcrumbs_free(engine->breadcrumbs); intel_engine_fini_retire(engine); - intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); if (engine->default_state) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 8ec3eecf3e397..f7b2e07e22298 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -6,6 +6,7 @@ #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine.h" #include "intel_engine_heartbeat.h" @@ -247,7 +248,7 @@ static int __engine_park(struct intel_wakeref *wf) call_idle_barriers(engine); /* cleanup after wedging */ intel_engine_park_heartbeat(engine); - intel_engine_disarm_breadcrumbs(engine); + intel_breadcrumbs_park(engine->breadcrumbs); /* Must be reset upon idling, or we may miss the busy wakeup. */ GEM_BUG_ON(engine->execlists.queue_priority_hint != INT_MIN); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 8de92fd7d392f..c400aaa2287be 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -22,6 +22,7 @@ #include "i915_pmu.h" #include "i915_priolist_types.h" #include "i915_selftest.h" +#include "intel_breadcrumbs_types.h" #include "intel_sseu.h" #include "intel_timeline_types.h" #include "intel_uncore.h" @@ -373,34 +374,8 @@ struct intel_engine_cs { */ struct ewma__engine_latency latency; - /* Rather than have every client wait upon all user interrupts, - * with the herd waking after every interrupt and each doing the - * heavyweight seqno dance, we delegate the task (of being the - * bottom-half of the user interrupt) to the first client. After - * every interrupt, we wake up one client, who does the heavyweight - * coherent seqno read and either goes back to sleep (if incomplete), - * or wakes up all the completed clients in parallel, before then - * transferring the bottom-half status to the next client in the queue. - * - * Compared to walking the entire list of waiters in a single dedicated - * bottom-half, we reduce the latency of the first waiter by avoiding - * a context switch, but incur additional coherent seqno reads when - * following the chain of request breadcrumbs. Since it is most likely - * that we have a single client waiting on each seqno, then reducing - * the overhead of waking that client is much preferred. - */ - struct intel_breadcrumbs { - spinlock_t irq_lock; - struct list_head signalers; - - struct list_head signaled_requests; - - struct irq_work irq_work; /* for use from inside irq_lock */ - - unsigned int irq_enabled; - - bool irq_armed; - } breadcrumbs; + /* Keep track of all the seqno used, a trail of breadcrumbs */ + struct intel_breadcrumbs *breadcrumbs; struct intel_engine_pmu { /** diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index b05da68e52f4e..257063a57101b 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -8,6 +8,7 @@ #include "i915_drv.h" #include "i915_irq.h" +#include "intel_breadcrumbs.h" #include "intel_gt.h" #include "intel_gt_irq.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e5a37d14bce80..801ebe1326f39 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -137,6 +137,7 @@ #include "i915_perf.h" #include "i915_trace.h" #include "i915_vgpu.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine_pm.h" #include "intel_gt.h" @@ -4112,7 +4113,7 @@ static int execlists_resume(struct intel_engine_cs *engine) { intel_mocs_init_engine(engine); - intel_engine_reset_breadcrumbs(engine); + intel_breadcrumbs_reset(engine->breadcrumbs); if (GEM_SHOW_DEBUG() && unexpected_starting_state(engine)) { struct drm_printer p = drm_debug_printer(__func__); @@ -5714,9 +5715,7 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings, snprintf(ve->base.name, sizeof(ve->base.name), "virtual"); intel_engine_init_active(&ve->base, ENGINE_VIRTUAL); - intel_engine_init_breadcrumbs(&ve->base); intel_engine_init_execlists(&ve->base); - ve->base.breadcrumbs.irq_armed = true; /* fake HW, used for irq_work */ ve->base.cops = &virtual_context_ops; ve->base.request_alloc = execlists_request_alloc; @@ -5733,6 +5732,12 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings, intel_context_init(&ve->context, &ve->base); + ve->base.breadcrumbs = intel_breadcrumbs_create(NULL); + if (!ve->base.breadcrumbs) { + err = -ENOMEM; + goto err_put; + } + for (n = 0; n < count; n++) { struct intel_engine_cs *sibling = siblings[n]; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 46a5ceffc22f7..ac36b67fb46be 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -15,6 +15,7 @@ #include "i915_drv.h" #include "i915_gpu_error.h" #include "i915_irq.h" +#include "intel_breadcrumbs.h" #include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_gt_pm.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 87cef6d011418..84da20f6515cf 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -32,6 +32,7 @@ #include "gen6_ppgtt.h" #include "gen7_renderclear.h" #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_gt.h" #include "intel_reset.h" @@ -255,7 +256,7 @@ static int xcs_resume(struct intel_engine_cs *engine) else ring_setup_status_page(engine); - intel_engine_reset_breadcrumbs(engine); + intel_breadcrumbs_reset(engine->breadcrumbs); /* Enforce ordering by reading HEAD register back */ ENGINE_POSTING_READ(engine, RING_HEAD); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 97ba14ad52e4b..e6a00eea06316 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -7,6 +7,7 @@ #include <drm/i915_drm.h> #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_irq.h" diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 027de53cd05b8..79764305b8ec0 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -260,11 +260,12 @@ static void mock_engine_release(struct intel_engine_cs *engine) GEM_BUG_ON(timer_pending(&mock->hw_delay)); + intel_breadcrumbs_free(engine->breadcrumbs); + intel_context_unpin(engine->kernel_context); intel_context_put(engine->kernel_context); intel_engine_fini_retire(engine); - intel_engine_fini_breadcrumbs(engine); } struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, @@ -322,11 +323,14 @@ int mock_engine_init(struct intel_engine_cs *engine) struct intel_context *ce; intel_engine_init_active(engine, ENGINE_MOCK); - intel_engine_init_breadcrumbs(engine); intel_engine_init_execlists(engine); intel_engine_init__pm(engine); intel_engine_init_retire(engine); + engine->breadcrumbs = intel_breadcrumbs_create(NULL); + if (!engine->breadcrumbs) + return -ENOMEM; + ce = create_kernel_context(engine); if (IS_ERR(ce)) goto err_breadcrumbs; @@ -338,7 +342,7 @@ int mock_engine_init(struct intel_engine_cs *engine) return 0; err_breadcrumbs: - intel_engine_fini_breadcrumbs(engine); + intel_breadcrumbs_free(engine->breadcrumbs); return -ENOMEM; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1fa67700d8f49..f113fe44572b5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -41,6 +41,7 @@ #include "display/intel_lpe_audio.h" #include "display/intel_psr.h" +#include "gt/intel_breadcrumbs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_irq.h" #include "gt/intel_gt_pm_irq.h" diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index e9d5ce247ae98..fcb00b283b4f6 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -31,6 +31,7 @@ #include <linux/sched/signal.h> #include "gem/i915_gem_context.h" +#include "gt/intel_breadcrumbs.h" #include "gt/intel_context.h" #include "gt/intel_ring.h" #include "gt/intel_rps.h" diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index fc18378c685d8..16b721080195f 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -361,10 +361,6 @@ void i915_request_submit(struct i915_request *request); void __i915_request_unsubmit(struct i915_request *request); void i915_request_unsubmit(struct i915_request *request); -/* Note: part of the intel_breadcrumbs family */ -bool i915_request_enable_breadcrumb(struct i915_request *request); -void i915_request_cancel_breadcrumb(struct i915_request *request); - long i915_request_wait(struct i915_request *rq, unsigned int flags, long timeout) -- GitLab From cd0452aa2a0d146ff2c695877a4f5d3e4d09b435 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 17:42:17 +0100 Subject: [PATCH 0815/1494] drm/i915: Preallocate stashes for vma page-directories We need to make the DMA allocations used for page directories to be performed up front so that we can include those allocations in our memory reservation pass. The downside is that we have to assume the worst case, even before we know the final layout, and always allocate enough page directories for this object, even when there will be overlap. This unfortunately can be quite expensive, especially as we have to clear/reset the page directories and DMA pages, but it should only be required during early phases of a workload when new objects are being discovered, or after memory/eviction pressure when we need to rebind. Once we reach steady state, the objects should not be moved and we no longer need to preallocating the pages tables. It should be noted that the lifetime for the page directories DMA is more or less decoupled from individual fences as they will be shared across objects across timelines. v2: Only allocate enough PD space for the PTE we may use, we do not need to allocate PD that will be left as scratch. v3: Store the shift unto the first PD level to encapsulate the different PTE counts for gen6/gen8. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_client_blt.c | 11 +-- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 40 ++++----- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 78 +++++------------ drivers/gpu/drm/i915/gt/intel_ggtt.c | 60 ++++++-------- drivers/gpu/drm/i915/gt/intel_gtt.h | 46 ++++++---- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 83 ++++++++++++++++--- drivers/gpu/drm/i915/i915_vma.c | 27 +++--- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 60 ++++++++------ drivers/gpu/drm/i915/selftests/mock_gtt.c | 22 ++--- 9 files changed, 237 insertions(+), 190 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index 278664f831e78..947c8aa8e13ed 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -32,12 +32,13 @@ static void vma_clear_pages(struct i915_vma *vma) vma->pages = NULL; } -static int vma_bind(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void vma_bind(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { - return vm->vma_ops.bind_vma(vm, vma, cache_level, flags); + vm->vma_ops.bind_vma(vm, stash, vma, cache_level, flags); } static void vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index cdc0b9c54305b..4e6c1f7f48ef7 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -177,16 +177,16 @@ static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end) mutex_unlock(&ppgtt->flush); } -static int gen6_alloc_va_range(struct i915_address_space *vm, - u64 start, u64 length) +static void gen6_alloc_va_range(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length) { struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_table *pt, *alloc = NULL; + struct i915_page_table *pt; bool flush = false; u64 from = start; unsigned int pde; - int ret = 0; spin_lock(&pd->lock); gen6_for_each_pde(pt, pd, start, length, pde) { @@ -195,21 +195,17 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, if (px_base(pt) == px_base(&vm->scratch[1])) { spin_unlock(&pd->lock); - pt = fetch_and_zero(&alloc); - if (!pt) - pt = alloc_pt(vm); - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto unwind_out; - } + pt = stash->pt[0]; + GEM_BUG_ON(!pt); fill32_px(pt, vm->scratch[0].encode); spin_lock(&pd->lock); if (pd->entry[pde] == &vm->scratch[1]) { + stash->pt[0] = pt->stash; + atomic_set(&pt->used, 0); pd->entry[pde] = pt; } else { - alloc = pt; pt = pd->entry[pde]; } @@ -226,15 +222,6 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, with_intel_runtime_pm(&vm->i915->runtime_pm, wakeref) gen6_flush_pd(ppgtt, from, start); } - - goto out; - -unwind_out: - gen6_ppgtt_clear_range(vm, from, start - from); -out: - if (alloc) - free_px(vm, alloc); - return ret; } static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) @@ -302,10 +289,11 @@ static void pd_vma_clear_pages(struct i915_vma *vma) vma->pages = NULL; } -static int pd_vma_bind(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 unused) +static void pd_vma_bind(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 unused) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); struct gen6_ppgtt *ppgtt = vma->private; @@ -315,7 +303,6 @@ static int pd_vma_bind(struct i915_address_space *vm, ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total); - return 0; } static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) @@ -448,6 +435,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) mutex_init(&ppgtt->pin_mutex); ppgtt_init(&ppgtt->base, gt); + ppgtt->base.vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen6_pte_t)); ppgtt->base.vm.top = 1; ppgtt->base.vm.bind_async_flags = I915_VMA_LOCAL_BIND; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index 6991259282720..08cb65bfb3137 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -269,14 +269,12 @@ static void gen8_ppgtt_clear(struct i915_address_space *vm, start, start + length, vm->top); } -static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, - struct i915_page_directory * const pd, - u64 * const start, const u64 end, int lvl) +static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, + struct i915_vm_pt_stash *stash, + struct i915_page_directory * const pd, + u64 * const start, const u64 end, int lvl) { - const struct i915_page_scratch * const scratch = &vm->scratch[lvl]; - struct i915_page_table *alloc = NULL; unsigned int idx, len; - int ret = 0; GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT); @@ -297,49 +295,30 @@ static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, DBG("%s(%p):{ lvl:%d, idx:%d } allocating new tree\n", __func__, vm, lvl + 1, idx); - pt = fetch_and_zero(&alloc); - if (lvl) { - if (!pt) { - pt = &alloc_pd(vm)->pt; - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto out; - } - } + pt = stash->pt[!!lvl]; + GEM_BUG_ON(!pt); + if (lvl || + gen8_pt_count(*start, end) < I915_PDES || + intel_vgpu_active(vm->i915)) fill_px(pt, vm->scratch[lvl].encode); - } else { - if (!pt) { - pt = alloc_pt(vm); - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto out; - } - } - - if (intel_vgpu_active(vm->i915) || - gen8_pt_count(*start, end) < I915_PDES) - fill_px(pt, vm->scratch[lvl].encode); - } spin_lock(&pd->lock); - if (likely(!pd->entry[idx])) + if (likely(!pd->entry[idx])) { + stash->pt[!!lvl] = pt->stash; + atomic_set(&pt->used, 0); set_pd_entry(pd, idx, pt); - else - alloc = pt, pt = pd->entry[idx]; + } else { + pt = pd->entry[idx]; + } } if (lvl) { atomic_inc(&pt->used); spin_unlock(&pd->lock); - ret = __gen8_ppgtt_alloc(vm, as_pd(pt), - start, end, lvl); - if (unlikely(ret)) { - if (release_pd_entry(pd, idx, pt, scratch)) - free_px(vm, pt); - goto out; - } + __gen8_ppgtt_alloc(vm, stash, + as_pd(pt), start, end, lvl); spin_lock(&pd->lock); atomic_dec(&pt->used); @@ -359,18 +338,12 @@ static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, } } while (idx++, --len); spin_unlock(&pd->lock); -out: - if (alloc) - free_px(vm, alloc); - return ret; } -static int gen8_ppgtt_alloc(struct i915_address_space *vm, - u64 start, u64 length) +static void gen8_ppgtt_alloc(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length) { - u64 from; - int err; - GEM_BUG_ON(!IS_ALIGNED(start, BIT_ULL(GEN8_PTE_SHIFT))); GEM_BUG_ON(!IS_ALIGNED(length, BIT_ULL(GEN8_PTE_SHIFT))); GEM_BUG_ON(range_overflows(start, length, vm->total)); @@ -378,15 +351,9 @@ static int gen8_ppgtt_alloc(struct i915_address_space *vm, start >>= GEN8_PTE_SHIFT; length >>= GEN8_PTE_SHIFT; GEM_BUG_ON(length == 0); - from = start; - - err = __gen8_ppgtt_alloc(vm, i915_vm_to_ppgtt(vm)->pd, - &start, start + length, vm->top); - if (unlikely(err && from != start)) - __gen8_ppgtt_clear(vm, i915_vm_to_ppgtt(vm)->pd, - from, start, vm->top); - return err; + __gen8_ppgtt_alloc(vm, stash, i915_vm_to_ppgtt(vm)->pd, + &start, start + length, vm->top); } static __always_inline void @@ -703,6 +670,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt) ppgtt_init(ppgtt, gt); ppgtt->vm.top = i915_vm_is_4lvl(&ppgtt->vm) ? 3 : 2; + ppgtt->vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen8_pte_t)); /* * From bdw, there is hw support for read-only pages in the PPGTT. diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 62979ea591f05..5a33056ab9767 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -436,16 +436,17 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm, intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT); } -static int ggtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void ggtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { struct drm_i915_gem_object *obj = vma->obj; u32 pte_flags; if (i915_vma_is_bound(vma, ~flags & I915_VMA_BIND_MASK)) - return 0; + return; /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ pte_flags = 0; @@ -454,8 +455,6 @@ static int ggtt_bind_vma(struct i915_address_space *vm, vm->insert_entries(vm, vma, cache_level, pte_flags); vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; - - return 0; } static void ggtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) @@ -568,31 +567,25 @@ static int init_ggtt(struct i915_ggtt *ggtt) return ret; } -static int aliasing_gtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void aliasing_gtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { u32 pte_flags; - int ret; /* Currently applicable only to VLV */ pte_flags = 0; if (i915_gem_object_is_readonly(vma->obj)) pte_flags |= PTE_READ_ONLY; - if (flags & I915_VMA_LOCAL_BIND) { - struct i915_ppgtt *alias = i915_vm_to_ggtt(vm)->alias; - - ret = ppgtt_bind_vma(&alias->vm, vma, cache_level, flags); - if (ret) - return ret; - } + if (flags & I915_VMA_LOCAL_BIND) + ppgtt_bind_vma(&i915_vm_to_ggtt(vm)->alias->vm, + stash, vma, cache_level, flags); if (flags & I915_VMA_GLOBAL_BIND) vm->insert_entries(vm, vma, cache_level, pte_flags); - - return 0; } static void aliasing_gtt_unbind_vma(struct i915_address_space *vm, @@ -607,6 +600,7 @@ static void aliasing_gtt_unbind_vma(struct i915_address_space *vm, static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) { + struct i915_vm_pt_stash stash = {}; struct i915_ppgtt *ppgtt; int err; @@ -619,15 +613,17 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) goto err_ppgtt; } + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, ggtt->vm.total); + if (err) + goto err_ppgtt; + /* * Note we only pre-allocate as far as the end of the global * GTT. On 48b / 4-level page-tables, the difference is very, * very significant! We have to preallocate as GVT/vgpu does * not like the page directory disappearing. */ - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, 0, ggtt->vm.total); - if (err) - goto err_ppgtt; + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, ggtt->vm.total); ggtt->alias = ppgtt; ggtt->vm.bind_async_flags |= ppgtt->vm.bind_async_flags; @@ -638,6 +634,7 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) GEM_BUG_ON(ggtt->vm.vma_ops.unbind_vma != ggtt_unbind_vma); ggtt->vm.vma_ops.unbind_vma = aliasing_gtt_unbind_vma; + i915_vm_free_pt_stash(&ppgtt->vm, &stash); return 0; err_ppgtt: @@ -1165,11 +1162,6 @@ void i915_ggtt_disable_guc(struct i915_ggtt *ggtt) ggtt->invalidate(ggtt); } -static unsigned int clear_bind(struct i915_vma *vma) -{ - return atomic_fetch_and(~I915_VMA_BIND_MASK, &vma->flags); -} - void i915_ggtt_resume(struct i915_ggtt *ggtt) { struct i915_vma *vma; @@ -1187,11 +1179,13 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt) /* clflush objects bound into the GGTT and rebind them. */ list_for_each_entry(vma, &ggtt->vm.bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; - unsigned int was_bound = clear_bind(vma); + unsigned int was_bound = + atomic_read(&vma->flags) & I915_VMA_BIND_MASK; - WARN_ON(i915_vma_bind(vma, - obj ? obj->cache_level : 0, - was_bound, NULL)); + GEM_BUG_ON(!was_bound); + vma->ops->bind_vma(&ggtt->vm, NULL, vma, + obj ? obj->cache_level : 0, + was_bound); if (obj) { /* only used during resume => exclusive access */ flush |= fetch_and_zero(&obj->write_domain); obj->read_domains |= I915_GEM_DOMAIN_GTT; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index f2b75078e05fa..0d9f29aea6b49 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -159,7 +159,10 @@ struct i915_page_scratch { struct i915_page_table { struct i915_page_dma base; - atomic_t used; + union { + atomic_t used; + struct i915_page_table *stash; + }; }; struct i915_page_directory { @@ -196,12 +199,18 @@ struct drm_i915_gem_object; struct i915_vma; struct intel_gt; +struct i915_vm_pt_stash { + /* preallocated chains of page tables/directories */ + struct i915_page_table *pt[2]; +}; + struct i915_vma_ops { /* Map an object into an address space with the given cache flags. */ - int (*bind_vma)(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); + void (*bind_vma)(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); /* * Unmap an object from an address space. This usually consists of * setting the valid PTE entries to a reserved scratch page. @@ -257,9 +266,6 @@ struct i915_address_space { #define VM_CLASS_PPGTT 1 struct i915_page_scratch scratch[4]; - unsigned int scratch_order; - unsigned int top; - /** * List of vma currently bound. */ @@ -276,13 +282,18 @@ struct i915_address_space { /* Some systems support read-only mappings for GGTT and/or PPGTT */ bool has_read_only:1; + u8 top; + u8 pd_shift; + u8 scratch_order; + u64 (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, u32 flags); /* Create a valid PTE */ #define PTE_READ_ONLY BIT(0) - int (*allocate_va_range)(struct i915_address_space *vm, - u64 start, u64 length); + void (*allocate_va_range)(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length); void (*clear_range)(struct i915_address_space *vm, u64 start, u64 length); void (*insert_page)(struct i915_address_space *vm, @@ -568,10 +579,11 @@ int ggtt_set_pages(struct i915_vma *vma); int ppgtt_set_pages(struct i915_vma *vma); void clear_pages(struct i915_vma *vma); -int ppgtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); +void ppgtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma); @@ -579,6 +591,12 @@ void gtt_write_workarounds(struct intel_gt *gt); void setup_private_pat(struct intel_uncore *uncore); +int i915_vm_alloc_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 size); +void i915_vm_free_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash); + static inline struct sgt_dma { struct scatterlist *sg; dma_addr_t dma, max; diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index f0862e924d11a..09056544bc293 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -155,19 +155,16 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt) return ppgtt; } -int ppgtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +void ppgtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { u32 pte_flags; - int err; if (!test_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma))) { - err = vm->allocate_va_range(vm, vma->node.start, vma->size); - if (err) - return err; - + vm->allocate_va_range(vm, stash, vma->node.start, vma->size); set_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma)); } @@ -178,8 +175,6 @@ int ppgtt_bind_vma(struct i915_address_space *vm, vm->insert_entries(vm, vma, cache_level, pte_flags); wmb(); - - return 0; } void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) @@ -188,12 +183,76 @@ void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) vm->clear_range(vm, vma->node.start, vma->size); } +static unsigned long pd_count(u64 size, int shift) +{ + /* Beware later misalignment */ + return (size + 2 * (BIT_ULL(shift) - 1)) >> shift; +} + +int i915_vm_alloc_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 size) +{ + unsigned long count; + int shift, n; + + shift = vm->pd_shift; + if (!shift) + return 0; + + count = pd_count(size, shift); + while (count--) { + struct i915_page_table *pt; + + pt = alloc_pt(vm); + if (IS_ERR(pt)) { + i915_vm_free_pt_stash(vm, stash); + return PTR_ERR(pt); + } + + pt->stash = stash->pt[0]; + stash->pt[0] = pt; + } + + for (n = 1; n < vm->top; n++) { + shift += ilog2(I915_PDES); /* Each PD holds 512 entries */ + count = pd_count(size, shift); + while (count--) { + struct i915_page_directory *pd; + + pd = alloc_pd(vm); + if (IS_ERR(pd)) { + i915_vm_free_pt_stash(vm, stash); + return PTR_ERR(pd); + } + + pd->pt.stash = stash->pt[1]; + stash->pt[1] = &pd->pt; + } + } + + return 0; +} + +void i915_vm_free_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash) +{ + struct i915_page_table *pt; + int n; + + for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { + while ((pt = stash->pt[n])) { + stash->pt[n] = pt->stash; + free_px(vm, pt); + } + } +} + int ppgtt_set_pages(struct i915_vma *vma) { GEM_BUG_ON(vma->pages); vma->pages = vma->obj->mm.pages; - vma->page_sizes = vma->obj->mm.page_sizes; return 0; diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index cd12047c77911..a9e79b67035e0 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -291,6 +291,8 @@ i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_vma_work { struct dma_fence_work base; + struct i915_address_space *vm; + struct i915_vm_pt_stash stash; struct i915_vma *vma; struct drm_i915_gem_object *pinned; struct i915_sw_dma_fence_cb cb; @@ -302,13 +304,10 @@ static int __vma_bind(struct dma_fence_work *work) { struct i915_vma_work *vw = container_of(work, typeof(*vw), base); struct i915_vma *vma = vw->vma; - int err; - - err = vma->ops->bind_vma(vma->vm, vma, vw->cache_level, vw->flags); - if (err) - atomic_or(I915_VMA_ERROR, &vma->flags); - return err; + vma->ops->bind_vma(vw->vm, &vw->stash, + vma, vw->cache_level, vw->flags); + return 0; } static void __vma_release(struct dma_fence_work *work) @@ -317,6 +316,9 @@ static void __vma_release(struct dma_fence_work *work) if (vw->pinned) __i915_gem_object_unpin_pages(vw->pinned); + + i915_vm_free_pt_stash(vw->vm, &vw->stash); + i915_vm_put(vw->vm); } static const struct dma_fence_work_ops bind_ops = { @@ -376,7 +378,6 @@ int i915_vma_bind(struct i915_vma *vma, { u32 bind_flags; u32 vma_flags; - int ret; GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(vma->size > vma->node.size); @@ -433,9 +434,7 @@ int i915_vma_bind(struct i915_vma *vma, work->pinned = vma->obj; } } else { - ret = vma->ops->bind_vma(vma->vm, vma, cache_level, bind_flags); - if (ret) - return ret; + vma->ops->bind_vma(vma->vm, NULL, vma, cache_level, bind_flags); } atomic_or(bind_flags, &vma->flags); @@ -879,6 +878,14 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) err = -ENOMEM; goto err_pages; } + + work->vm = i915_vm_get(vma->vm); + + /* Allocate enough page directories to used PTE */ + if (vma->vm->allocate_va_range) + i915_vm_alloc_pt_stash(vma->vm, + &work->stash, + vma->size); } if (flags & PIN_GLOBAL) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 0016ffc7d9147..9b8fc990e9efc 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -172,35 +172,33 @@ static int igt_ppgtt_alloc(void *arg) /* Check we can allocate the entire range */ for (size = 4096; size <= limit; size <<= 2) { - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, 0, size); - if (err) { - if (err == -ENOMEM) { - pr_info("[1] Ran out of memory for va_range [0 + %llx] [bit %d]\n", - size, ilog2(size)); - err = 0; /* virtual space too large! */ - } + struct i915_vm_pt_stash stash = {}; + + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, size); + if (err) goto err_ppgtt_cleanup; - } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, size); cond_resched(); ppgtt->vm.clear_range(&ppgtt->vm, 0, size); + + i915_vm_free_pt_stash(&ppgtt->vm, &stash); } /* Check we can incrementally allocate the entire range */ for (last = 0, size = 4096; size <= limit; last = size, size <<= 2) { - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, - last, size - last); - if (err) { - if (err == -ENOMEM) { - pr_info("[2] Ran out of memory for va_range [%llx + %llx] [bit %d]\n", - last, size - last, ilog2(size)); - err = 0; /* virtual space too large! */ - } + struct i915_vm_pt_stash stash = {}; + + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, size - last); + if (err) goto err_ppgtt_cleanup; - } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, + last, size - last); cond_resched(); + + i915_vm_free_pt_stash(&ppgtt->vm, &stash); } err_ppgtt_cleanup: @@ -284,9 +282,18 @@ static int lowlevel_hole(struct i915_address_space *vm, break; } - if (vm->allocate_va_range && - vm->allocate_va_range(vm, addr, BIT_ULL(size))) - break; + if (vm->allocate_va_range) { + struct i915_vm_pt_stash stash = {}; + + if (i915_vm_alloc_pt_stash(vm, &stash, + BIT_ULL(size))) + break; + + vm->allocate_va_range(vm, &stash, + addr, BIT_ULL(size)); + + i915_vm_free_pt_stash(vm, &stash); + } mock_vma->pages = obj->mm.pages; mock_vma->node.size = BIT_ULL(size); @@ -1881,6 +1888,7 @@ static int igt_cs_tlb(void *arg) continue; while (!__igt_timeout(end_time, NULL)) { + struct i915_vm_pt_stash stash = {}; struct i915_request *rq; u64 offset; @@ -1888,10 +1896,6 @@ static int igt_cs_tlb(void *arg) 0, vm->total - PAGE_SIZE, chunk_size, PAGE_SIZE); - err = vm->allocate_va_range(vm, offset, chunk_size); - if (err) - goto end; - memset32(result, STACK_MAGIC, PAGE_SIZE / sizeof(u32)); vma = i915_vma_instance(bbe, vm, NULL); @@ -1904,6 +1908,14 @@ static int igt_cs_tlb(void *arg) if (err) goto end; + err = i915_vm_alloc_pt_stash(vm, &stash, chunk_size); + if (err) + goto end; + + vm->allocate_va_range(vm, &stash, offset, chunk_size); + + i915_vm_free_pt_stash(vm, &stash); + /* Prime the TLB with the dummy pages */ for (i = 0; i < count; i++) { vma->node.start = offset + i * PAGE_SIZE; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index b173086411ef5..5e4fb0fba34bc 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -38,14 +38,14 @@ static void mock_insert_entries(struct i915_address_space *vm, { } -static int mock_bind_ppgtt(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void mock_bind_ppgtt(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { GEM_BUG_ON(flags & I915_VMA_GLOBAL_BIND); set_bit(I915_VMA_LOCAL_BIND_BIT, __i915_vma_flags(vma)); - return 0; } static void mock_unbind_ppgtt(struct i915_address_space *vm, @@ -74,6 +74,7 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) ppgtt->vm.i915 = i915; ppgtt->vm.total = round_down(U64_MAX, PAGE_SIZE); ppgtt->vm.file = ERR_PTR(-ENODEV); + ppgtt->vm.dma = &i915->drm.pdev->dev; i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT); @@ -90,13 +91,12 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) return ppgtt; } -static int mock_bind_ggtt(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void mock_bind_ggtt(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { - atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags); - return 0; } static void mock_unbind_ggtt(struct i915_address_space *vm, -- GitLab From 89351925a477441ae5fdd0136aec80b49ea1c53c Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 17:42:18 +0100 Subject: [PATCH 0816/1494] drm/i915/gt: Switch to object allocations for page directories The GEM object is grossly overweight for the practicality of tracking large numbers of individual pages, yet it is currently our only abstraction for tracking DMA allocations. Since those allocations need to be reserved upfront before an operation, and that we need to break away from simple system memory, we need to ditch using plain struct page wrappers. In the process, we drop the WC mapping as we ended up clflushing everything anyway due to various issues across a wider range of platforms. Though in a future step, we need to drop the kmap_atomic approach which suggests we need to pre-map all the pages and keep them mapped. v2: Verify our large scratch page is suitably DMA aligned; and manually clear the scratch since we are allocating plain struct pages full of prior content. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_object_types.h | 1 + .../gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../drm/i915/gem/selftests/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 53 ++-- drivers/gpu/drm/i915/gt/gen6_ppgtt.h | 1 + drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 89 +++--- drivers/gpu/drm/i915/gt/intel_ggtt.c | 37 ++- drivers/gpu/drm/i915/gt/intel_gtt.c | 300 ++++-------------- drivers/gpu/drm/i915/gt/intel_gtt.h | 94 ++---- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 42 ++- .../gpu/drm/i915/gt/intel_ring_submission.c | 16 +- drivers/gpu/drm/i915/gvt/scheduler.c | 17 +- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 5 - drivers/gpu/drm/i915/i915_vma.c | 18 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 23 ++ drivers/gpu/drm/i915/selftests/i915_perf.c | 4 +- drivers/gpu/drm/i915/selftests/mock_gtt.c | 4 + 18 files changed, 289 insertions(+), 420 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 5335f799b5482..d0847d7896f95 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -282,6 +282,7 @@ struct drm_i915_gem_object { } userptr; unsigned long scratch; + u64 encode; void *gvt_info; }; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 8291ede6902c4..e2f3d014acb24 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -393,7 +393,7 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) */ for (i = 1; i < BIT(ARRAY_SIZE(page_sizes)); i++) { - unsigned int combination = 0; + unsigned int combination = SZ_4K; /* Required for ppGTT */ for (j = 0; j < ARRAY_SIZE(page_sizes); j++) { if (i & BIT(j)) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 7ffc3c7514329..d176b015353fb 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1748,7 +1748,7 @@ static int check_scratch_page(struct i915_gem_context *ctx, u32 *out) if (!vm) return -ENODEV; - page = vm->scratch[0].base.page; + page = __px_page(vm->scratch[0]); if (!page) { pr_err("No scratch page!\n"); return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index 4e6c1f7f48ef7..fb702e1de7391 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -16,8 +16,10 @@ static inline void gen6_write_pde(const struct gen6_ppgtt *ppgtt, const unsigned int pde, const struct i915_page_table *pt) { + dma_addr_t addr = pt ? px_dma(pt) : px_dma(ppgtt->base.vm.scratch[1]); + /* Caller needs to make sure the write completes if necessary */ - iowrite32(GEN6_PDE_ADDR_ENCODE(px_dma(pt)) | GEN6_PDE_VALID, + iowrite32(GEN6_PDE_ADDR_ENCODE(addr) | GEN6_PDE_VALID, ppgtt->pd_addr + pde); } @@ -79,7 +81,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, { struct gen6_ppgtt * const ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); const unsigned int first_entry = start / I915_GTT_PAGE_SIZE; - const gen6_pte_t scratch_pte = vm->scratch[0].encode; + const gen6_pte_t scratch_pte = vm->scratch[0]->encode; unsigned int pde = first_entry / GEN6_PTES; unsigned int pte = first_entry % GEN6_PTES; unsigned int num_entries = length / I915_GTT_PAGE_SIZE; @@ -90,8 +92,6 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, const unsigned int count = min(num_entries, GEN6_PTES - pte); gen6_pte_t *vaddr; - GEM_BUG_ON(px_base(pt) == px_base(&vm->scratch[1])); - num_entries -= count; GEM_BUG_ON(count > atomic_read(&pt->used)); @@ -127,7 +127,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, struct sgt_dma iter = sgt_dma(vma); gen6_pte_t *vaddr; - GEM_BUG_ON(pd->entry[act_pt] == &vm->scratch[1]); + GEM_BUG_ON(!pd->entry[act_pt]); vaddr = kmap_atomic_px(i915_pt_entry(pd, act_pt)); do { @@ -192,16 +192,17 @@ static void gen6_alloc_va_range(struct i915_address_space *vm, gen6_for_each_pde(pt, pd, start, length, pde) { const unsigned int count = gen6_pte_count(start, length); - if (px_base(pt) == px_base(&vm->scratch[1])) { + if (!pt) { spin_unlock(&pd->lock); pt = stash->pt[0]; - GEM_BUG_ON(!pt); + __i915_gem_object_pin_pages(pt->base); + i915_gem_object_make_unshrinkable(pt->base); - fill32_px(pt, vm->scratch[0].encode); + fill32_px(pt, vm->scratch[0]->encode); spin_lock(&pd->lock); - if (pd->entry[pde] == &vm->scratch[1]) { + if (!pd->entry[pde]) { stash->pt[0] = pt->stash; atomic_set(&pt->used, 0); pd->entry[pde] = pt; @@ -227,24 +228,27 @@ static void gen6_alloc_va_range(struct i915_address_space *vm, static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) { struct i915_address_space * const vm = &ppgtt->base.vm; - struct i915_page_directory * const pd = ppgtt->base.pd; int ret; - ret = setup_scratch_page(vm, __GFP_HIGHMEM); + ret = setup_scratch_page(vm); if (ret) return ret; - vm->scratch[0].encode = - vm->pte_encode(px_dma(&vm->scratch[0]), + vm->scratch[0]->encode = + vm->pte_encode(px_dma(vm->scratch[0]), I915_CACHE_NONE, PTE_READ_ONLY); - if (unlikely(setup_page_dma(vm, px_base(&vm->scratch[1])))) { - cleanup_scratch_page(vm); - return -ENOMEM; + vm->scratch[1] = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(vm->scratch[1])) + return PTR_ERR(vm->scratch[1]); + + ret = pin_pt_dma(vm, vm->scratch[1]); + if (ret) { + i915_gem_object_put(vm->scratch[1]); + return ret; } - fill32_px(&vm->scratch[1], vm->scratch[0].encode); - memset_p(pd->entry, &vm->scratch[1], I915_PDES); + fill32_px(vm->scratch[1], vm->scratch[0]->encode); return 0; } @@ -252,13 +256,11 @@ static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt) { struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_dma * const scratch = - px_base(&ppgtt->base.vm.scratch[1]); struct i915_page_table *pt; u32 pde; gen6_for_all_pdes(pt, pd, pde) - if (px_base(pt) != scratch) + if (pt) free_px(&ppgtt->base.vm, pt); } @@ -299,7 +301,7 @@ static void pd_vma_bind(struct i915_address_space *vm, struct gen6_ppgtt *ppgtt = vma->private; u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE; - px_base(ppgtt->base.pd)->ggtt_offset = ggtt_offset * sizeof(gen6_pte_t); + ppgtt->pp_dir = ggtt_offset * sizeof(gen6_pte_t) << 10; ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total); @@ -309,8 +311,6 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) { struct gen6_ppgtt *ppgtt = vma->private; struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_dma * const scratch = - px_base(&ppgtt->base.vm.scratch[1]); struct i915_page_table *pt; unsigned int pde; @@ -319,11 +319,11 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) /* Free all no longer used page tables */ gen6_for_all_pdes(pt, ppgtt->base.pd, pde) { - if (px_base(pt) == scratch || atomic_read(&pt->used)) + if (!pt || atomic_read(&pt->used)) continue; free_px(&ppgtt->base.vm, pt); - pd->entry[pde] = scratch; + pd->entry[pde] = NULL; } ppgtt->scan_for_unused_pt = false; @@ -444,6 +444,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) ppgtt->base.vm.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.vm.cleanup = gen6_ppgtt_cleanup; + ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma; ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode; ppgtt->base.pd = __alloc_pd(sizeof(*ppgtt->base.pd)); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h index 72e481806c962..7249672e5802d 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h @@ -14,6 +14,7 @@ struct gen6_ppgtt { struct mutex flush; struct i915_vma *vma; gen6_pte_t __iomem *pd_addr; + u32 pp_dir; atomic_t pin_count; struct mutex pin_mutex; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index 08cb65bfb3137..a40cb7ea8c666 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -199,7 +199,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, struct i915_page_directory * const pd, u64 start, const u64 end, int lvl) { - const struct i915_page_scratch * const scratch = &vm->scratch[lvl]; + const struct drm_i915_gem_object * const scratch = vm->scratch[lvl]; unsigned int idx, len; GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT); @@ -239,7 +239,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, vaddr = kmap_atomic_px(pt); memset64(vaddr + gen8_pd_index(start, 0), - vm->scratch[0].encode, + vm->scratch[0]->encode, count); kunmap_atomic(vaddr); @@ -296,12 +296,13 @@ static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, __func__, vm, lvl + 1, idx); pt = stash->pt[!!lvl]; - GEM_BUG_ON(!pt); + __i915_gem_object_pin_pages(pt->base); + i915_gem_object_make_unshrinkable(pt->base); if (lvl || gen8_pt_count(*start, end) < I915_PDES || intel_vgpu_active(vm->i915)) - fill_px(pt, vm->scratch[lvl].encode); + fill_px(pt, vm->scratch[lvl]->encode); spin_lock(&pd->lock); if (likely(!pd->entry[idx])) { @@ -356,16 +357,6 @@ static void gen8_ppgtt_alloc(struct i915_address_space *vm, &start, start + length, vm->top); } -static __always_inline void -write_pte(gen8_pte_t *pte, const gen8_pte_t val) -{ - /* Magic delays? Or can we refine these to flush all in one pass? */ - *pte = val; - wmb(); /* cpu to cache */ - clflush(pte); /* cache to memory */ - wmb(); /* visible to all */ -} - static __always_inline u64 gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, struct i915_page_directory *pdp, @@ -382,8 +373,7 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1))); do { GEM_BUG_ON(iter->sg->length < I915_GTT_PAGE_SIZE); - write_pte(&vaddr[gen8_pd_index(idx, 0)], - pte_encode | iter->dma); + vaddr[gen8_pd_index(idx, 0)] = pte_encode | iter->dma; iter->dma += I915_GTT_PAGE_SIZE; if (iter->dma >= iter->max) { @@ -406,10 +396,12 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, pd = pdp->entry[gen8_pd_index(idx, 2)]; } + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1))); } } while (1); + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); return idx; @@ -465,7 +457,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, do { GEM_BUG_ON(iter->sg->length < page_size); - write_pte(&vaddr[index++], encode | iter->dma); + vaddr[index++] = encode | iter->dma; start += page_size; iter->dma += page_size; @@ -490,6 +482,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, } } while (rem >= page_size && index < I915_PDES); + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); /* @@ -521,7 +514,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) { u16 i; - encode = vma->vm->scratch[0].encode; + encode = vma->vm->scratch[0]->encode; vaddr = kmap_atomic_px(i915_pt_entry(pd, maybe_64K)); for (i = 1; i < index; i += 16) @@ -575,27 +568,37 @@ static int gen8_init_scratch(struct i915_address_space *vm) GEM_BUG_ON(!clone->has_read_only); vm->scratch_order = clone->scratch_order; - memcpy(vm->scratch, clone->scratch, sizeof(vm->scratch)); - px_dma(&vm->scratch[0]) = 0; /* no xfer of ownership */ + for (i = 0; i <= vm->top; i++) + vm->scratch[i] = i915_gem_object_get(clone->scratch[i]); + return 0; } - ret = setup_scratch_page(vm, __GFP_HIGHMEM); + ret = setup_scratch_page(vm); if (ret) return ret; - vm->scratch[0].encode = - gen8_pte_encode(px_dma(&vm->scratch[0]), + vm->scratch[0]->encode = + gen8_pte_encode(px_dma(vm->scratch[0]), I915_CACHE_LLC, vm->has_read_only); for (i = 1; i <= vm->top; i++) { - if (unlikely(setup_page_dma(vm, px_base(&vm->scratch[i])))) + struct drm_i915_gem_object *obj; + + obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(obj)) goto free_scratch; - fill_px(&vm->scratch[i], vm->scratch[i - 1].encode); - vm->scratch[i].encode = - gen8_pde_encode(px_dma(&vm->scratch[i]), - I915_CACHE_LLC); + ret = pin_pt_dma(vm, obj); + if (ret) { + i915_gem_object_put(obj); + goto free_scratch; + } + + fill_px(obj, vm->scratch[i - 1]->encode); + obj->encode = gen8_pde_encode(px_dma(obj), I915_CACHE_LLC); + + vm->scratch[i] = obj; } return 0; @@ -616,12 +619,20 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt) for (idx = 0; idx < GEN8_3LVL_PDPES; idx++) { struct i915_page_directory *pde; + int err; pde = alloc_pd(vm); if (IS_ERR(pde)) return PTR_ERR(pde); - fill_px(pde, vm->scratch[1].encode); + err = pin_pt_dma(vm, pde->pt.base); + if (err) { + i915_gem_object_put(pde->pt.base); + kfree(pde); + return err; + } + + fill_px(pde, vm->scratch[1]->encode); set_pd_entry(pd, idx, pde); atomic_inc(px_used(pde)); /* keep pinned */ } @@ -635,6 +646,7 @@ gen8_alloc_top_pd(struct i915_address_space *vm) { const unsigned int count = gen8_pd_top_count(vm); struct i915_page_directory *pd; + int err; GEM_BUG_ON(count > ARRAY_SIZE(pd->entry)); @@ -642,12 +654,20 @@ gen8_alloc_top_pd(struct i915_address_space *vm) if (unlikely(!pd)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, px_base(pd)))) { + pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pd->pt.base)) { kfree(pd); return ERR_PTR(-ENOMEM); } - fill_page_dma(px_base(pd), vm->scratch[vm->top].encode, count); + err = pin_pt_dma(vm, pd->pt.base); + if (err) { + i915_gem_object_put(pd->pt.base); + kfree(pd); + return ERR_PTR(err); + } + + fill_page_dma(px_base(pd), vm->scratch[vm->top]->encode, count); atomic_inc(px_used(pd)); /* mark as pinned */ return pd; } @@ -682,12 +702,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt) */ ppgtt->vm.has_read_only = !IS_GEN_RANGE(gt->i915, 11, 12); - /* - * There are only few exceptions for gen >=6. chv and bxt. - * And we are not sure about the latter so play safe for now. - */ - if (IS_CHERRYVIEW(gt->i915) || IS_BROXTON(gt->i915)) - ppgtt->vm.pt_kmap_wc = true; + ppgtt->vm.alloc_pt_dma = alloc_pt_dma; err = gen8_init_scratch(&ppgtt->vm); if (err) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 5a33056ab9767..33a3f627ddb1c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -78,8 +78,6 @@ int i915_ggtt_init_hw(struct drm_i915_private *i915) { int ret; - stash_init(&i915->mm.wc_stash); - /* * Note that we use page colouring to enforce a guard page at the * end of the address space. This is required as the CS may prefetch @@ -232,7 +230,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, /* Fill the allocated but "unused" space beyond the end of the buffer */ while (gte < end) - gen8_set_pte(gte++, vm->scratch[0].encode); + gen8_set_pte(gte++, vm->scratch[0]->encode); /* * We want to flush the TLBs only after we're certain all the PTE @@ -283,7 +281,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, /* Fill the allocated but "unused" space beyond the end of the buffer */ while (gte < end) - iowrite32(vm->scratch[0].encode, gte++); + iowrite32(vm->scratch[0]->encode, gte++); /* * We want to flush the TLBs only after we're certain all the PTE @@ -303,7 +301,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); unsigned int first_entry = start / I915_GTT_PAGE_SIZE; unsigned int num_entries = length / I915_GTT_PAGE_SIZE; - const gen8_pte_t scratch_pte = vm->scratch[0].encode; + const gen8_pte_t scratch_pte = vm->scratch[0]->encode; gen8_pte_t __iomem *gtt_base = (gen8_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; @@ -401,7 +399,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->scratch[0].encode; + scratch_pte = vm->scratch[0]->encode; for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); } @@ -617,6 +615,10 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) if (err) goto err_ppgtt; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) + goto err_stash; + /* * Note we only pre-allocate as far as the end of the global * GTT. On 48b / 4-level page-tables, the difference is very, @@ -637,6 +639,8 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) i915_vm_free_pt_stash(&ppgtt->vm, &stash); return 0; +err_stash: + i915_vm_free_pt_stash(&ppgtt->vm, &stash); err_ppgtt: i915_vm_put(&ppgtt->vm); return err; @@ -712,18 +716,11 @@ static void ggtt_cleanup_hw(struct i915_ggtt *ggtt) void i915_ggtt_driver_release(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = &i915->ggtt; - struct pagevec *pvec; fini_aliasing_ppgtt(ggtt); intel_ggtt_fini_fences(ggtt); ggtt_cleanup_hw(ggtt); - - pvec = &i915->mm.wc_stash.pvec; - if (pvec->nr) { - set_pages_array_wb(pvec->pages, pvec->nr); - __pagevec_release(pvec); - } } static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) @@ -786,7 +783,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return -ENOMEM; } - ret = setup_scratch_page(&ggtt->vm, GFP_DMA32); + ret = setup_scratch_page(&ggtt->vm); if (ret) { drm_err(&i915->drm, "Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ @@ -794,8 +791,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return ret; } - ggtt->vm.scratch[0].encode = - ggtt->vm.pte_encode(px_dma(&ggtt->vm.scratch[0]), + ggtt->vm.scratch[0]->encode = + ggtt->vm.pte_encode(px_dma(ggtt->vm.scratch[0]), I915_CACHE_NONE, 0); return 0; @@ -821,7 +818,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm) struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); iounmap(ggtt->gsm); - cleanup_scratch_page(vm); + free_scratch(vm); } static struct resource pci_resource(struct pci_dev *pdev, int bar) @@ -849,6 +846,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) else size = gen8_get_total_gtt_size(snb_gmch_ctl); + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.cleanup = gen6_gmch_remove; ggtt->vm.insert_page = gen8_ggtt_insert_page; @@ -997,6 +996,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) size = gen6_get_total_gtt_size(snb_gmch_ctl); ggtt->vm.total = (size / sizeof(gen6_pte_t)) * I915_GTT_PAGE_SIZE; + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.clear_range = nop_clear_range; if (!HAS_FULL_PPGTT(i915) || intel_scanout_needs_vtd_wa(i915)) ggtt->vm.clear_range = gen6_ggtt_clear_range; @@ -1047,6 +1048,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt) ggtt->gmadr = (struct resource)DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->do_idle_maps = needs_idle_maps(i915); ggtt->vm.insert_page = i915_ggtt_insert_page; ggtt->vm.insert_entries = i915_ggtt_insert_entries; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 2a72cce63fd91..3f1114b58b018 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -11,160 +11,24 @@ #include "intel_gt.h" #include "intel_gtt.h" -void stash_init(struct pagestash *stash) +struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz) { - pagevec_init(&stash->pvec); - spin_lock_init(&stash->lock); -} - -static struct page *stash_pop_page(struct pagestash *stash) -{ - struct page *page = NULL; - - spin_lock(&stash->lock); - if (likely(stash->pvec.nr)) - page = stash->pvec.pages[--stash->pvec.nr]; - spin_unlock(&stash->lock); - - return page; -} - -static void stash_push_pagevec(struct pagestash *stash, struct pagevec *pvec) -{ - unsigned int nr; - - spin_lock_nested(&stash->lock, SINGLE_DEPTH_NESTING); - - nr = min_t(typeof(nr), pvec->nr, pagevec_space(&stash->pvec)); - memcpy(stash->pvec.pages + stash->pvec.nr, - pvec->pages + pvec->nr - nr, - sizeof(pvec->pages[0]) * nr); - stash->pvec.nr += nr; - - spin_unlock(&stash->lock); - - pvec->nr -= nr; -} - -static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) -{ - struct pagevec stack; - struct page *page; - if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1))) i915_gem_shrink_all(vm->i915); - page = stash_pop_page(&vm->free_pages); - if (page) - return page; - - if (!vm->pt_kmap_wc) - return alloc_page(gfp); - - /* Look in our global stash of WC pages... */ - page = stash_pop_page(&vm->i915->mm.wc_stash); - if (page) - return page; - - /* - * Otherwise batch allocate pages to amortize cost of set_pages_wc. - * - * We have to be careful as page allocation may trigger the shrinker - * (via direct reclaim) which will fill up the WC stash underneath us. - * So we add our WB pages into a temporary pvec on the stack and merge - * them into the WC stash after all the allocations are complete. - */ - pagevec_init(&stack); - do { - struct page *page; - - page = alloc_page(gfp); - if (unlikely(!page)) - break; - - stack.pages[stack.nr++] = page; - } while (pagevec_space(&stack)); - - if (stack.nr && !set_pages_array_wc(stack.pages, stack.nr)) { - page = stack.pages[--stack.nr]; - - /* Merge spare WC pages to the global stash */ - if (stack.nr) - stash_push_pagevec(&vm->i915->mm.wc_stash, &stack); - - /* Push any surplus WC pages onto the local VM stash */ - if (stack.nr) - stash_push_pagevec(&vm->free_pages, &stack); - } - - /* Return unwanted leftovers */ - if (unlikely(stack.nr)) { - WARN_ON_ONCE(set_pages_array_wb(stack.pages, stack.nr)); - __pagevec_release(&stack); - } - - return page; + return i915_gem_object_create_internal(vm->i915, sz); } -static void vm_free_pages_release(struct i915_address_space *vm, - bool immediate) +int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj) { - struct pagevec *pvec = &vm->free_pages.pvec; - struct pagevec stack; - - lockdep_assert_held(&vm->free_pages.lock); - GEM_BUG_ON(!pagevec_count(pvec)); - - if (vm->pt_kmap_wc) { - /* - * When we use WC, first fill up the global stash and then - * only if full immediately free the overflow. - */ - stash_push_pagevec(&vm->i915->mm.wc_stash, pvec); - - /* - * As we have made some room in the VM's free_pages, - * we can wait for it to fill again. Unless we are - * inside i915_address_space_fini() and must - * immediately release the pages! - */ - if (pvec->nr <= (immediate ? 0 : PAGEVEC_SIZE - 1)) - return; + int err; - /* - * We have to drop the lock to allow ourselves to sleep, - * so take a copy of the pvec and clear the stash for - * others to use it as we sleep. - */ - stack = *pvec; - pagevec_reinit(pvec); - spin_unlock(&vm->free_pages.lock); - - pvec = &stack; - set_pages_array_wb(pvec->pages, pvec->nr); - - spin_lock(&vm->free_pages.lock); - } + err = i915_gem_object_pin_pages(obj); + if (err) + return err; - __pagevec_release(pvec); -} - -static void vm_free_page(struct i915_address_space *vm, struct page *page) -{ - /* - * On !llc, we need to change the pages back to WB. We only do so - * in bulk, so we rarely need to change the page attributes here, - * but doing so requires a stop_machine() from deep inside arch/x86/mm. - * To make detection of the possible sleep more likely, use an - * unconditional might_sleep() for everybody. - */ - might_sleep(); - spin_lock(&vm->free_pages.lock); - while (!pagevec_space(&vm->free_pages.pvec)) - vm_free_pages_release(vm, false); - GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec) >= PAGEVEC_SIZE); - pagevec_add(&vm->free_pages.pvec, page); - spin_unlock(&vm->free_pages.lock); + i915_gem_object_make_unshrinkable(obj); + return 0; } void __i915_vm_close(struct i915_address_space *vm) @@ -194,14 +58,7 @@ void __i915_vm_close(struct i915_address_space *vm) void i915_address_space_fini(struct i915_address_space *vm) { - spin_lock(&vm->free_pages.lock); - if (pagevec_count(&vm->free_pages.pvec)) - vm_free_pages_release(vm, true); - GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec)); - spin_unlock(&vm->free_pages.lock); - drm_mm_takedown(&vm->mm); - mutex_destroy(&vm->mutex); } @@ -246,8 +103,6 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass) drm_mm_init(&vm->mm, 0, vm->total); vm->mm.head_node.color = I915_COLOR_UNEVICTABLE; - stash_init(&vm->free_pages); - INIT_LIST_HEAD(&vm->bound_list); } @@ -264,64 +119,50 @@ void clear_pages(struct i915_vma *vma) memset(&vma->page_sizes, 0, sizeof(vma->page_sizes)); } -static int __setup_page_dma(struct i915_address_space *vm, - struct i915_page_dma *p, - gfp_t gfp) -{ - p->page = vm_alloc_page(vm, gfp | I915_GFP_ALLOW_FAIL); - if (unlikely(!p->page)) - return -ENOMEM; - - p->daddr = dma_map_page_attrs(vm->dma, - p->page, 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC | - DMA_ATTR_NO_WARN); - if (unlikely(dma_mapping_error(vm->dma, p->daddr))) { - vm_free_page(vm, p->page); - return -ENOMEM; - } - - return 0; -} - -int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p) +dma_addr_t __px_dma(struct drm_i915_gem_object *p) { - return __setup_page_dma(vm, p, __GFP_HIGHMEM); + GEM_BUG_ON(!i915_gem_object_has_pages(p)); + return sg_dma_address(p->mm.pages->sgl); } -void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p) +struct page *__px_page(struct drm_i915_gem_object *p) { - dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - vm_free_page(vm, p->page); + GEM_BUG_ON(!i915_gem_object_has_pages(p)); + return sg_page(p->mm.pages->sgl); } void -fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count) +fill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count) { - kunmap_atomic(memset64(kmap_atomic(p->page), val, count)); + struct page *page = __px_page(p); + void *vaddr; + + vaddr = kmap(page); + memset64(vaddr, val, count); + clflush_cache_range(vaddr, PAGE_SIZE); + kunmap(page); } -static void poison_scratch_page(struct page *page, unsigned long size) +static void poison_scratch_page(struct drm_i915_gem_object *scratch) { - if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) - return; + struct sgt_iter sgt; + struct page *page; + u8 val; - GEM_BUG_ON(!IS_ALIGNED(size, PAGE_SIZE)); + val = 0; + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) + val = POISON_FREE; - do { + for_each_sgt_page(page, sgt, scratch->mm.pages) { void *vaddr; vaddr = kmap(page); - memset(vaddr, POISON_FREE, PAGE_SIZE); + memset(vaddr, val, PAGE_SIZE); kunmap(page); - - page = pfn_to_page(page_to_pfn(page) + 1); - size -= PAGE_SIZE; - } while (size); + } } -int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) +int setup_scratch_page(struct i915_address_space *vm) { unsigned long size; @@ -338,21 +179,27 @@ int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) */ size = I915_GTT_PAGE_SIZE_4K; if (i915_vm_is_4lvl(vm) && - HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) { + HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) size = I915_GTT_PAGE_SIZE_64K; - gfp |= __GFP_NOWARN; - } - gfp |= __GFP_ZERO | __GFP_RETRY_MAYFAIL; do { - unsigned int order = get_order(size); - struct page *page; - dma_addr_t addr; + struct drm_i915_gem_object *obj; - page = alloc_pages(gfp, order); - if (unlikely(!page)) + obj = vm->alloc_pt_dma(vm, size); + if (IS_ERR(obj)) goto skip; + if (pin_pt_dma(vm, obj)) + goto skip_obj; + + /* We need a single contiguous page for our scratch */ + if (obj->mm.page_sizes.sg < size) + goto skip_obj; + + /* And it needs to be correspondingly aligned */ + if (__px_dma(obj) & (size - 1)) + goto skip_obj; + /* * Use a non-zero scratch page for debugging. * @@ -362,61 +209,28 @@ int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) * should it ever be accidentally used, the effect should be * fairly benign. */ - poison_scratch_page(page, size); - - addr = dma_map_page_attrs(vm->dma, - page, 0, size, - PCI_DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC | - DMA_ATTR_NO_WARN); - if (unlikely(dma_mapping_error(vm->dma, addr))) - goto free_page; - - if (unlikely(!IS_ALIGNED(addr, size))) - goto unmap_page; - - vm->scratch[0].base.page = page; - vm->scratch[0].base.daddr = addr; - vm->scratch_order = order; + poison_scratch_page(obj); + + vm->scratch[0] = obj; + vm->scratch_order = get_order(size); return 0; -unmap_page: - dma_unmap_page(vm->dma, addr, size, PCI_DMA_BIDIRECTIONAL); -free_page: - __free_pages(page, order); +skip_obj: + i915_gem_object_put(obj); skip: if (size == I915_GTT_PAGE_SIZE_4K) return -ENOMEM; size = I915_GTT_PAGE_SIZE_4K; - gfp &= ~__GFP_NOWARN; } while (1); } -void cleanup_scratch_page(struct i915_address_space *vm) -{ - struct i915_page_dma *p = px_base(&vm->scratch[0]); - unsigned int order = vm->scratch_order; - - dma_unmap_page(vm->dma, p->daddr, BIT(order) << PAGE_SHIFT, - PCI_DMA_BIDIRECTIONAL); - __free_pages(p->page, order); -} - void free_scratch(struct i915_address_space *vm) { int i; - if (!px_dma(&vm->scratch[0])) /* set to 0 on clones */ - return; - - for (i = 1; i <= vm->top; i++) { - if (!px_dma(&vm->scratch[i])) - break; - cleanup_page_dma(vm, px_base(&vm->scratch[i])); - } - - cleanup_scratch_page(vm); + for (i = 0; i <= vm->top; i++) + i915_gem_object_put(vm->scratch[i]); } void gtt_write_workarounds(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 0d9f29aea6b49..6abab2d37b6fe 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -134,31 +134,19 @@ typedef u64 gen8_pte_t; #define GEN8_PDE_IPS_64K BIT(11) #define GEN8_PDE_PS_2M BIT(7) +enum i915_cache_level; + +struct drm_i915_file_private; +struct drm_i915_gem_object; struct i915_fence_reg; +struct i915_vma; +struct intel_gt; #define for_each_sgt_daddr(__dp, __iter, __sgt) \ __for_each_sgt_daddr(__dp, __iter, __sgt, I915_GTT_PAGE_SIZE) -struct i915_page_dma { - struct page *page; - union { - dma_addr_t daddr; - - /* - * For gen6/gen7 only. This is the offset in the GGTT - * where the page directory entries for PPGTT begin - */ - u32 ggtt_offset; - }; -}; - -struct i915_page_scratch { - struct i915_page_dma base; - u64 encode; -}; - struct i915_page_table { - struct i915_page_dma base; + struct drm_i915_gem_object *base; union { atomic_t used; struct i915_page_table *stash; @@ -179,12 +167,14 @@ struct i915_page_directory { other) #define px_base(px) \ - __px_choose_expr(px, struct i915_page_dma *, __x, \ - __px_choose_expr(px, struct i915_page_scratch *, &__x->base, \ - __px_choose_expr(px, struct i915_page_table *, &__x->base, \ - __px_choose_expr(px, struct i915_page_directory *, &__x->pt.base, \ - (void)0)))) -#define px_dma(px) (px_base(px)->daddr) + __px_choose_expr(px, struct drm_i915_gem_object *, __x, \ + __px_choose_expr(px, struct i915_page_table *, __x->base, \ + __px_choose_expr(px, struct i915_page_directory *, __x->pt.base, \ + (void)0))) + +struct page *__px_page(struct drm_i915_gem_object *p); +dma_addr_t __px_dma(struct drm_i915_gem_object *p); +#define px_dma(px) (__px_dma(px_base(px))) #define px_pt(px) \ __px_choose_expr(px, struct i915_page_table *, __x, \ @@ -192,13 +182,6 @@ struct i915_page_directory { (void)0)) #define px_used(px) (&px_pt(px)->used) -enum i915_cache_level; - -struct drm_i915_file_private; -struct drm_i915_gem_object; -struct i915_vma; -struct intel_gt; - struct i915_vm_pt_stash { /* preallocated chains of page tables/directories */ struct i915_page_table *pt[2]; @@ -222,13 +205,6 @@ struct i915_vma_ops { void (*clear_pages)(struct i915_vma *vma); }; -struct pagestash { - spinlock_t lock; - struct pagevec pvec; -}; - -void stash_init(struct pagestash *stash); - struct i915_address_space { struct kref ref; struct rcu_work rcu; @@ -265,20 +241,15 @@ struct i915_address_space { #define VM_CLASS_GGTT 0 #define VM_CLASS_PPGTT 1 - struct i915_page_scratch scratch[4]; + struct drm_i915_gem_object *scratch[4]; /** * List of vma currently bound. */ struct list_head bound_list; - struct pagestash free_pages; - /* Global GTT */ bool is_ggtt:1; - /* Some systems require uncached updates of the page directories */ - bool pt_kmap_wc:1; - /* Some systems support read-only mappings for GGTT and/or PPGTT */ bool has_read_only:1; @@ -286,6 +257,9 @@ struct i915_address_space { u8 pd_shift; u8 scratch_order; + struct drm_i915_gem_object * + (*alloc_pt_dma)(struct i915_address_space *vm, int sz); + u64 (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, u32 flags); /* Create a valid PTE */ @@ -501,9 +475,9 @@ i915_pd_entry(const struct i915_page_directory * const pdp, static inline dma_addr_t i915_page_dir_dma_addr(const struct i915_ppgtt *ppgtt, const unsigned int n) { - struct i915_page_dma *pt = ppgtt->pd->entry[n]; + struct i915_page_table *pt = ppgtt->pd->entry[n]; - return px_dma(pt ?: px_base(&ppgtt->vm.scratch[ppgtt->vm.top])); + return __px_dma(pt ? px_base(pt) : ppgtt->vm.scratch[ppgtt->vm.top]); } void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt); @@ -528,13 +502,10 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt); void i915_ggtt_suspend(struct i915_ggtt *gtt); void i915_ggtt_resume(struct i915_ggtt *ggtt); -int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p); -void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p); - -#define kmap_atomic_px(px) kmap_atomic(px_base(px)->page) +#define kmap_atomic_px(px) kmap_atomic(__px_page(px_base(px))) void -fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count); +fill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count); #define fill_px(px, v) fill_page_dma(px_base(px), (v), PAGE_SIZE / sizeof(u64)) #define fill32_px(px, v) do { \ @@ -542,37 +513,38 @@ fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count); fill_px((px), v__ << 32 | v__); \ } while (0) -int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp); -void cleanup_scratch_page(struct i915_address_space *vm); +int setup_scratch_page(struct i915_address_space *vm); void free_scratch(struct i915_address_space *vm); +struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz); struct i915_page_table *alloc_pt(struct i915_address_space *vm); struct i915_page_directory *alloc_pd(struct i915_address_space *vm); struct i915_page_directory *__alloc_pd(size_t sz); -void free_pd(struct i915_address_space *vm, struct i915_page_dma *pd); +int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj); -#define free_px(vm, px) free_pd(vm, px_base(px)) +void free_pt(struct i915_address_space *vm, struct i915_page_table *pt); +#define free_px(vm, px) free_pt(vm, px_pt(px)) void __set_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - struct i915_page_dma * const to, + struct i915_page_table *pt, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)); #define set_pd_entry(pd, idx, to) \ - __set_pd_entry((pd), (idx), px_base(to), gen8_pde_encode) + __set_pd_entry((pd), (idx), px_pt(to), gen8_pde_encode) void clear_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - const struct i915_page_scratch * const scratch); + const struct drm_i915_gem_object * const scratch); bool release_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, struct i915_page_table * const pt, - const struct i915_page_scratch * const scratch); + const struct drm_i915_gem_object * const scratch); void gen6_ggtt_invalidate(struct i915_ggtt *ggtt); int ggtt_set_pages(struct i915_vma *vma); @@ -594,6 +566,8 @@ void setup_private_pat(struct intel_uncore *uncore); int i915_vm_alloc_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash, u64 size); +int i915_vm_pin_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash); void i915_vm_free_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash); diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index 09056544bc293..ede6369a9092d 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -18,7 +18,8 @@ struct i915_page_table *alloc_pt(struct i915_address_space *vm) if (unlikely(!pt)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, &pt->base))) { + pt->base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pt->base)) { kfree(pt); return ERR_PTR(-ENOMEM); } @@ -47,7 +48,8 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) if (unlikely(!pd)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, px_base(pd)))) { + pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pd->pt.base)) { kfree(pd); return ERR_PTR(-ENOMEM); } @@ -55,27 +57,28 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) return pd; } -void free_pd(struct i915_address_space *vm, struct i915_page_dma *pd) +void free_pt(struct i915_address_space *vm, struct i915_page_table *pt) { - cleanup_page_dma(vm, pd); - kfree(pd); + i915_gem_object_put(pt->base); + kfree(pt); } static inline void -write_dma_entry(struct i915_page_dma * const pdma, +write_dma_entry(struct drm_i915_gem_object * const pdma, const unsigned short idx, const u64 encoded_entry) { - u64 * const vaddr = kmap_atomic(pdma->page); + u64 * const vaddr = kmap_atomic(__px_page(pdma)); vaddr[idx] = encoded_entry; + clflush_cache_range(&vaddr[idx], sizeof(u64)); kunmap_atomic(vaddr); } void __set_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - struct i915_page_dma * const to, + struct i915_page_table * const to, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) { /* Each thread pre-pins the pd, and we may have a thread per pde. */ @@ -83,13 +86,13 @@ __set_pd_entry(struct i915_page_directory * const pd, atomic_inc(px_used(pd)); pd->entry[idx] = to; - write_dma_entry(px_base(pd), idx, encode(to->daddr, I915_CACHE_LLC)); + write_dma_entry(px_base(pd), idx, encode(px_dma(to), I915_CACHE_LLC)); } void clear_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - const struct i915_page_scratch * const scratch) + const struct drm_i915_gem_object * const scratch) { GEM_BUG_ON(atomic_read(px_used(pd)) == 0); @@ -102,7 +105,7 @@ bool release_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, struct i915_page_table * const pt, - const struct i915_page_scratch * const scratch) + const struct drm_i915_gem_object * const scratch) { bool free = false; @@ -234,6 +237,23 @@ int i915_vm_alloc_pt_stash(struct i915_address_space *vm, return 0; } +int i915_vm_pin_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash) +{ + struct i915_page_table *pt; + int n, err; + + for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { + for (pt = stash->pt[n]; pt; pt = pt->stash) { + err = pin_pt_dma(vm, pt->base); + if (err) + return err; + } + } + + return 0; +} + void i915_vm_free_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash) { diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 84da20f6515cf..a3b10f3c83ebc 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -202,16 +202,18 @@ static struct i915_address_space *vm_alias(struct i915_address_space *vm) return vm; } +static u32 pp_dir(struct i915_address_space *vm) +{ + return to_gen6_ppgtt(i915_vm_to_ppgtt(vm))->pp_dir; +} + static void set_pp_dir(struct intel_engine_cs *engine) { struct i915_address_space *vm = vm_alias(engine->gt->vm); if (vm) { - struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - ENGINE_WRITE(engine, RING_PP_DIR_DCLV, PP_DIR_DCLV_2G); - ENGINE_WRITE(engine, RING_PP_DIR_BASE, - px_base(ppgtt->pd)->ggtt_offset << 10); + ENGINE_WRITE(engine, RING_PP_DIR_BASE, pp_dir(vm)); } } @@ -609,7 +611,7 @@ static const struct intel_context_ops ring_context_ops = { }; static int load_pd_dir(struct i915_request *rq, - const struct i915_ppgtt *ppgtt, + struct i915_address_space *vm, u32 valid) { const struct intel_engine_cs * const engine = rq->engine; @@ -625,7 +627,7 @@ static int load_pd_dir(struct i915_request *rq, *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); - *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; + *cs++ = pp_dir(vm); /* Stall until the page table load is complete? */ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; @@ -827,7 +829,7 @@ static int switch_mm(struct i915_request *rq, struct i915_address_space *vm) * post-sync op, this extra pass appears vital before a * mm switch! */ - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), PP_DIR_DCLV_2G); + ret = load_pd_dir(rq, vm, PP_DIR_DCLV_2G); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 3c3b9842bbbdc..1570eb8aa9783 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -403,6 +403,14 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) wa_ctx->indirect_ctx.shadow_va = NULL; } +static void set_dma_address(struct i915_page_directory *pd, dma_addr_t addr) +{ + struct scatterlist *sg = pd->pt.base->mm.pages->sgl; + + /* This is not a good idea */ + sg->dma_address = addr; +} + static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, struct intel_context *ce) { @@ -411,7 +419,7 @@ static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, int i = 0; if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) { - px_dma(ppgtt->pd) = mm->ppgtt_mm.shadow_pdps[0]; + set_dma_address(ppgtt->pd, mm->ppgtt_mm.shadow_pdps[0]); } else { for (i = 0; i < GVT_RING_CTX_NR_PDPS; i++) { struct i915_page_directory * const pd = @@ -421,7 +429,8 @@ static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, shadow ppgtt. */ if (!pd) break; - px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i]; + + set_dma_address(pd, mm->ppgtt_mm.shadow_pdps[i]); } } } @@ -1240,13 +1249,13 @@ i915_context_ppgtt_root_restore(struct intel_vgpu_submission *s, int i; if (i915_vm_is_4lvl(&ppgtt->vm)) { - px_dma(ppgtt->pd) = s->i915_context_pml4; + set_dma_address(ppgtt->pd, s->i915_context_pml4); } else { for (i = 0; i < GEN8_3LVL_PDPES; i++) { struct i915_page_directory * const pd = i915_pd_entry(ppgtt->pd, i); - px_dma(pd) = s->i915_context_pdps[i]; + set_dma_address(pd, s->i915_context_pdps[i]); } } } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d8aaa882560bd..00292a849c34c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1075,6 +1075,7 @@ static void i915_driver_release(struct drm_device *dev) intel_memory_regions_driver_release(dev_priv); i915_ggtt_driver_release(dev_priv); + i915_gem_drain_freed_objects(dev_priv); i915_driver_mmio_release(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0fb83a780b218..2b95467b760ad 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -587,11 +587,6 @@ struct i915_gem_mm { */ atomic_t free_count; - /** - * Small stash of WC pages - */ - struct pagestash wc_stash; - /** * tmpfs instance used for shmem backed objects */ diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index a9e79b67035e0..c6bf04ca20328 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -872,24 +872,30 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) if (err) return err; + if (flags & PIN_GLOBAL) + wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm); + if (flags & vma->vm->bind_async_flags) { work = i915_vma_work(); if (!work) { err = -ENOMEM; - goto err_pages; + goto err_rpm; } work->vm = i915_vm_get(vma->vm); /* Allocate enough page directories to used PTE */ - if (vma->vm->allocate_va_range) + if (vma->vm->allocate_va_range) { i915_vm_alloc_pt_stash(vma->vm, &work->stash, vma->size); - } - if (flags & PIN_GLOBAL) - wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm); + err = i915_vm_pin_pt_stash(vma->vm, + &work->stash); + if (err) + goto err_fence; + } + } /* * Differentiate between user/kernel vma inside the aliasing-ppgtt. @@ -978,9 +984,9 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) err_fence: if (work) dma_fence_work_commit_imm(&work->base); +err_rpm: if (wakeref) intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref); -err_pages: vma_put_pages(vma); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 9b8fc990e9efc..af8205a2bd8fd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -178,6 +178,12 @@ static int igt_ppgtt_alloc(void *arg) if (err) goto err_ppgtt_cleanup; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) { + i915_vm_free_pt_stash(&ppgtt->vm, &stash); + goto err_ppgtt_cleanup; + } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, size); cond_resched(); @@ -194,6 +200,12 @@ static int igt_ppgtt_alloc(void *arg) if (err) goto err_ppgtt_cleanup; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) { + i915_vm_free_pt_stash(&ppgtt->vm, &stash); + goto err_ppgtt_cleanup; + } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, last, size - last); cond_resched(); @@ -289,6 +301,11 @@ static int lowlevel_hole(struct i915_address_space *vm, BIT_ULL(size))) break; + if (i915_vm_pin_pt_stash(vm, &stash)) { + i915_vm_free_pt_stash(vm, &stash); + break; + } + vm->allocate_va_range(vm, &stash, addr, BIT_ULL(size)); @@ -1912,6 +1929,12 @@ static int igt_cs_tlb(void *arg) if (err) goto end; + err = i915_vm_pin_pt_stash(vm, &stash); + if (err) { + i915_vm_free_pt_stash(vm, &stash); + goto end; + } + vm->allocate_va_range(vm, &stash, offset, chunk_size); i915_vm_free_pt_stash(vm, &stash); diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c index c2d001d9c0ec0..debbac660519e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_perf.c +++ b/drivers/gpu/drm/i915/selftests/i915_perf.c @@ -307,7 +307,7 @@ static int live_noa_gpr(void *arg) } /* Poison the ce->vm so we detect writes not to the GGTT gt->scratch */ - scratch = kmap(ce->vm->scratch[0].base.page); + scratch = kmap(__px_page(ce->vm->scratch[0])); memset(scratch, POISON_FREE, PAGE_SIZE); rq = intel_context_create_request(ce); @@ -405,7 +405,7 @@ static int live_noa_gpr(void *arg) out_rq: i915_request_put(rq); out_ce: - kunmap(ce->vm->scratch[0].base.page); + kunmap(__px_page(ce->vm->scratch[0])); intel_context_put(ce); out: stream_destroy(stream); diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 5e4fb0fba34bc..7270fc8ca801a 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -78,6 +78,8 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT); + ppgtt->vm.alloc_pt_dma = alloc_pt_dma; + ppgtt->vm.clear_range = mock_clear_range; ppgtt->vm.insert_page = mock_insert_page; ppgtt->vm.insert_entries = mock_insert_entries; @@ -116,6 +118,8 @@ void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt) ggtt->mappable_end = resource_size(&ggtt->gmadr); ggtt->vm.total = 4096 * PAGE_SIZE; + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.clear_range = mock_clear_range; ggtt->vm.insert_page = mock_insert_page; ggtt->vm.insert_entries = mock_insert_entries; -- GitLab From 82adf901138cc0564656dc8dc3a47862a546cb2a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 29 Jul 2020 17:42:19 +0100 Subject: [PATCH 0817/1494] drm/i915/gt: Shrink i915_page_directory's slab bucket kmalloc uses power-of-two slab buckets for small allocations (up to a few pages). Since i915_page_directory is a page of pointers, plus a couple more, this is rounded up to 8K, and we waste nearly 50% of that allocation. Long terms this leads to poor memory utilisation, bloating the kernel footprint, but the problem is exacerbated by our conservative preallocation scheme for binding VMA. As we are required to allocate all levels for each vma just in case we need to insert them upon binding, this leads to a large multiplication factor for a single page vma. By halving the allocation we need for the page directory structure, we halve the impact of that factor, bringing workloads that once fitted into memory, hopefully back to fitting into memory. We maintain the split between i915_page_directory and i915_page_table as we only need half the allocation for the lowest, most populous, level. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 11 +++++----- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 26 +++++++++++----------- drivers/gpu/drm/i915/gt/intel_gtt.h | 10 +++++---- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 31 +++++++++++++++++++++------ 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index fb702e1de7391..7e5a86b774a7a 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -261,7 +261,7 @@ static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt) gen6_for_all_pdes(pt, pd, pde) if (pt) - free_px(&ppgtt->base.vm, pt); + free_pt(&ppgtt->base.vm, pt); } static void gen6_ppgtt_cleanup(struct i915_address_space *vm) @@ -275,7 +275,8 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm) mutex_destroy(&ppgtt->flush); mutex_destroy(&ppgtt->pin_mutex); - kfree(ppgtt->base.pd); + + free_pd(&ppgtt->base.vm, ppgtt->base.pd); } static int pd_vma_set_pages(struct i915_vma *vma) @@ -322,7 +323,7 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) if (!pt || atomic_read(&pt->used)) continue; - free_px(&ppgtt->base.vm, pt); + free_pt(&ppgtt->base.vm, pt); pd->entry[pde] = NULL; } @@ -447,7 +448,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma; ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode; - ppgtt->base.pd = __alloc_pd(sizeof(*ppgtt->base.pd)); + ppgtt->base.pd = __alloc_pd(I915_PDES); if (!ppgtt->base.pd) { err = -ENOMEM; goto err_free; @@ -468,7 +469,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) err_scratch: free_scratch(&ppgtt->base.vm); err_pd: - kfree(ppgtt->base.pd); + free_pd(&ppgtt->base.vm, ppgtt->base.pd); err_free: mutex_destroy(&ppgtt->pin_mutex); kfree(ppgtt); diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index a40cb7ea8c666..eb64f474a78c6 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -181,7 +181,7 @@ static void __gen8_ppgtt_cleanup(struct i915_address_space *vm, } while (pde++, --count); } - free_px(vm, pd); + free_px(vm, &pd->pt, lvl); } static void gen8_ppgtt_cleanup(struct i915_address_space *vm) @@ -248,7 +248,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, } if (release_pd_entry(pd, idx, pt, scratch)) - free_px(vm, pt); + free_px(vm, pt, lvl); } while (idx++, --len); return start; @@ -628,7 +628,7 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt) err = pin_pt_dma(vm, pde->pt.base); if (err) { i915_gem_object_put(pde->pt.base); - kfree(pde); + free_pd(vm, pde); return err; } @@ -648,28 +648,30 @@ gen8_alloc_top_pd(struct i915_address_space *vm) struct i915_page_directory *pd; int err; - GEM_BUG_ON(count > ARRAY_SIZE(pd->entry)); + GEM_BUG_ON(count > I915_PDES); - pd = __alloc_pd(offsetof(typeof(*pd), entry[count])); + pd = __alloc_pd(count); if (unlikely(!pd)) return ERR_PTR(-ENOMEM); pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); if (IS_ERR(pd->pt.base)) { - kfree(pd); - return ERR_PTR(-ENOMEM); + err = PTR_ERR(pd->pt.base); + pd->pt.base = NULL; + goto err_pd; } err = pin_pt_dma(vm, pd->pt.base); - if (err) { - i915_gem_object_put(pd->pt.base); - kfree(pd); - return ERR_PTR(err); - } + if (err) + goto err_pd; fill_page_dma(px_base(pd), vm->scratch[vm->top]->encode, count); atomic_inc(px_used(pd)); /* mark as pinned */ return pd; + +err_pd: + free_pd(vm, pd); + return ERR_PTR(err); } /* diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 6abab2d37b6fe..c13c650ced224 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -156,7 +156,7 @@ struct i915_page_table { struct i915_page_directory { struct i915_page_table pt; spinlock_t lock; - void *entry[512]; + void **entry; }; #define __px_choose_expr(x, type, expr, other) \ @@ -519,12 +519,14 @@ void free_scratch(struct i915_address_space *vm); struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz); struct i915_page_table *alloc_pt(struct i915_address_space *vm); struct i915_page_directory *alloc_pd(struct i915_address_space *vm); -struct i915_page_directory *__alloc_pd(size_t sz); +struct i915_page_directory *__alloc_pd(int npde); int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj); -void free_pt(struct i915_address_space *vm, struct i915_page_table *pt); -#define free_px(vm, px) free_pt(vm, px_pt(px)) +void free_px(struct i915_address_space *vm, + struct i915_page_table *pt, int lvl); +#define free_pt(vm, px) free_px(vm, px, 0) +#define free_pd(vm, px) free_px(vm, px_pt(px), 1) void __set_pd_entry(struct i915_page_directory * const pd, diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index ede6369a9092d..46d9aceda64cd 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -28,14 +28,20 @@ struct i915_page_table *alloc_pt(struct i915_address_space *vm) return pt; } -struct i915_page_directory *__alloc_pd(size_t sz) +struct i915_page_directory *__alloc_pd(int count) { struct i915_page_directory *pd; - pd = kzalloc(sz, I915_GFP_ALLOW_FAIL); + pd = kzalloc(sizeof(*pd), I915_GFP_ALLOW_FAIL); if (unlikely(!pd)) return NULL; + pd->entry = kcalloc(count, sizeof(*pd->entry), I915_GFP_ALLOW_FAIL); + if (unlikely(!pd->entry)) { + kfree(pd); + return NULL; + } + spin_lock_init(&pd->lock); return pd; } @@ -44,12 +50,13 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) { struct i915_page_directory *pd; - pd = __alloc_pd(sizeof(*pd)); + pd = __alloc_pd(I915_PDES); if (unlikely(!pd)) return ERR_PTR(-ENOMEM); pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); if (IS_ERR(pd->pt.base)) { + kfree(pd->entry); kfree(pd); return ERR_PTR(-ENOMEM); } @@ -57,9 +64,19 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) return pd; } -void free_pt(struct i915_address_space *vm, struct i915_page_table *pt) +void free_px(struct i915_address_space *vm, struct i915_page_table *pt, int lvl) { - i915_gem_object_put(pt->base); + BUILD_BUG_ON(offsetof(struct i915_page_directory, pt)); + + if (lvl) { + struct i915_page_directory *pd = + container_of(pt, typeof(*pd), pt); + kfree(pd->entry); + } + + if (pt->base) + i915_gem_object_put(pt->base); + kfree(pt); } @@ -82,7 +99,7 @@ __set_pd_entry(struct i915_page_directory * const pd, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) { /* Each thread pre-pins the pd, and we may have a thread per pde. */ - GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * ARRAY_SIZE(pd->entry)); + GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * I915_PDES); atomic_inc(px_used(pd)); pd->entry[idx] = to; @@ -263,7 +280,7 @@ void i915_vm_free_pt_stash(struct i915_address_space *vm, for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { while ((pt = stash->pt[n])) { stash->pt[n] = pt->stash; - free_px(vm, pt); + free_px(vm, pt, n); } } } -- GitLab From 3f7dc1071665c38a195e24d28d8418b68c441584 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Sat, 1 Aug 2020 17:02:24 +0100 Subject: [PATCH 0818/1494] drm/i915/gt: Move intel_breadcrumbs_arm_irq earlier Move the __intel_breadcrumbs_arm_irq earlier, next to the disarm_irq, so that we can make use of it in the following patch. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200801160225.6814-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 84 ++++++++++----------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 2ffd47a86656c..9dd99969fd07c 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -54,6 +54,36 @@ static void irq_disable(struct intel_engine_cs *engine) spin_unlock(&engine->gt->irq_lock); } +static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) +{ + lockdep_assert_held(&b->irq_lock); + + if (!b->irq_engine || b->irq_armed) + return; + + if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) + return; + + /* + * The breadcrumb irq will be disarmed on the interrupt after the + * waiters are signaled. This gives us a single interrupt window in + * which we can add a new waiter and avoid the cost of re-enabling + * the irq. + */ + WRITE_ONCE(b->irq_armed, true); + + /* + * Since we are waiting on a request, the GPU should be busy + * and should have its own rpm reference. This is tracked + * by i915->gt.awake, we can forgo holding our own wakref + * for the interrupt as before i915->gt.awake is released (when + * the driver is idle) we disarm the breadcrumbs. + */ + + if (!b->irq_enabled++) + irq_enable(b->irq_engine); +} + static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { lockdep_assert_held(&b->irq_lock); @@ -69,18 +99,6 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) intel_gt_pm_put_async(b->irq_engine->gt); } -void intel_breadcrumbs_park(struct intel_breadcrumbs *b) -{ - unsigned long flags; - - if (!READ_ONCE(b->irq_armed)) - return; - - spin_lock_irqsave(&b->irq_lock, flags); - __intel_breadcrumbs_disarm_irq(b); - spin_unlock_irqrestore(&b->irq_lock, flags); -} - static inline bool __request_completed(const struct i915_request *rq) { return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); @@ -214,36 +232,6 @@ static void signal_irq_work(struct irq_work *work) } } -static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) -{ - lockdep_assert_held(&b->irq_lock); - - if (!b->irq_engine || b->irq_armed) - return; - - if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) - return; - - /* - * The breadcrumb irq will be disarmed on the interrupt after the - * waiters are signaled. This gives us a single interrupt window in - * which we can add a new waiter and avoid the cost of re-enabling - * the irq. - */ - WRITE_ONCE(b->irq_armed, true); - - /* - * Since we are waiting on a request, the GPU should be busy - * and should have its own rpm reference. This is tracked - * by i915->gt.awake, we can forgo holding our own wakref - * for the interrupt as before i915->gt.awake is released (when - * the driver is idle) we disarm the breadcrumbs. - */ - - if (!b->irq_enabled++) - irq_enable(b->irq_engine); -} - struct intel_breadcrumbs * intel_breadcrumbs_create(struct intel_engine_cs *irq_engine) { @@ -281,6 +269,18 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b) spin_unlock_irqrestore(&b->irq_lock, flags); } +void intel_breadcrumbs_park(struct intel_breadcrumbs *b) +{ + unsigned long flags; + + if (!READ_ONCE(b->irq_armed)) + return; + + spin_lock_irqsave(&b->irq_lock, flags); + __intel_breadcrumbs_disarm_irq(b); + spin_unlock_irqrestore(&b->irq_lock, flags); +} + void intel_breadcrumbs_free(struct intel_breadcrumbs *b) { kfree(b); -- GitLab From e23005604b2f815720b00c2b36c9597fd43923cf Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Sat, 1 Aug 2020 17:02:25 +0100 Subject: [PATCH 0819/1494] drm/i915/gt: Hold context/request reference while breadcrumbs are active Currently we hold no actual reference to the request nor context while they are attached to a breadcrumb. To avoid freeing the request/context too early, we serialise with cancel-breadcrumbs by taking the irq spinlock in i915_request_retire(). The alternative is to take a reference for a new breadcrumb and release it upon signaling; removing the more frequently hit contention point in i915_request_retire(). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200801160225.6814-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Rebased and reordered into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 103 +++++++++++++------- drivers/gpu/drm/i915/i915_request.c | 9 +- 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 9dd99969fd07c..d8b206e53660a 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_breadcrumbs.h" +#include "intel_context.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" @@ -99,6 +100,22 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) intel_gt_pm_put_async(b->irq_engine->gt); } +static void add_signaling_context(struct intel_breadcrumbs *b, + struct intel_context *ce) +{ + intel_context_get(ce); + list_add_tail(&ce->signal_link, &b->signalers); + if (list_is_first(&ce->signal_link, &b->signalers)) + __intel_breadcrumbs_arm_irq(b); +} + +static void remove_signaling_context(struct intel_breadcrumbs *b, + struct intel_context *ce) +{ + list_del(&ce->signal_link); + intel_context_put(ce); +} + static inline bool __request_completed(const struct i915_request *rq) { return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); @@ -107,6 +124,9 @@ static inline bool __request_completed(const struct i915_request *rq) __maybe_unused static bool check_signal_order(struct intel_context *ce, struct i915_request *rq) { + if (rq->context != ce) + return false; + if (!list_is_last(&rq->signal_link, &ce->signals) && i915_seqno_passed(rq->fence.seqno, list_next_entry(rq, signal_link)->fence.seqno)) @@ -158,10 +178,11 @@ static bool __signal_request(struct i915_request *rq, struct list_head *signals) { clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); - if (!__dma_fence_signal(&rq->fence)) + if (!__dma_fence_signal(&rq->fence)) { + i915_request_put(rq); return false; + } - i915_request_get(rq); list_add_tail(&rq->signal_link, signals); return true; } @@ -209,8 +230,8 @@ static void signal_irq_work(struct irq_work *work) /* Advance the list to the first incomplete request */ __list_del_many(&ce->signals, pos); if (&ce->signals == pos) { /* now empty */ - list_del_init(&ce->signal_link); add_retire(b, ce->timeline); + remove_signaling_context(b, ce); } } } @@ -279,6 +300,9 @@ void intel_breadcrumbs_park(struct intel_breadcrumbs *b) spin_lock_irqsave(&b->irq_lock, flags); __intel_breadcrumbs_disarm_irq(b); spin_unlock_irqrestore(&b->irq_lock, flags); + + if (!list_empty(&b->signalers)) + irq_work_queue(&b->irq_work); } void intel_breadcrumbs_free(struct intel_breadcrumbs *b) @@ -295,6 +319,8 @@ static void insert_breadcrumb(struct i915_request *rq, if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) return; + i915_request_get(rq); + /* * If the request is already completed, we can transfer it * straight onto a signaled list, and queue the irq worker for @@ -306,32 +332,33 @@ static void insert_breadcrumb(struct i915_request *rq, return; } - __intel_breadcrumbs_arm_irq(b); - - /* - * We keep the seqno in retirement order, so we can break - * inside intel_engine_signal_breadcrumbs as soon as we've - * passed the last completed request (or seen a request that - * hasn't event started). We could walk the timeline->requests, - * but keeping a separate signalers_list has the advantage of - * hopefully being much smaller than the full list and so - * provides faster iteration and detection when there are no - * more interrupts required for this context. - * - * We typically expect to add new signalers in order, so we - * start looking for our insertion point from the tail of - * the list. - */ - list_for_each_prev(pos, &ce->signals) { - struct i915_request *it = - list_entry(pos, typeof(*it), signal_link); + if (list_empty(&ce->signals)) { + add_signaling_context(b, ce); + pos = &ce->signals; + } else { + /* + * We keep the seqno in retirement order, so we can break + * inside intel_engine_signal_breadcrumbs as soon as we've + * passed the last completed request (or seen a request that + * hasn't event started). We could walk the timeline->requests, + * but keeping a separate signalers_list has the advantage of + * hopefully being much smaller than the full list and so + * provides faster iteration and detection when there are no + * more interrupts required for this context. + * + * We typically expect to add new signalers in order, so we + * start looking for our insertion point from the tail of + * the list. + */ + list_for_each_prev(pos, &ce->signals) { + struct i915_request *it = + list_entry(pos, typeof(*it), signal_link); - if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) - break; + if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) + break; + } } list_add(&rq->signal_link, pos); - if (pos == &ce->signals) /* catch transitions from empty list */ - list_move_tail(&ce->signal_link, &b->signalers); GEM_BUG_ON(!check_signal_order(ce, rq)); set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); @@ -412,23 +439,19 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) list_del(&rq->signal_link); if (list_empty(&ce->signals)) - list_del_init(&ce->signal_link); + remove_signaling_context(b, ce); clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); + i915_request_put(rq); } spin_unlock(&b->irq_lock); } -void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, - struct drm_printer *p) +static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p) { - struct intel_breadcrumbs *b = engine->breadcrumbs; struct intel_context *ce; struct i915_request *rq; - if (!b || list_empty(&b->signalers)) - return; - drm_printf(p, "Signals:\n"); spin_lock_irq(&b->irq_lock); @@ -444,3 +467,17 @@ void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, } spin_unlock_irq(&b->irq_lock); } + +void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, + struct drm_printer *p) +{ + struct intel_breadcrumbs *b; + + b = engine->breadcrumbs; + if (!b) + return; + + drm_printf(p, "IRQ: %s\n", enableddisabled(b->irq_armed)); + if (!list_empty(&b->signalers)) + print_signals(b, p); +} diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index fcb00b283b4f6..20ba3d9fcc5eb 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -296,13 +296,12 @@ bool i915_request_retire(struct i915_request *rq) */ remove_from_engine(rq); - spin_lock_irq(&rq->lock); i915_request_mark_complete(rq); - if (!i915_request_signaled(rq)) + if (!i915_request_signaled(rq)) { + spin_lock_irq(&rq->lock); dma_fence_signal_locked(&rq->fence); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags)) - i915_request_cancel_breadcrumb(rq); - spin_unlock_irq(&rq->lock); + spin_unlock_irq(&rq->lock); + } if (i915_request_has_waitboost(rq)) { GEM_BUG_ON(!atomic_read(&rq->engine->gt->rps.num_waiters)); -- GitLab From dd5e024956bf3035be380a3f022b77c06166112a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 6 Aug 2020 15:57:28 +0100 Subject: [PATCH 0820/1494] drm/i915/selftests: Prevent selecting 0 for our random width/align When igt_random_offset() is a given a range of [0, PAGE_SIZE], it is allowed to return 0. However, attempting to use a size of 0 for the igt_lmem_write_cpu() byte poking, leads to call igt_random_offset() with a range of [offset, offset + 0] and ask it to find a length of 4 within it. This triggers the bug on that the requested length should fit within the range! Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200806145728.16495-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/selftests/intel_memory_region.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 6e80d99048e4b..741270fcb6b99 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -522,9 +522,9 @@ static int igt_lmem_write_cpu(void *arg) goto out_unpin; } - /* We want to throw in a random width/align */ - bytes[0] = igt_random_offset(&prng, 0, PAGE_SIZE, sizeof(u32), - sizeof(u32)); + /* A random multiple of u32, picked between [64, PAGE_SIZE - 64] */ + bytes[0] = igt_random_offset(&prng, 64, PAGE_SIZE - 64, 0, sizeof(u32)); + GEM_BUG_ON(!IS_ALIGNED(bytes[0], sizeof(u32))); i = 0; do { -- GitLab From 736e785f9b28cd9ef2d16a80960a04fd00e64b22 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 6 Aug 2020 11:59:54 +0100 Subject: [PATCH 0821/1494] drm/i915/gem: Reduce context termination list iteration guard to RCU As we now protect the timeline list using RCU, we can drop the timeline->mutex for guarding the list iteration during context close, as we are searching for an inflight request. Any new request will see the context is banned and not be submitted. In doing so, pull the checks for a concurrent submission of the request (notably the i915_request_completed()) under the engine spinlock, to fully serialise with __i915_request_submit()). That is in the case of preempt-to-busy where the request may be completed during the __i915_request_submit(), we need to be careful that we sample the request status after serialising so that we don't miss the request the engine is actually submitting. Fixes: 4a3174152147 ("drm/i915/gem: Refine occupancy test in kill_context()") References: d22d2d073ef8 ("drm/i915: Protect i915_request_await_start from early waits") # rcu protection of timeline->requests References: https://gitlab.freedesktop.org/drm/intel/-/issues/1622 References: https://gitlab.freedesktop.org/drm/intel/-/issues/2158 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200806105954.7766-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 32 ++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d8cccbab7a51d..db893f6c516b4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -439,29 +439,36 @@ static bool __cancel_engine(struct intel_engine_cs *engine) return __reset_engine(engine); } -static struct intel_engine_cs *__active_engine(struct i915_request *rq) +static bool +__active_engine(struct i915_request *rq, struct intel_engine_cs **active) { struct intel_engine_cs *engine, *locked; + bool ret = false; /* * Serialise with __i915_request_submit() so that it sees * is-banned?, or we know the request is already inflight. + * + * Note that rq->engine is unstable, and so we double + * check that we have acquired the lock on the final engine. */ locked = READ_ONCE(rq->engine); spin_lock_irq(&locked->active.lock); while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) { spin_unlock(&locked->active.lock); - spin_lock(&engine->active.lock); locked = engine; + spin_lock(&locked->active.lock); } - engine = NULL; - if (i915_request_is_active(rq) && rq->fence.error != -EIO) - engine = rq->engine; + if (!i915_request_completed(rq)) { + if (i915_request_is_active(rq) && rq->fence.error != -EIO) + *active = locked; + ret = true; + } spin_unlock_irq(&locked->active.lock); - return engine; + return ret; } static struct intel_engine_cs *active_engine(struct intel_context *ce) @@ -472,17 +479,16 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) if (!ce->timeline) return NULL; - mutex_lock(&ce->timeline->mutex); - list_for_each_entry_reverse(rq, &ce->timeline->requests, link) { - if (i915_request_completed(rq)) - break; + rcu_read_lock(); + list_for_each_entry_rcu(rq, &ce->timeline->requests, link) { + if (i915_request_is_active(rq) && i915_request_completed(rq)) + continue; /* Check with the backend if the request is inflight */ - engine = __active_engine(rq); - if (engine) + if (__active_engine(rq, &engine)) break; } - mutex_unlock(&ce->timeline->mutex); + rcu_read_unlock(); return engine; } -- GitLab From da1ea128a6a4d6d52b02ded82933944161c1cb01 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 6 Aug 2020 17:10:56 +0100 Subject: [PATCH 0822/1494] drm/i915/gem: Free the fence after a fence-chain lookup failure If dma_fence_chain_find_seqno() reports an error, it does so in its preamble before it disposes of the input fence. On handling the error, we need to drop the reference to the fence. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2292 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Fixes: 13149e8bafc4 ("drm/i915: add syncobj timeline support") Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200806161056.17593-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 9ce114d672887..24a1486d2dc54 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2289,6 +2289,7 @@ add_timeline_fence_array(struct i915_execbuffer *eb, if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { DRM_DEBUG("Syncobj handle missing requested point %llu\n", point); + dma_fence_put(fence); drm_syncobj_put(syncobj); return err; } -- GitLab From 102a0a9051f4bb61c105bd2c68b82456325c7c2a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:41 +0200 Subject: [PATCH 0823/1494] Revert "drm/i915/gem: Async GPU relocations only" This reverts commit 9e0f9464e2ab ("drm/i915/gem: Async GPU relocations only"), and related commit 7ac2d2536dfa7 ("drm/i915/gem: Delete unused code"). Async GPU relocations are not the path forward, we want to remove GPU accelerated relocation support eventually when userspace is fixed to use VM_BIND, and this is the first step towards that. We will keep async gpu relocations around for now, until userspace is fixed. Relocation support will be disabled completely on platforms where there was never any userspace that depends on it, as the hardware doesn't require it from at least gen9+ onward. For older platforms, the plan is to use cpu relocations only. The igt side is fixed in igt commit 39e9aa1032a4e ("tests/i915: Remove subtests that rely on async relocation behavior"). Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-2-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 319 ++++++++++++++++-- .../i915/gem/selftests/i915_gem_execbuffer.c | 21 +- 2 files changed, 313 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 24a1486d2dc54..c6a613d92a13a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -46,6 +46,13 @@ struct eb_vma_array { struct eb_vma vma[]; }; +enum { + FORCE_CPU_RELOC = 1, + FORCE_GTT_RELOC, + FORCE_GPU_RELOC, +#define DBG_FORCE_RELOC 0 /* choose one of the above! */ +}; + #define __EXEC_OBJECT_HAS_PIN BIT(31) #define __EXEC_OBJECT_HAS_FENCE BIT(30) #define __EXEC_OBJECT_NEEDS_MAP BIT(29) @@ -261,6 +268,8 @@ struct i915_execbuffer { */ struct reloc_cache { struct drm_mm_node node; /** temporary GTT binding */ + unsigned long vaddr; /** Current kmap address */ + unsigned long page; /** Currently mapped page index */ unsigned int gen; /** Cached value of INTEL_GEN */ bool use_64bit_reloc : 1; bool has_llc : 1; @@ -607,6 +616,23 @@ eb_add_vma(struct i915_execbuffer *eb, } } +static inline int use_cpu_reloc(const struct reloc_cache *cache, + const struct drm_i915_gem_object *obj) +{ + if (!i915_gem_object_has_struct_page(obj)) + return false; + + if (DBG_FORCE_RELOC == FORCE_CPU_RELOC) + return true; + + if (DBG_FORCE_RELOC == FORCE_GTT_RELOC) + return false; + + return (cache->has_llc || + obj->cache_dirty || + obj->cache_level != I915_CACHE_NONE); +} + static int eb_reserve_vma(const struct i915_execbuffer *eb, struct eb_vma *ev, u64 pin_flags) @@ -937,6 +963,8 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc, static void reloc_cache_init(struct reloc_cache *cache, struct drm_i915_private *i915) { + cache->page = -1; + cache->vaddr = 0; /* Must be a variable in the struct to allow GCC to unroll. */ cache->gen = INTEL_GEN(i915); cache->has_llc = HAS_LLC(i915); @@ -948,6 +976,25 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->target = NULL; } +static inline void *unmask_page(unsigned long p) +{ + return (void *)(uintptr_t)(p & PAGE_MASK); +} + +static inline unsigned int unmask_flags(unsigned long p) +{ + return p & ~PAGE_MASK; +} + +#define KMAP 0x4 /* after CLFLUSH_FLAGS */ + +static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) +{ + struct drm_i915_private *i915 = + container_of(cache, struct i915_execbuffer, reloc_cache)->i915; + return &i915->ggtt; +} + #define RELOC_TAIL 4 static int reloc_gpu_chain(struct reloc_cache *cache) @@ -1060,6 +1107,186 @@ static int reloc_gpu_flush(struct reloc_cache *cache) return err; } +static void reloc_cache_reset(struct reloc_cache *cache) +{ + void *vaddr; + + if (!cache->vaddr) + return; + + vaddr = unmask_page(cache->vaddr); + if (cache->vaddr & KMAP) { + if (cache->vaddr & CLFLUSH_AFTER) + mb(); + + kunmap_atomic(vaddr); + i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm); + } else { + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __iomem *)vaddr); + + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.clear_range(&ggtt->vm, + cache->node.start, + cache->node.size); + mutex_lock(&ggtt->vm.mutex); + drm_mm_remove_node(&cache->node); + mutex_unlock(&ggtt->vm.mutex); + } else { + i915_vma_unpin((struct i915_vma *)cache->node.mm); + } + } + + cache->vaddr = 0; + cache->page = -1; +} + +static void *reloc_kmap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long pageno) +{ + void *vaddr; + struct page *page; + + if (cache->vaddr) { + kunmap_atomic(unmask_page(cache->vaddr)); + } else { + unsigned int flushes; + int err; + + err = i915_gem_object_prepare_write(obj, &flushes); + if (err) + return ERR_PTR(err); + + BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); + BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); + + cache->vaddr = flushes | KMAP; + cache->node.mm = (void *)obj; + if (flushes) + mb(); + } + + page = i915_gem_object_get_page(obj, pageno); + if (!obj->mm.dirty) + set_page_dirty(page); + + vaddr = kmap_atomic(page); + cache->vaddr = unmask_flags(cache->vaddr) | (unsigned long)vaddr; + cache->page = pageno; + + return vaddr; +} + +static void *reloc_iomap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + unsigned long offset; + void *vaddr; + + if (cache->vaddr) { + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); + } else { + struct i915_vma *vma; + int err; + + if (i915_gem_object_is_tiled(obj)) + return ERR_PTR(-EINVAL); + + if (use_cpu_reloc(cache, obj)) + return NULL; + + i915_gem_object_lock(obj); + err = i915_gem_object_set_to_gtt_domain(obj, true); + i915_gem_object_unlock(obj); + if (err) + return ERR_PTR(err); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (IS_ERR(vma)) { + memset(&cache->node, 0, sizeof(cache->node)); + mutex_lock(&ggtt->vm.mutex); + err = drm_mm_insert_node_in_range + (&ggtt->vm.mm, &cache->node, + PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE, + 0, ggtt->mappable_end, + DRM_MM_INSERT_LOW); + mutex_unlock(&ggtt->vm.mutex); + if (err) /* no inactive aperture space, use cpu reloc */ + return NULL; + } else { + cache->node.start = vma->node.start; + cache->node.mm = (void *)vma; + } + } + + offset = cache->node.start; + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.insert_page(&ggtt->vm, + i915_gem_object_get_dma_address(obj, page), + offset, I915_CACHE_NONE, 0); + } else { + offset += page << PAGE_SHIFT; + } + + vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap, + offset); + cache->page = page; + cache->vaddr = (unsigned long)vaddr; + + return vaddr; +} + +static void *reloc_vaddr(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + void *vaddr; + + if (cache->page == page) { + vaddr = unmask_page(cache->vaddr); + } else { + vaddr = NULL; + if ((cache->vaddr & KMAP) == 0) + vaddr = reloc_iomap(obj, cache, page); + if (!vaddr) + vaddr = reloc_kmap(obj, cache, page); + } + + return vaddr; +} + +static void clflush_write32(u32 *addr, u32 value, unsigned int flushes) +{ + if (unlikely(flushes & (CLFLUSH_BEFORE | CLFLUSH_AFTER))) { + if (flushes & CLFLUSH_BEFORE) { + clflushopt(addr); + mb(); + } + + *addr = value; + + /* + * Writes to the same cacheline are serialised by the CPU + * (including clflush). On the write path, we only require + * that it hits memory in an orderly fashion and place + * mb barriers at the start and end of the relocation phase + * to ensure ordering of clflush wrt to the system. + */ + if (flushes & CLFLUSH_AFTER) + clflushopt(addr); + } else + *addr = value; +} + static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -1225,6 +1452,17 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, return cmd; } +static inline bool use_reloc_gpu(struct i915_vma *vma) +{ + if (DBG_FORCE_RELOC == FORCE_GPU_RELOC) + return true; + + if (DBG_FORCE_RELOC) + return false; + + return !dma_resv_test_signaled_rcu(vma->resv, true); +} + static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) { struct page *page; @@ -1239,10 +1477,10 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static int __reloc_entry_gpu(struct i915_execbuffer *eb, - struct i915_vma *vma, - u64 offset, - u64 target_addr) +static bool __reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) { const unsigned int gen = eb->reloc_cache.gen; unsigned int len; @@ -1258,7 +1496,7 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, batch = reloc_gpu(eb, vma, len); if (IS_ERR(batch)) - return PTR_ERR(batch); + return false; addr = gen8_canonical_addr(vma->node.start + offset); if (gen >= 8) { @@ -1307,21 +1545,55 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, *batch++ = target_addr; } - return 0; + return true; +} + +static bool reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) +{ + if (eb->reloc_cache.vaddr) + return false; + + if (!use_reloc_gpu(vma)) + return false; + + return __reloc_entry_gpu(eb, vma, offset, target_addr); } static u64 -relocate_entry(struct i915_execbuffer *eb, - struct i915_vma *vma, +relocate_entry(struct i915_vma *vma, const struct drm_i915_gem_relocation_entry *reloc, + struct i915_execbuffer *eb, const struct i915_vma *target) { u64 target_addr = relocation_target(reloc, target); - int err; - - err = __reloc_entry_gpu(eb, vma, reloc->offset, target_addr); - if (err) - return err; + u64 offset = reloc->offset; + + if (!reloc_entry_gpu(eb, vma, offset, target_addr)) { + bool wide = eb->reloc_cache.use_64bit_reloc; + void *vaddr; + +repeat: + vaddr = reloc_vaddr(vma->obj, + &eb->reloc_cache, + offset >> PAGE_SHIFT); + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + + GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32))); + clflush_write32(vaddr + offset_in_page(offset), + lower_32_bits(target_addr), + eb->reloc_cache.vaddr); + + if (wide) { + offset += sizeof(u32); + target_addr >>= 32; + wide = false; + goto repeat; + } + } return target->node.start | UPDATE; } @@ -1386,7 +1658,8 @@ eb_relocate_entry(struct i915_execbuffer *eb, * If the relocation already has the right value in it, no * more work needs to be done. */ - if (gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) + if (!DBG_FORCE_RELOC && + gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) return 0; /* Check that the relocation address is valid... */ @@ -1418,7 +1691,7 @@ eb_relocate_entry(struct i915_execbuffer *eb, ev->flags &= ~EXEC_OBJECT_ASYNC; /* and update the user's relocation entry */ - return relocate_entry(eb, ev->vma, reloc, target->vma); + return relocate_entry(ev->vma, reloc, eb, target->vma); } static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) @@ -1456,8 +1729,10 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) * this is bad and so lockdep complains vehemently. */ copied = __copy_from_user(r, urelocs, count * sizeof(r[0])); - if (unlikely(copied)) - return -EFAULT; + if (unlikely(copied)) { + remain = -EFAULT; + goto out; + } remain -= count; do { @@ -1465,7 +1740,8 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) if (likely(offset == 0)) { } else if ((s64)offset < 0) { - return (int)offset; + remain = (int)offset; + goto out; } else { /* * Note that reporting an error now @@ -1495,8 +1771,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) } while (r++, --count); urelocs += ARRAY_SIZE(stack); } while (remain); - - return 0; +out: + reloc_cache_reset(&eb->reloc_cache); + return remain; } static int eb_relocate(struct i915_execbuffer *eb) @@ -2573,7 +2850,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.i915 = i915; eb.file = file; eb.args = args; - if (!(args->flags & I915_EXEC_NO_RELOC)) + if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC)) args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 57c14d3340cde..a49016f8ee0dc 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -37,14 +37,20 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, return err; /* 8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[0] * sizeof(u32), + 0)) { + err = -EIO; goto unpin_vma; + } /* !8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[1] * sizeof(u32), + 1)) { + err = -EIO; goto unpin_vma; + } /* Skip to the end of the cmd page */ i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1; @@ -54,9 +60,12 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, eb->reloc_cache.rq_size += i; /* Force batch chaining */ - err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[2] * sizeof(u32), + 2)) { + err = -EIO; goto unpin_vma; + } GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); -- GitLab From 50ae6c61a17ce12c81fb1aa8b1bd21c284b81768 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:42 +0200 Subject: [PATCH 0824/1494] drm/i915: Revert relocation chaining commits. This reverts commit 964a9b0f611ee ("drm/i915/gem: Use chained reloc batches") and commit 0e97fbb080553 ("drm/i915/gem: Use a single chained reloc batches for a single execbuf"). When adding ww locking to execbuf, it's hard enough to deal with a single BO that is part of relocation execution. Chaining is hard to get right, and with GPU relocation deprecated, it's best to drop this altogether, instead of trying to fix something we will remove. This is not a completely 1:1 revert, we reset rq_size to 0 in reloc_cache_init, this was from e3d291301f99 ("drm/i915/gem: Implement legacy MI_STORE_DATA_IMM"), because we don't want to break the selftests. (Daniel) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-3-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 171 ++++-------------- .../i915/gem/selftests/i915_gem_execbuffer.c | 8 +- 2 files changed, 35 insertions(+), 144 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index c6a613d92a13a..6acbd08f82f03 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -276,9 +276,7 @@ struct i915_execbuffer { bool has_fence : 1; bool needs_unfenced : 1; - struct i915_vma *target; struct i915_request *rq; - struct i915_vma *rq_vma; u32 *rq_cmd; unsigned int rq_size; } reloc_cache; @@ -973,7 +971,7 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment; cache->node.flags = 0; cache->rq = NULL; - cache->target = NULL; + cache->rq_size = 0; } static inline void *unmask_page(unsigned long p) @@ -995,122 +993,29 @@ static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) return &i915->ggtt; } -#define RELOC_TAIL 4 - -static int reloc_gpu_chain(struct reloc_cache *cache) +static void reloc_gpu_flush(struct reloc_cache *cache) { - struct intel_gt_buffer_pool_node *pool; - struct i915_request *rq = cache->rq; - struct i915_vma *batch; - u32 *cmd; - int err; - - pool = intel_gt_get_buffer_pool(rq->engine->gt, PAGE_SIZE); - if (IS_ERR(pool)) - return PTR_ERR(pool); - - batch = i915_vma_instance(pool->obj, rq->context->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_pool; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER | PIN_NONBLOCK); - if (err) - goto out_pool; - - GEM_BUG_ON(cache->rq_size + RELOC_TAIL > PAGE_SIZE / sizeof(u32)); - cmd = cache->rq_cmd + cache->rq_size; - *cmd++ = MI_ARB_CHECK; - if (cache->gen >= 8) - *cmd++ = MI_BATCH_BUFFER_START_GEN8; - else if (cache->gen >= 6) - *cmd++ = MI_BATCH_BUFFER_START; - else - *cmd++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; - *cmd++ = lower_32_bits(batch->node.start); - *cmd++ = upper_32_bits(batch->node.start); /* Always 0 for gen<8 */ - i915_gem_object_flush_map(cache->rq_vma->obj); - i915_gem_object_unpin_map(cache->rq_vma->obj); - cache->rq_vma = NULL; - - err = intel_gt_buffer_pool_mark_active(pool, rq); - if (err == 0) { - i915_vma_lock(batch); - err = i915_request_await_object(rq, batch->obj, false); - if (err == 0) - err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); - } - i915_vma_unpin(batch); - if (err) - goto out_pool; + struct drm_i915_gem_object *obj = cache->rq->batch->obj; - cmd = i915_gem_object_pin_map(batch->obj, - cache->has_llc ? - I915_MAP_FORCE_WB : - I915_MAP_FORCE_WC); - if (IS_ERR(cmd)) { - err = PTR_ERR(cmd); - goto out_pool; - } + GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32)); + cache->rq_cmd[cache->rq_size] = MI_BATCH_BUFFER_END; - /* Return with batch mapping (cmd) still pinned */ - cache->rq_cmd = cmd; - cache->rq_size = 0; - cache->rq_vma = batch; + __i915_gem_object_flush_map(obj, 0, sizeof(u32) * (cache->rq_size + 1)); + i915_gem_object_unpin_map(obj); -out_pool: - intel_gt_buffer_pool_put(pool); - return err; -} + intel_gt_chipset_flush(cache->rq->engine->gt); -static unsigned int reloc_bb_flags(const struct reloc_cache *cache) -{ - return cache->gen > 5 ? 0 : I915_DISPATCH_SECURE; -} - -static int reloc_gpu_flush(struct reloc_cache *cache) -{ - struct i915_request *rq; - int err; - - rq = fetch_and_zero(&cache->rq); - if (!rq) - return 0; - - if (cache->rq_vma) { - struct drm_i915_gem_object *obj = cache->rq_vma->obj; - - GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32)); - cache->rq_cmd[cache->rq_size++] = MI_BATCH_BUFFER_END; - - __i915_gem_object_flush_map(obj, - 0, sizeof(u32) * cache->rq_size); - i915_gem_object_unpin_map(obj); - } - - err = 0; - if (rq->engine->emit_init_breadcrumb) - err = rq->engine->emit_init_breadcrumb(rq); - if (!err) - err = rq->engine->emit_bb_start(rq, - rq->batch->node.start, - PAGE_SIZE, - reloc_bb_flags(cache)); - if (err) - i915_request_set_error_once(rq, err); - - intel_gt_chipset_flush(rq->engine->gt); - i915_request_add(rq); - - return err; + i915_request_add(cache->rq); + cache->rq = NULL; } static void reloc_cache_reset(struct reloc_cache *cache) { void *vaddr; + if (cache->rq) + reloc_gpu_flush(cache); + if (!cache->vaddr) return; @@ -1309,6 +1214,7 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) static int __reloc_gpu_alloc(struct i915_execbuffer *eb, struct intel_engine_cs *engine, + struct i915_vma *vma, unsigned int len) { struct reloc_cache *cache = &eb->reloc_cache; @@ -1331,7 +1237,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, goto out_pool; } - batch = i915_vma_instance(pool->obj, eb->context->vm, NULL); + batch = i915_vma_instance(pool->obj, vma->vm, NULL); if (IS_ERR(batch)) { err = PTR_ERR(batch); goto err_unmap; @@ -1367,6 +1273,16 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto err_request; + err = reloc_move_to_gpu(rq, vma); + if (err) + goto err_request; + + err = eb->engine->emit_bb_start(rq, + batch->node.start, PAGE_SIZE, + cache->gen > 5 ? 0 : I915_DISPATCH_SECURE); + if (err) + goto skip_request; + i915_vma_lock(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) @@ -1381,7 +1297,6 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, cache->rq = rq; cache->rq_cmd = cmd; cache->rq_size = 0; - cache->rq_vma = batch; /* Return with batch mapping (cmd) still pinned */ goto out_pool; @@ -1410,9 +1325,12 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, { struct reloc_cache *cache = &eb->reloc_cache; u32 *cmd; - int err; + + if (cache->rq_size > PAGE_SIZE/sizeof(u32) - (len + 1)) + reloc_gpu_flush(cache); if (unlikely(!cache->rq)) { + int err; struct intel_engine_cs *engine = eb->engine; if (!reloc_can_use_engine(engine)) { @@ -1421,31 +1339,11 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, return ERR_PTR(-ENODEV); } - err = __reloc_gpu_alloc(eb, engine, len); + err = __reloc_gpu_alloc(eb, engine, vma, len); if (unlikely(err)) return ERR_PTR(err); } - if (vma != cache->target) { - err = reloc_move_to_gpu(cache->rq, vma); - if (unlikely(err)) { - i915_request_set_error_once(cache->rq, err); - return ERR_PTR(err); - } - - cache->target = vma; - } - - if (unlikely(cache->rq_size + len > - PAGE_SIZE / sizeof(u32) - RELOC_TAIL)) { - err = reloc_gpu_chain(cache); - if (unlikely(err)) { - i915_request_set_error_once(cache->rq, err); - return ERR_PTR(err); - } - } - - GEM_BUG_ON(cache->rq_size + len >= PAGE_SIZE / sizeof(u32)); cmd = cache->rq_cmd + cache->rq_size; cache->rq_size += len; @@ -1793,20 +1691,15 @@ static int eb_relocate(struct i915_execbuffer *eb) /* The objects are in their final locations, apply the relocations. */ if (eb->args->flags & __EXEC_HAS_RELOC) { struct eb_vma *ev; - int flush; list_for_each_entry(ev, &eb->relocs, reloc_link) { err = eb_relocate_vma(eb, ev); if (err) - break; + return err; } - - flush = reloc_gpu_flush(&eb->reloc_cache); - if (!err) - err = flush; } - return err; + return 0; } static int eb_move_to_gpu(struct i915_execbuffer *eb) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index a49016f8ee0dc..580884cffec36 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -53,13 +53,13 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, } /* Skip to the end of the cmd page */ - i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1; + i = PAGE_SIZE / sizeof(u32) - 1; i -= eb->reloc_cache.rq_size; memset32(eb->reloc_cache.rq_cmd + eb->reloc_cache.rq_size, MI_NOOP, i); eb->reloc_cache.rq_size += i; - /* Force batch chaining */ + /* Force next batch */ if (!__reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2)) { @@ -69,9 +69,7 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); - err = reloc_gpu_flush(&eb->reloc_cache); - if (err) - goto put_rq; + reloc_gpu_flush(&eb->reloc_cache); GEM_BUG_ON(eb->reloc_cache.rq); err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, HZ / 2); -- GitLab From fd1500fcd4420eee06e2c7f3aa6067b78ac05871 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:43 +0200 Subject: [PATCH 0825/1494] Revert "drm/i915/gem: Drop relocation slowpath". This reverts commit 7dc8f1143778 ("drm/i915/gem: Drop relocation slowpath"). We need the slowpath relocation for taking ww-mutex inside the page fault handler, and we will take this mutex when pinning all objects. We also functionally revert ef398881d27d ("drm/i915/gem: Limit struct_mutex to eb_reserve"), as we need the struct_mutex in the slowpath as well, and a tiny part of 003d8b9143a6 ("drm/i915/gem: Only call eb_lookup_vma once during execbuf ioctl"). Specifically, we make the -EAGAIN handling part of fallback to slowpath again. With this, we have a proper working slowpath again, which will allow us to do fault handling with WW locks held. [mlankhorst: Adjusted for reloc_gpu_flush() changes] Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> [mlankhorst: Removed extra reloc_gpu_flush()] Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-4-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 262 +++++++++++++++++- 1 file changed, 252 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 6acbd08f82f03..e8d713f78323a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -707,7 +707,7 @@ static int eb_reserve(struct i915_execbuffer *eb) if (err) break; } - if (!(err == -ENOSPC || err == -EAGAIN)) + if (err != -ENOSPC) break; /* Resort *all* the objects into priority order */ @@ -738,13 +738,6 @@ static int eb_reserve(struct i915_execbuffer *eb) } list_splice_tail(&last, &eb->unbound); - if (err == -EAGAIN) { - mutex_unlock(&eb->i915->drm.struct_mutex); - flush_workqueue(eb->i915->mm.userptr_wq); - mutex_lock(&eb->i915->drm.struct_mutex); - continue; - } - switch (pass++) { case 0: break; @@ -1626,7 +1619,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) * we would try to acquire the struct mutex again. Obviously * this is bad and so lockdep complains vehemently. */ - copied = __copy_from_user(r, urelocs, count * sizeof(r[0])); + pagefault_disable(); + copied = __copy_from_user_inatomic(r, urelocs, count * sizeof(r[0])); + pagefault_enable(); if (unlikely(copied)) { remain = -EFAULT; goto out; @@ -1674,6 +1669,250 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) return remain; } +static int +eb_relocate_vma_slow(struct i915_execbuffer *eb, struct eb_vma *ev) +{ + const struct drm_i915_gem_exec_object2 *entry = ev->exec; + struct drm_i915_gem_relocation_entry *relocs = + u64_to_ptr(typeof(*relocs), entry->relocs_ptr); + unsigned int i; + int err; + + for (i = 0; i < entry->relocation_count; i++) { + u64 offset = eb_relocate_entry(eb, ev, &relocs[i]); + + if ((s64)offset < 0) { + err = (int)offset; + goto err; + } + } + err = 0; +err: + reloc_cache_reset(&eb->reloc_cache); + return err; +} + +static int check_relocations(const struct drm_i915_gem_exec_object2 *entry) +{ + const char __user *addr, *end; + unsigned long size; + char __maybe_unused c; + + size = entry->relocation_count; + if (size == 0) + return 0; + + if (size > N_RELOC(ULONG_MAX)) + return -EINVAL; + + addr = u64_to_user_ptr(entry->relocs_ptr); + size *= sizeof(struct drm_i915_gem_relocation_entry); + if (!access_ok(addr, size)) + return -EFAULT; + + end = addr + size; + for (; addr < end; addr += PAGE_SIZE) { + int err = __get_user(c, addr); + if (err) + return err; + } + return __get_user(c, end - 1); +} + +static int eb_copy_relocations(const struct i915_execbuffer *eb) +{ + struct drm_i915_gem_relocation_entry *relocs; + const unsigned int count = eb->buffer_count; + unsigned int i; + int err; + + for (i = 0; i < count; i++) { + const unsigned int nreloc = eb->exec[i].relocation_count; + struct drm_i915_gem_relocation_entry __user *urelocs; + unsigned long size; + unsigned long copied; + + if (nreloc == 0) + continue; + + err = check_relocations(&eb->exec[i]); + if (err) + goto err; + + urelocs = u64_to_user_ptr(eb->exec[i].relocs_ptr); + size = nreloc * sizeof(*relocs); + + relocs = kvmalloc_array(size, 1, GFP_KERNEL); + if (!relocs) { + err = -ENOMEM; + goto err; + } + + /* copy_from_user is limited to < 4GiB */ + copied = 0; + do { + unsigned int len = + min_t(u64, BIT_ULL(31), size - copied); + + if (__copy_from_user((char *)relocs + copied, + (char __user *)urelocs + copied, + len)) + goto end; + + copied += len; + } while (copied < size); + + /* + * As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + if (!user_access_begin(urelocs, size)) + goto end; + + for (copied = 0; copied < nreloc; copied++) + unsafe_put_user(-1, + &urelocs[copied].presumed_offset, + end_user); + user_access_end(); + + eb->exec[i].relocs_ptr = (uintptr_t)relocs; + } + + return 0; + +end_user: + user_access_end(); +end: + kvfree(relocs); + err = -EFAULT; +err: + while (i--) { + relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr); + if (eb->exec[i].relocation_count) + kvfree(relocs); + } + return err; +} + +static int eb_prefault_relocations(const struct i915_execbuffer *eb) +{ + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + int err; + + err = check_relocations(&eb->exec[i]); + if (err) + return err; + } + + return 0; +} + +static noinline int eb_relocate_slow(struct i915_execbuffer *eb) +{ + bool have_copy = false; + struct eb_vma *ev; + int err = 0; + +repeat: + if (signal_pending(current)) { + err = -ERESTARTSYS; + goto out; + } + + /* + * We take 3 passes through the slowpatch. + * + * 1 - we try to just prefault all the user relocation entries and + * then attempt to reuse the atomic pagefault disabled fast path again. + * + * 2 - we copy the user entries to a local buffer here outside of the + * local and allow ourselves to wait upon any rendering before + * relocations + * + * 3 - we already have a local copy of the relocation entries, but + * were interrupted (EAGAIN) whilst waiting for the objects, try again. + */ + if (!err) { + err = eb_prefault_relocations(eb); + } else if (!have_copy) { + err = eb_copy_relocations(eb); + have_copy = err == 0; + } else { + cond_resched(); + err = 0; + } + + flush_workqueue(eb->i915->mm.userptr_wq); + + if (err) + goto out; + + err = mutex_lock_interruptible(&eb->i915->drm.struct_mutex); + if (err) + goto out; + + list_for_each_entry(ev, &eb->relocs, reloc_link) { + if (!have_copy) { + pagefault_disable(); + err = eb_relocate_vma(eb, ev); + pagefault_enable(); + if (err) + break; + } else { + err = eb_relocate_vma_slow(eb, ev); + if (err) + break; + } + } + + mutex_unlock(&eb->i915->drm.struct_mutex); + if (err && !have_copy) + goto repeat; + + if (err) + goto err; + + /* + * Leave the user relocations as are, this is the painfully slow path, + * and we want to avoid the complication of dropping the lock whilst + * having buffers reserved in the aperture and so causing spurious + * ENOSPC for random operations. + */ + +err: + if (err == -EAGAIN) + goto repeat; + +out: + if (have_copy) { + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + const struct drm_i915_gem_exec_object2 *entry = + &eb->exec[i]; + struct drm_i915_gem_relocation_entry *relocs; + + if (!entry->relocation_count) + continue; + + relocs = u64_to_ptr(typeof(*relocs), entry->relocs_ptr); + kvfree(relocs); + } + } + + return err; +} + static int eb_relocate(struct i915_execbuffer *eb) { int err; @@ -1695,8 +1934,11 @@ static int eb_relocate(struct i915_execbuffer *eb) list_for_each_entry(ev, &eb->relocs, reloc_link) { err = eb_relocate_vma(eb, ev); if (err) - return err; + break; } + + if (err) + return eb_relocate_slow(eb); } return 0; -- GitLab From 8ae275c288d3629cd7a2d0191c09f9c9edcec4c0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:44 +0200 Subject: [PATCH 0826/1494] Revert "drm/i915/gem: Split eb_vma into its own allocation" This reverts commit 0f1dd02295f3 ("drm/i915/gem: Split eb_vma into its own allocation") and also moves all unreserving to a single place at the end, which is a minor simplification. With the WW locking, we will drop all references only at the end when unlocking, so refcounting can now be removed. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-5-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 124 +++++++----------- 1 file changed, 51 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index e8d713f78323a..ccaaf9e599a0d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -41,11 +41,6 @@ struct eb_vma { u32 handle; }; -struct eb_vma_array { - struct kref kref; - struct eb_vma vma[]; -}; - enum { FORCE_CPU_RELOC = 1, FORCE_GTT_RELOC, @@ -58,6 +53,7 @@ enum { #define __EXEC_OBJECT_NEEDS_MAP BIT(29) #define __EXEC_OBJECT_NEEDS_BIAS BIT(28) #define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 28) /* all of the above */ +#define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE) #define __EXEC_HAS_RELOC BIT(31) #define __EXEC_INTERNAL_FLAGS (~0u << 31) @@ -295,7 +291,6 @@ struct i915_execbuffer { */ int lut_size; struct hlist_head *buckets; /** ht for relocation handles */ - struct eb_vma_array *array; struct eb_fence *fences; unsigned long num_fences; @@ -308,62 +303,8 @@ static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) eb->args->batch_len); } -static struct eb_vma_array *eb_vma_array_create(unsigned int count) -{ - struct eb_vma_array *arr; - - arr = kvmalloc(struct_size(arr, vma, count), GFP_KERNEL | __GFP_NOWARN); - if (!arr) - return NULL; - - kref_init(&arr->kref); - arr->vma[0].vma = NULL; - - return arr; -} - -static inline void eb_unreserve_vma(struct eb_vma *ev) -{ - struct i915_vma *vma = ev->vma; - - if (unlikely(ev->flags & __EXEC_OBJECT_HAS_FENCE)) - __i915_vma_unpin_fence(vma); - - if (ev->flags & __EXEC_OBJECT_HAS_PIN) - __i915_vma_unpin(vma); - - ev->flags &= ~(__EXEC_OBJECT_HAS_PIN | - __EXEC_OBJECT_HAS_FENCE); -} - -static void eb_vma_array_destroy(struct kref *kref) -{ - struct eb_vma_array *arr = container_of(kref, typeof(*arr), kref); - struct eb_vma *ev = arr->vma; - - while (ev->vma) { - eb_unreserve_vma(ev); - i915_vma_put(ev->vma); - ev++; - } - - kvfree(arr); -} - -static void eb_vma_array_put(struct eb_vma_array *arr) -{ - kref_put(&arr->kref, eb_vma_array_destroy); -} - static int eb_create(struct i915_execbuffer *eb) { - /* Allocate an extra slot for use by the command parser + sentinel */ - eb->array = eb_vma_array_create(eb->buffer_count + 2); - if (!eb->array) - return -ENOMEM; - - eb->vma = eb->array->vma; - if (!(eb->args->flags & I915_EXEC_HANDLE_LUT)) { unsigned int size = 1 + ilog2(eb->buffer_count); @@ -397,10 +338,8 @@ static int eb_create(struct i915_execbuffer *eb) break; } while (--size); - if (unlikely(!size)) { - eb_vma_array_put(eb->array); + if (unlikely(!size)) return -ENOMEM; - } eb->lut_size = size; } else { @@ -511,6 +450,26 @@ eb_pin_vma(struct i915_execbuffer *eb, return !eb_vma_misplaced(entry, vma, ev->flags); } +static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags) +{ + GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN)); + + if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE)) + __i915_vma_unpin_fence(vma); + + __i915_vma_unpin(vma); +} + +static inline void +eb_unreserve_vma(struct eb_vma *ev) +{ + if (!(ev->flags & __EXEC_OBJECT_HAS_PIN)) + return; + + __eb_unreserve_vma(ev->vma, ev->flags); + ev->flags &= ~__EXEC_OBJECT_RESERVED; +} + static int eb_validate_vma(struct i915_execbuffer *eb, struct drm_i915_gem_exec_object2 *entry, @@ -933,13 +892,31 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } +static void eb_release_vmas(const struct i915_execbuffer *eb) +{ + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + struct eb_vma *ev = &eb->vma[i]; + struct i915_vma *vma = ev->vma; + + if (!vma) + break; + + eb->vma[i].vma = NULL; + + if (ev->flags & __EXEC_OBJECT_HAS_PIN) + __eb_unreserve_vma(vma, ev->flags); + + i915_vma_put(vma); + } +} + static void eb_destroy(const struct i915_execbuffer *eb) { GEM_BUG_ON(eb->reloc_cache.rq); - if (eb->array) - eb_vma_array_put(eb->array); - if (eb->lut_size > 0) kfree(eb->buckets); } @@ -2021,12 +1998,9 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) err = i915_vma_move_to_active(vma, eb->request, flags); i915_vma_unlock(vma); - eb_unreserve_vma(ev); } ww_acquire_fini(&acquire); - eb_vma_array_put(fetch_and_zero(&eb->array)); - if (unlikely(err)) goto err_skip; @@ -2323,7 +2297,6 @@ static int eb_parse(struct i915_execbuffer *eb) eb->vma[eb->buffer_count].vma = i915_vma_get(shadow); eb->vma[eb->buffer_count].flags = __EXEC_OBJECT_HAS_PIN; eb->batch = &eb->vma[eb->buffer_count++]; - eb->vma[eb->buffer_count].vma = NULL; eb->trampoline = trampoline; eb->batch_start_offset = 0; @@ -2989,6 +2962,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; + eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); + eb.vma[0].vma = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3198,6 +3173,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (batch->private) intel_gt_buffer_pool_put(batch->private); err_vma: + if (eb.exec) + eb_release_vmas(&eb); if (eb.trampoline) i915_vma_unpin(eb.trampoline); eb_unpin_engine(&eb); @@ -3217,7 +3194,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, static size_t eb_element_size(void) { - return sizeof(struct drm_i915_gem_exec_object2); + return sizeof(struct drm_i915_gem_exec_object2) + sizeof(struct eb_vma); } static bool check_buffer_count(size_t count) @@ -3273,7 +3250,7 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, /* Copy in the exec list from userland */ exec_list = kvmalloc_array(count, sizeof(*exec_list), __GFP_NOWARN | GFP_KERNEL); - exec2_list = kvmalloc_array(count, eb_element_size(), + exec2_list = kvmalloc_array(count + 1, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec_list == NULL || exec2_list == NULL) { drm_dbg(&i915->drm, @@ -3350,7 +3327,8 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, if (err) return err; - exec2_list = kvmalloc_array(count, eb_element_size(), + /* Allocate an extra slot for use by the command parser */ + exec2_list = kvmalloc_array(count + 1, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec2_list == NULL) { drm_dbg(&i915->drm, "Failed to allocate exec list for %zd buffers\n", -- GitLab From 80f0b679d6f0683f23cf98a511af3e44dd509472 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:45 +0200 Subject: [PATCH 0827/1494] drm/i915: Add an implementation for i915_gem_ww_ctx locking, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i915_gem_ww_ctx is used to lock all gem bo's for pinning and memory eviction. We don't use it yet, but lets start adding the definition first. To use it, we have to pass a non-NULL ww to gem_object_lock, and don't unlock directly. It is done in i915_gem_ww_ctx_fini. Changes since v1: - Change ww_ctx and obj order in locking functions (Jonas Lahtinen) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-6-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 4 +- .../gpu/drm/i915/gem/i915_gem_client_blt.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 10 ++-- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_object.h | 38 +++++++++++--- .../gpu/drm/i915/gem/i915_gem_object_types.h | 9 ++++ drivers/gpu/drm/i915/gem/i915_gem_pm.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_tiling.c | 2 +- .../gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../i915/gem/selftests/i915_gem_client_blt.c | 2 +- .../i915/gem/selftests/i915_gem_coherency.c | 10 ++-- .../drm/i915/gem/selftests/i915_gem_context.c | 4 +- .../drm/i915/gem/selftests/i915_gem_mman.c | 4 +- .../drm/i915/gem/selftests/i915_gem_phys.c | 2 +- .../gpu/drm/i915/gt/selftest_workarounds.c | 2 +- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 52 +++++++++++++++++-- drivers/gpu/drm/i915/i915_gem.h | 11 ++++ drivers/gpu/drm/i915/selftests/i915_gem.c | 41 +++++++++++++++ drivers/gpu/drm/i915/selftests/i915_vma.c | 2 +- .../drm/i915/selftests/intel_memory_region.c | 2 +- 22 files changed, 170 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7d50b7177d402..27c0a2140441d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2311,7 +2311,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) { - i915_gem_object_lock(vma->obj); + i915_gem_object_lock(vma->obj, NULL); if (flags & PLANE_HAS_FENCE) i915_vma_unpin_fence(vma); i915_gem_object_unpin_from_display_plane(vma); @@ -17194,7 +17194,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, if (!intel_fb->frontbuffer) return -ENOMEM; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); tiling = i915_gem_object_get_tiling(obj); stride = i915_gem_object_get_stride(obj); i915_gem_object_unlock(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index 947c8aa8e13ed..a85907f29c538 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -288,7 +288,7 @@ int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj, dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0); i915_sw_fence_init(&work->wait, clear_pages_work_notify); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_sw_fence_await_reservation(&work->wait, obj->base.resv, NULL, true, 0, I915_FENCE_GFP); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 2679380159fc7..27fddc22a7c6f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -128,7 +128,7 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire if (err) return err; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out; @@ -149,7 +149,7 @@ static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direct if (err) return err; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 7f76fc68f498a..c0acfc97fae30 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -32,7 +32,7 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) if (!i915_gem_object_is_framebuffer(obj)) return; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); __i915_gem_object_flush_for_display(obj); i915_gem_object_unlock(obj); } @@ -197,7 +197,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; @@ -536,7 +536,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (err) goto out; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out_unpin; @@ -576,7 +576,7 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; @@ -630,7 +630,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index ccaaf9e599a0d..51395a0ceb159 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1076,7 +1076,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (use_cpu_reloc(cache, obj)) return NULL; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index e5b9276d254c0..4884591433664 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -110,20 +110,44 @@ i915_gem_object_put(struct drm_i915_gem_object *obj) #define assert_object_held(obj) dma_resv_assert_held((obj)->base.resv) -static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj) +static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + bool intr) { - dma_resv_lock(obj->base.resv, NULL); + int ret; + + if (intr) + ret = dma_resv_lock_interruptible(obj->base.resv, ww ? &ww->ctx : NULL); + else + ret = dma_resv_lock(obj->base.resv, ww ? &ww->ctx : NULL); + + if (!ret && ww) + list_add_tail(&obj->obj_link, &ww->obj_list); + if (ret == -EALREADY) + ret = 0; + + if (ret == -EDEADLK) + ww->contended = obj; + + return ret; } -static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj) +static inline int i915_gem_object_lock(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww) { - return dma_resv_trylock(obj->base.resv); + return __i915_gem_object_lock(obj, ww, ww && ww->intr); } -static inline int -i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj) +static inline int i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww) { - return dma_resv_lock_interruptible(obj->base.resv, NULL); + WARN_ON(ww && !ww->intr); + return __i915_gem_object_lock(obj, ww, true); +} + +static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj) +{ + return dma_resv_trylock(obj->base.resv); } static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index d0847d7896f95..b5c15557cc87b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -123,6 +123,15 @@ struct drm_i915_gem_object { struct list_head lut_list; spinlock_t lut_lock; /* guards lut_list */ + /** + * @obj_link: Link into @i915_gem_ww_ctx.obj_list + * + * When we lock this object through i915_gem_object_lock() with a + * context, we add it to the list to ensure we can unlock everything + * when i915_gem_ww_ctx_backoff() or i915_gem_ww_ctx_fini() are called. + */ + struct list_head obj_link; + /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; union { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index 3d215164dd5a4..40d3e40500fa0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -84,7 +84,7 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) spin_unlock_irqrestore(&i915->mm.obj_lock, flags); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); drm_WARN_ON(&i915->drm, i915_gem_object_set_to_gtt_domain(obj, false)); i915_gem_object_unlock(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index ff72ee2fd9cd8..ffcaee74a2493 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -249,7 +249,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, * whilst executing a fenced command for an untiled object. */ - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); if (i915_gem_object_is_framebuffer(obj)) { i915_gem_object_unlock(obj); return -EBUSY; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index e2f3d014acb24..68c3631f3746c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -947,7 +947,7 @@ static int gpu_write(struct intel_context *ce, { int err; - i915_gem_object_lock(vma->obj); + i915_gem_object_lock(vma->obj, NULL); err = i915_gem_object_set_to_gtt_domain(vma->obj, true); i915_gem_object_unlock(vma->obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index 299c29e9ad86a..4e36d4897ea65 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -75,7 +75,7 @@ static int __igt_client_fill(struct intel_engine_cs *engine) if (err) goto err_unpin; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 87d7d8aa080f7..1de2959b153c5 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -82,7 +82,7 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v) u32 __iomem *map; int err = 0; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) @@ -115,7 +115,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) u32 __iomem *map; int err = 0; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, false); i915_gem_object_unlock(ctx->obj); if (err) @@ -147,7 +147,7 @@ static int wc_set(struct context *ctx, unsigned long offset, u32 v) u32 *map; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_wc_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) @@ -170,7 +170,7 @@ static int wc_get(struct context *ctx, unsigned long offset, u32 *v) u32 *map; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_wc_domain(ctx->obj, false); i915_gem_object_unlock(ctx->obj); if (err) @@ -193,7 +193,7 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) u32 *cs; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index d176b015353fb..52af9a52b7437 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -950,7 +950,7 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return PTR_ERR(vma); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, false); i915_gem_object_unlock(obj); if (err) @@ -1709,7 +1709,7 @@ static int read_from_scratch(struct i915_gem_context *ctx, i915_request_add(rq); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 9c7402ce5bf9c..9fb95a45bcad3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -103,7 +103,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { @@ -188,7 +188,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj, GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c index 34932871b3a59..a94243dc4c5cf 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c @@ -44,7 +44,7 @@ static int mock_phys_object(void *arg) } /* Make the object dirty so that put_pages must do copy back the data */ - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index febc9e6692bac..61a0532d0f3d3 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -214,7 +214,7 @@ static int check_whitelist(struct i915_gem_context *ctx, return PTR_ERR(results); err = 0; - i915_gem_object_lock(results); + i915_gem_object_lock(results, NULL); intel_wedge_on_timeout(&wedge, engine->gt, HZ / 5) /* safety net! */ err = i915_gem_object_set_to_cpu_domain(results, false); i915_gem_object_unlock(results); diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index f1940939260aa..943c8d2327035 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -2982,7 +2982,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) goto put_obj; } - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); ret = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e1de50780ed50..4bc8fdb94019e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -420,7 +420,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj, GEM_BUG_ON(!drm_mm_node_allocated(&node)); } - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) goto out_unpin; @@ -619,7 +619,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, GEM_BUG_ON(!drm_mm_node_allocated(&node)); } - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) goto out_unpin; @@ -1290,7 +1290,7 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) i915_gem_drain_freed_objects(i915); list_for_each_entry(obj, &i915->mm.shrink_list, mm.link) { - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); drm_WARN_ON(&i915->drm, i915_gem_object_set_to_cpu_domain(obj, true)); i915_gem_object_unlock(obj); @@ -1326,6 +1326,52 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) return ret; } +void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr) +{ + ww_acquire_init(&ww->ctx, &reservation_ww_class); + INIT_LIST_HEAD(&ww->obj_list); + ww->intr = intr; + ww->contended = NULL; +} + +static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) +{ + struct drm_i915_gem_object *obj; + + while ((obj = list_first_entry_or_null(&ww->obj_list, struct drm_i915_gem_object, obj_link))) { + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); + } +} + +void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww) +{ + i915_gem_ww_ctx_unlock_all(ww); + WARN_ON(ww->contended); + ww_acquire_fini(&ww->ctx); +} + +int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww) +{ + int ret = 0; + + if (WARN_ON(!ww->contended)) + return -EINVAL; + + i915_gem_ww_ctx_unlock_all(ww); + if (ww->intr) + ret = dma_resv_lock_slow_interruptible(ww->contended->base.resv, &ww->ctx); + else + dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx); + + if (!ret) + list_add_tail(&ww->contended->obj_link, &ww->obj_list); + + ww->contended = NULL; + + return ret; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_gem_device.c" #include "selftests/i915_gem.c" diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index f333e88a2b6ed..427ebd02fceb0 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -116,4 +116,15 @@ static inline bool __tasklet_is_scheduled(struct tasklet_struct *t) return test_bit(TASKLET_STATE_SCHED, &t->state); } +struct i915_gem_ww_ctx { + struct ww_acquire_ctx ctx; + struct list_head obj_list; + bool intr; + struct drm_i915_gem_object *contended; +}; + +void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr); +void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); +int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); + #endif /* __I915_GEM_H__ */ diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 88d400b9df88c..23a6132c5f4e8 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -199,11 +199,52 @@ static int igt_gem_hibernate(void *arg) return err; } +static int igt_gem_ww_ctx(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj, *obj2; + struct i915_gem_ww_ctx ww; + int err = 0; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + obj2 = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto put1; + } + + i915_gem_ww_ctx_init(&ww, true); +retry: + /* Lock the objects, twice for good measure (-EALREADY handling) */ + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_gem_object_lock_interruptible(obj, &ww); + if (!err) + err = i915_gem_object_lock_interruptible(obj2, &ww); + if (!err) + err = i915_gem_object_lock(obj2, &ww); + + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + i915_gem_object_put(obj2); +put1: + i915_gem_object_put(obj); + return err; +} + int i915_gem_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_gem_suspend), SUBTEST(igt_gem_hibernate), + SUBTEST(igt_gem_ww_ctx), }; if (intel_gt_is_wedged(&i915->gt)) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index af89c7fc8f593..88c5e9acb84c7 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -892,7 +892,7 @@ static int igt_vma_remapped_gtt(void *arg) unsigned int x, y; int err; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 741270fcb6b99..93a38a3235843 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -509,7 +509,7 @@ static int igt_lmem_write_cpu(void *arg) if (err) goto out_unpin; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_wc_domain(obj, true); i915_gem_object_unlock(obj); if (err) -- GitLab From 1af343cdc1971ff953f08f9dcf0efad464cf057f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:46 +0200 Subject: [PATCH 0828/1494] drm/i915: Remove locking from i915_gem_object_prepare_read/write Execbuffer submission will perform its own WW locking, and we cannot rely on the implicit lock there. This also makes it clear that the GVT code will get a lockdep splat when multiple batchbuffer shadows need to be performed in the same instance, fix that up. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-7-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 20 ++++++------------- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 13 ++++++++++-- drivers/gpu/drm/i915/gem/i915_gem_object.h | 1 - .../gpu/drm/i915/gem/selftests/huge_pages.c | 5 ++++- .../i915/gem/selftests/i915_gem_coherency.c | 14 +++++++++---- .../drm/i915/gem/selftests/i915_gem_context.c | 12 ++++++++--- drivers/gpu/drm/i915/gvt/cmd_parser.c | 1 + drivers/gpu/drm/i915/i915_gem.c | 20 +++++++++++++++++-- 8 files changed, 59 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index c0acfc97fae30..8ebceebd11b09 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -576,19 +576,17 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; + assert_object_held(obj); ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); if (ret) - goto err_unlock; + return ret; ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_unlock; + return ret; if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ || !static_cpu_has(X86_FEATURE_CLFLUSH)) { @@ -616,8 +614,6 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj, err_unpin: i915_gem_object_unpin_pages(obj); -err_unlock: - i915_gem_object_unlock(obj); return ret; } @@ -630,20 +626,18 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; + assert_object_held(obj); ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT); if (ret) - goto err_unlock; + return ret; ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_unlock; + return ret; if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE || !static_cpu_has(X86_FEATURE_CLFLUSH)) { @@ -680,7 +674,5 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, err_unpin: i915_gem_object_unpin_pages(obj); -err_unlock: - i915_gem_object_unlock(obj); return ret; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 51395a0ceb159..ac2001f10b61a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -991,11 +991,14 @@ static void reloc_cache_reset(struct reloc_cache *cache) vaddr = unmask_page(cache->vaddr); if (cache->vaddr & KMAP) { + struct drm_i915_gem_object *obj = + (struct drm_i915_gem_object *)cache->node.mm; if (cache->vaddr & CLFLUSH_AFTER) mb(); kunmap_atomic(vaddr); - i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm); + i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); } else { struct i915_ggtt *ggtt = cache_to_ggtt(cache); @@ -1031,10 +1034,16 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, unsigned int flushes; int err; - err = i915_gem_object_prepare_write(obj, &flushes); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) return ERR_PTR(err); + err = i915_gem_object_prepare_write(obj, &flushes); + if (err) { + i915_gem_object_unlock(obj); + return ERR_PTR(err); + } + BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 4884591433664..45d79d75e73a2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -432,7 +432,6 @@ static inline void i915_gem_object_finish_access(struct drm_i915_gem_object *obj) { i915_gem_object_unpin_pages(obj); - i915_gem_object_unlock(obj); } static inline struct intel_engine_cs * diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 68c3631f3746c..5daf4a2be422a 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -964,9 +964,10 @@ __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val) unsigned long n; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_read(obj, &needs_flush); if (err) - return err; + goto err_unlock; for (n = 0; n < obj->base.size >> PAGE_SHIFT; ++n) { u32 *ptr = kmap_atomic(i915_gem_object_get_page(obj, n)); @@ -986,6 +987,8 @@ __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val) } i915_gem_object_finish_access(obj); +err_unlock: + i915_gem_object_unlock(obj); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 1de2959b153c5..dcdfc396f2f84 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -27,9 +27,10 @@ static int cpu_set(struct context *ctx, unsigned long offset, u32 v) u32 *cpu; int err; + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_prepare_write(ctx->obj, &needs_clflush); if (err) - return err; + goto out; page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT); map = kmap_atomic(page); @@ -46,7 +47,9 @@ static int cpu_set(struct context *ctx, unsigned long offset, u32 v) kunmap_atomic(map); i915_gem_object_finish_access(ctx->obj); - return 0; +out: + i915_gem_object_unlock(ctx->obj); + return err; } static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) @@ -57,9 +60,10 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) u32 *cpu; int err; + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_prepare_read(ctx->obj, &needs_clflush); if (err) - return err; + goto out; page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT); map = kmap_atomic(page); @@ -73,7 +77,9 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) kunmap_atomic(map); i915_gem_object_finish_access(ctx->obj); - return 0; +out: + i915_gem_object_unlock(ctx->obj); + return err; } static int gtt_set(struct context *ctx, unsigned long offset, u32 v) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 52af9a52b7437..9160a335c684c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -461,9 +461,10 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) unsigned int n, m, need_flush; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_write(obj, &need_flush); if (err) - return err; + goto out; for (n = 0; n < real_page_count(obj); n++) { u32 *map; @@ -479,7 +480,9 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) i915_gem_object_finish_access(obj); obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; obj->write_domain = 0; - return 0; +out: + i915_gem_object_unlock(obj); + return err; } static noinline int cpu_check(struct drm_i915_gem_object *obj, @@ -488,9 +491,10 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj, unsigned int n, m, needs_flush; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_read(obj, &needs_flush); if (err) - return err; + goto out_unlock; for (n = 0; n < real_page_count(obj); n++) { u32 *map; @@ -527,6 +531,8 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj, } i915_gem_object_finish_access(obj); +out_unlock: + i915_gem_object_unlock(obj); return err; } diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 943c8d2327035..d0a599b51bfed 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1923,6 +1923,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) if (ret) goto err_unmap; + i915_gem_object_unlock(bb->obj); INIT_LIST_HEAD(&bb->list); list_add(&bb->list, &s->workload->shadow_bb); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4bc8fdb94019e..55158e487a7f4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -335,12 +335,20 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj, u64 remain; int ret; - ret = i915_gem_object_prepare_read(obj, &needs_clflush); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; + ret = i915_gem_object_prepare_read(obj, &needs_clflush); + if (ret) { + i915_gem_object_unlock(obj); + return ret; + } + fence = i915_gem_object_lock_fence(obj); i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); + if (!fence) return -ENOMEM; @@ -734,12 +742,20 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj, u64 remain; int ret; - ret = i915_gem_object_prepare_write(obj, &needs_clflush); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; + ret = i915_gem_object_prepare_write(obj, &needs_clflush); + if (ret) { + i915_gem_object_unlock(obj); + return ret; + } + fence = i915_gem_object_lock_fence(obj); i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); + if (!fence) return -ENOMEM; -- GitLab From 8e4ba491b0ba6fef69270d3c4e48fc517096ef41 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:47 +0200 Subject: [PATCH 0829/1494] drm/i915: Parse command buffer earlier in eb_relocate(slow) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to introduce backoff logic, but we need to lock the pool object as well for command parsing. Because of this, we will need backoff logic for the engine pool obj, move the batch validation up slightly to eb_lookup_vmas, and the actual command parsing in a separate function which can get called from execbuf relocation fast and slowpath. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-8-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index ac2001f10b61a..c34e55cff73d5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -296,6 +296,8 @@ struct i915_execbuffer { unsigned long num_fences; }; +static int eb_parse(struct i915_execbuffer *eb); + static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { return intel_engine_requires_cmd_parser(eb->engine) || @@ -843,6 +845,7 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle) static int eb_lookup_vmas(struct i915_execbuffer *eb) { + struct drm_i915_private *i915 = eb->i915; unsigned int batch = eb_batch_index(eb); unsigned int i; int err = 0; @@ -856,18 +859,37 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) vma = eb_lookup_vma(eb, eb->exec[i].handle); if (IS_ERR(vma)) { err = PTR_ERR(vma); - break; + goto err; } err = eb_validate_vma(eb, &eb->exec[i], vma); if (unlikely(err)) { i915_vma_put(vma); - break; + goto err; } eb_add_vma(eb, i, batch, vma); } + if (unlikely(eb->batch->flags & EXEC_OBJECT_WRITE)) { + drm_dbg(&i915->drm, + "Attempting to use self-modifying batch buffer\n"); + return -EINVAL; + } + + if (range_overflows_t(u64, + eb->batch_start_offset, eb->batch_len, + eb->batch->vma->size)) { + drm_dbg(&i915->drm, "Attempting to use out-of-bounds batch\n"); + return -EINVAL; + } + + if (eb->batch_len == 0) + eb->batch_len = eb->batch->vma->size - eb->batch_start_offset; + + return 0; + +err: eb->vma[i].vma = NULL; return err; } @@ -1802,7 +1824,7 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) return 0; } -static noinline int eb_relocate_slow(struct i915_execbuffer *eb) +static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) { bool have_copy = false; struct eb_vma *ev; @@ -1867,6 +1889,11 @@ static noinline int eb_relocate_slow(struct i915_execbuffer *eb) if (err) goto err; + /* as last step, parse the command buffer */ + err = eb_parse(eb); + if (err) + goto err; + /* * Leave the user relocations as are, this is the painfully slow path, * and we want to avoid the complication of dropping the lock whilst @@ -1899,7 +1926,7 @@ static noinline int eb_relocate_slow(struct i915_execbuffer *eb) return err; } -static int eb_relocate(struct i915_execbuffer *eb) +static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; @@ -1924,10 +1951,10 @@ static int eb_relocate(struct i915_execbuffer *eb) } if (err) - return eb_relocate_slow(eb); + return eb_relocate_parse_slow(eb); } - return 0; + return eb_parse(eb); } static int eb_move_to_gpu(struct i915_execbuffer *eb) @@ -3045,7 +3072,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_context; - err = eb_relocate(&eb); + err = eb_relocate_parse(&eb); if (err) { /* * If the user expects the execobject.offset and @@ -3058,33 +3085,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_vma; } - if (unlikely(eb.batch->flags & EXEC_OBJECT_WRITE)) { - drm_dbg(&i915->drm, - "Attempting to use self-modifying batch buffer\n"); - err = -EINVAL; - goto err_vma; - } - - if (range_overflows_t(u64, - eb.batch_start_offset, eb.batch_len, - eb.batch->vma->size)) { - drm_dbg(&i915->drm, "Attempting to use out-of-bounds batch\n"); - err = -EINVAL; - goto err_vma; - } - - if (eb.batch_len == 0) - eb.batch_len = eb.batch->vma->size - eb.batch_start_offset; - - err = eb_parse(&eb); - if (err) - goto err_vma; - /* * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. * hsw should have this fixed, but bdw mucks it up again. */ - batch = eb.batch->vma; if (eb.batch_flags & I915_DISPATCH_SECURE) { struct i915_vma *vma; @@ -3098,13 +3102,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, * fitting due to fragmentation. * So this is actually safe. */ - vma = i915_gem_object_ggtt_pin(batch->obj, NULL, 0, 0, 0); + vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { err = PTR_ERR(vma); goto err_parse; } batch = vma; + } else { + batch = eb.batch->vma; } /* All GPU relocation batches must be submitted prior to the user rq */ -- GitLab From c43ce12328df0770ce899feabdf9c430c54c766a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:48 +0200 Subject: [PATCH 0830/1494] drm/i915: Use per object locking in execbuf, v12. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we changed execbuf submission slightly to allow us to do all pinning in one place, we can now simply add ww versions on top of struct_mutex. All we have to do is a separate path for -EDEADLK handling, which needs to unpin all gem bo's before dropping the lock, then starting over. This finally allows us to do parallel submission, but because not all of the pinning code uses the ww ctx yet, we cannot completely drop struct_mutex yet. Changes since v1: - Keep struct_mutex for now. :( Changes since v2: - Make sure we always lock the ww context in slowpath. Changes since v3: - Don't call __eb_unreserve_vma in eb_move_to_gpu now; this can be done on normal unlock path. - Unconditionally release vmas and context. Changes since v4: - Rebased on top of struct_mutex reduction. Changes since v5: - Remove training wheels. Changes since v6: - Fix accidentally broken -ENOSPC handling. Changes since v7: - Handle gt buffer pool better. Changes since v8: - Properly clear variables, to make -EDEADLK handling not BUG. Change since v9: - Fix unpinning fence on pnv and below. Changes since v10: - Make relocation gpu chaining working again. Changes since v11: - Remove relocation chaining, pain to make it work. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-9-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 363 +++++++++++------- .../i915/gem/selftests/i915_gem_execbuffer.c | 62 +-- drivers/gpu/drm/i915/i915_gem.c | 6 + drivers/gpu/drm/i915/i915_gem.h | 1 + 4 files changed, 262 insertions(+), 170 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index c34e55cff73d5..13b996830e25d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -257,6 +257,8 @@ struct i915_execbuffer { /** list of vma that have execobj.relocation_count */ struct list_head relocs; + struct i915_gem_ww_ctx ww; + /** * Track the most recently used object for relocations, as we * frequently have to perform multiple relocations within the same @@ -275,14 +277,18 @@ struct i915_execbuffer { struct i915_request *rq; u32 *rq_cmd; unsigned int rq_size; + struct intel_gt_buffer_pool_node *pool; } reloc_cache; + struct intel_gt_buffer_pool_node *reloc_pool; /** relocation pool for -EDEADLK handling */ + u64 invalid_flags; /** Set of execobj.flags that are invalid */ u32 context_flags; /** Set of execobj.flags to insert from the ctx */ u32 batch_start_offset; /** Location within object of batch */ u32 batch_len; /** Length of batch within object */ u32 batch_flags; /** Flags composed for emit_bb_start() */ + struct intel_gt_buffer_pool_node *batch_pool; /** pool node for batch buffer */ /** * Indicate either the size of the hastable used to resolve @@ -452,23 +458,16 @@ eb_pin_vma(struct i915_execbuffer *eb, return !eb_vma_misplaced(entry, vma, ev->flags); } -static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags) -{ - GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN)); - - if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE)) - __i915_vma_unpin_fence(vma); - - __i915_vma_unpin(vma); -} - static inline void eb_unreserve_vma(struct eb_vma *ev) { if (!(ev->flags & __EXEC_OBJECT_HAS_PIN)) return; - __eb_unreserve_vma(ev->vma, ev->flags); + if (unlikely(ev->flags & __EXEC_OBJECT_HAS_FENCE)) + __i915_vma_unpin_fence(ev->vma); + + __i915_vma_unpin(ev->vma); ev->flags &= ~__EXEC_OBJECT_RESERVED; } @@ -563,16 +562,6 @@ eb_add_vma(struct i915_execbuffer *eb, eb->batch = ev; } - - if (eb_pin_vma(eb, entry, ev)) { - if (entry->offset != vma->node.start) { - entry->offset = vma->node.start | UPDATE; - eb->args->flags |= __EXEC_HAS_RELOC; - } - } else { - eb_unreserve_vma(ev); - list_add_tail(&ev->bind_link, &eb->unbound); - } } static inline int use_cpu_reloc(const struct reloc_cache *cache, @@ -657,10 +646,6 @@ static int eb_reserve(struct i915_execbuffer *eb) * This avoid unnecessary unbinding of later objects in order to make * room for the earlier objects *unless* we need to defragment. */ - - if (mutex_lock_interruptible(&eb->i915->drm.struct_mutex)) - return -EINTR; - pass = 0; do { list_for_each_entry(ev, &eb->unbound, bind_link) { @@ -669,7 +654,7 @@ static int eb_reserve(struct i915_execbuffer *eb) break; } if (err != -ENOSPC) - break; + return err; /* Resort *all* the objects into priority order */ INIT_LIST_HEAD(&eb->unbound); @@ -709,20 +694,15 @@ static int eb_reserve(struct i915_execbuffer *eb) err = i915_gem_evict_vm(eb->context->vm); mutex_unlock(&eb->context->vm->mutex); if (err) - goto unlock; + return err; break; default: - err = -ENOSPC; - goto unlock; + return -ENOSPC; } pin_flags = PIN_USER; } while (1); - -unlock: - mutex_unlock(&eb->i915->drm.struct_mutex); - return err; } static unsigned int eb_batch_index(const struct i915_execbuffer *eb) @@ -851,7 +831,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) int err = 0; INIT_LIST_HEAD(&eb->relocs); - INIT_LIST_HEAD(&eb->unbound); for (i = 0; i < eb->buffer_count; i++) { struct i915_vma *vma; @@ -894,6 +873,48 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) return err; } +static int eb_validate_vmas(struct i915_execbuffer *eb) +{ + unsigned int i; + int err; + + INIT_LIST_HEAD(&eb->unbound); + + for (i = 0; i < eb->buffer_count; i++) { + struct drm_i915_gem_exec_object2 *entry = &eb->exec[i]; + struct eb_vma *ev = &eb->vma[i]; + struct i915_vma *vma = ev->vma; + + err = i915_gem_object_lock(vma->obj, &eb->ww); + if (err) + return err; + + if (eb_pin_vma(eb, entry, ev)) { + if (entry->offset != vma->node.start) { + entry->offset = vma->node.start | UPDATE; + eb->args->flags |= __EXEC_HAS_RELOC; + } + } else { + eb_unreserve_vma(ev); + + list_add_tail(&ev->bind_link, &eb->unbound); + if (drm_mm_node_allocated(&vma->node)) { + err = i915_vma_unbind(vma); + if (err) + return err; + } + } + + GEM_BUG_ON(drm_mm_node_allocated(&vma->node) && + eb_vma_misplaced(&eb->exec[i], vma, ev->flags)); + } + + if (!list_empty(&eb->unbound)) + return eb_reserve(eb); + + return 0; +} + static struct eb_vma * eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) { @@ -914,7 +935,7 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } -static void eb_release_vmas(const struct i915_execbuffer *eb) +static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) { const unsigned int count = eb->buffer_count; unsigned int i; @@ -926,12 +947,10 @@ static void eb_release_vmas(const struct i915_execbuffer *eb) if (!vma) break; - eb->vma[i].vma = NULL; - - if (ev->flags & __EXEC_OBJECT_HAS_PIN) - __eb_unreserve_vma(vma, ev->flags); + eb_unreserve_vma(ev); - i915_vma_put(vma); + if (final) + i915_vma_put(vma); } } @@ -950,6 +969,14 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc, return gen8_canonical_addr((int)reloc->delta + target->node.start); } +static void reloc_cache_clear(struct reloc_cache *cache) +{ + cache->rq = NULL; + cache->rq_cmd = NULL; + cache->pool = NULL; + cache->rq_size = 0; +} + static void reloc_cache_init(struct reloc_cache *cache, struct drm_i915_private *i915) { @@ -962,8 +989,7 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->has_fence = cache->gen < 4; cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment; cache->node.flags = 0; - cache->rq = NULL; - cache->rq_size = 0; + reloc_cache_clear(cache); } static inline void *unmask_page(unsigned long p) @@ -985,7 +1011,23 @@ static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) return &i915->ggtt; } -static void reloc_gpu_flush(struct reloc_cache *cache) +static void reloc_cache_put_pool(struct i915_execbuffer *eb, struct reloc_cache *cache) +{ + if (!cache->pool) + return; + + /* + * This is a bit nasty, normally we keep objects locked until the end + * of execbuffer, but we already submit this, and have to unlock before + * dropping the reference. Fortunately we can only hold 1 pool node at + * a time, so this should be harmless. + */ + i915_gem_ww_unlock_single(cache->pool->obj); + intel_gt_buffer_pool_put(cache->pool); + cache->pool = NULL; +} + +static void reloc_gpu_flush(struct i915_execbuffer *eb, struct reloc_cache *cache) { struct drm_i915_gem_object *obj = cache->rq->batch->obj; @@ -998,15 +1040,18 @@ static void reloc_gpu_flush(struct reloc_cache *cache) intel_gt_chipset_flush(cache->rq->engine->gt); i915_request_add(cache->rq); - cache->rq = NULL; + reloc_cache_put_pool(eb, cache); + reloc_cache_clear(cache); + + eb->reloc_pool = NULL; } -static void reloc_cache_reset(struct reloc_cache *cache) +static void reloc_cache_reset(struct reloc_cache *cache, struct i915_execbuffer *eb) { void *vaddr; if (cache->rq) - reloc_gpu_flush(cache); + reloc_gpu_flush(eb, cache); if (!cache->vaddr) return; @@ -1020,7 +1065,6 @@ static void reloc_cache_reset(struct reloc_cache *cache) kunmap_atomic(vaddr); i915_gem_object_finish_access(obj); - i915_gem_object_unlock(obj); } else { struct i915_ggtt *ggtt = cache_to_ggtt(cache); @@ -1056,16 +1100,10 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, unsigned int flushes; int err; - err = i915_gem_object_lock_interruptible(obj, NULL); + err = i915_gem_object_prepare_write(obj, &flushes); if (err) return ERR_PTR(err); - err = i915_gem_object_prepare_write(obj, &flushes); - if (err) { - i915_gem_object_unlock(obj); - return ERR_PTR(err); - } - BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); @@ -1107,9 +1145,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (use_cpu_reloc(cache, obj)) return NULL; - i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); - i915_gem_object_unlock(obj); if (err) return ERR_PTR(err); @@ -1198,7 +1234,7 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) struct drm_i915_gem_object *obj = vma->obj; int err; - i915_vma_lock(vma); + assert_vma_held(vma); if (obj->cache_dirty & ~obj->cache_coherent) i915_gem_clflush_object(obj, 0); @@ -1208,8 +1244,6 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - return err; } @@ -1219,15 +1253,22 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, unsigned int len) { struct reloc_cache *cache = &eb->reloc_cache; - struct intel_gt_buffer_pool_node *pool; + struct intel_gt_buffer_pool_node *pool = eb->reloc_pool; struct i915_request *rq; struct i915_vma *batch; u32 *cmd; int err; - pool = intel_gt_get_buffer_pool(engine->gt, PAGE_SIZE); - if (IS_ERR(pool)) - return PTR_ERR(pool); + if (!pool) { + pool = intel_gt_get_buffer_pool(engine->gt, PAGE_SIZE); + if (IS_ERR(pool)) + return PTR_ERR(pool); + } + eb->reloc_pool = NULL; + + err = i915_gem_object_lock(pool->obj, &eb->ww); + if (err) + goto err_pool; cmd = i915_gem_object_pin_map(pool->obj, cache->has_llc ? @@ -1235,7 +1276,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, I915_MAP_FORCE_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_pool; + goto err_pool; } batch = i915_vma_instance(pool->obj, vma->vm, NULL); @@ -1284,11 +1325,10 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto skip_request; - i915_vma_lock(batch); + assert_vma_held(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); if (err) goto skip_request; @@ -1298,9 +1338,10 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, cache->rq = rq; cache->rq_cmd = cmd; cache->rq_size = 0; + cache->pool = pool; /* Return with batch mapping (cmd) still pinned */ - goto out_pool; + return 0; skip_request: i915_request_set_error_once(rq, err); @@ -1310,8 +1351,8 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, i915_vma_unpin(batch); err_unmap: i915_gem_object_unpin_map(pool->obj); -out_pool: - intel_gt_buffer_pool_put(pool); +err_pool: + eb->reloc_pool = pool; return err; } @@ -1328,7 +1369,7 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, u32 *cmd; if (cache->rq_size > PAGE_SIZE/sizeof(u32) - (len + 1)) - reloc_gpu_flush(cache); + reloc_gpu_flush(eb, cache); if (unlikely(!cache->rq)) { int err; @@ -1376,7 +1417,7 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static bool __reloc_entry_gpu(struct i915_execbuffer *eb, +static int __reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1394,7 +1435,9 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, len = 3; batch = reloc_gpu(eb, vma, len); - if (IS_ERR(batch)) + if (batch == ERR_PTR(-EDEADLK)) + return (s64)-EDEADLK; + else if (IS_ERR(batch)) return false; addr = gen8_canonical_addr(vma->node.start + offset); @@ -1447,7 +1490,7 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, return true; } -static bool reloc_entry_gpu(struct i915_execbuffer *eb, +static int reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1469,8 +1512,12 @@ relocate_entry(struct i915_vma *vma, { u64 target_addr = relocation_target(reloc, target); u64 offset = reloc->offset; + int reloc_gpu = reloc_entry_gpu(eb, vma, offset, target_addr); + + if (reloc_gpu < 0) + return reloc_gpu; - if (!reloc_entry_gpu(eb, vma, offset, target_addr)) { + if (!reloc_gpu) { bool wide = eb->reloc_cache.use_64bit_reloc; void *vaddr; @@ -1673,7 +1720,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) urelocs += ARRAY_SIZE(stack); } while (remain); out: - reloc_cache_reset(&eb->reloc_cache); + reloc_cache_reset(&eb->reloc_cache, eb); return remain; } @@ -1696,7 +1743,7 @@ eb_relocate_vma_slow(struct i915_execbuffer *eb, struct eb_vma *ev) } err = 0; err: - reloc_cache_reset(&eb->reloc_cache); + reloc_cache_reset(&eb->reloc_cache, eb); return err; } @@ -1836,6 +1883,10 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) goto out; } + /* We may process another execbuffer during the unlock... */ + eb_release_vmas(eb, false); + i915_gem_ww_ctx_fini(&eb->ww); + /* * We take 3 passes through the slowpatch. * @@ -1861,12 +1912,17 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) flush_workqueue(eb->i915->mm.userptr_wq); + i915_gem_ww_ctx_init(&eb->ww, true); if (err) goto out; - err = mutex_lock_interruptible(&eb->i915->drm.struct_mutex); + /* reacquire the objects */ +repeat_validate: + err = eb_validate_vmas(eb); if (err) - goto out; + goto err; + + GEM_BUG_ON(!eb->batch); list_for_each_entry(ev, &eb->relocs, reloc_link) { if (!have_copy) { @@ -1882,7 +1938,9 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) } } - mutex_unlock(&eb->i915->drm.struct_mutex); + if (err == -EDEADLK) + goto err; + if (err && !have_copy) goto repeat; @@ -1902,6 +1960,13 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) */ err: + if (err == -EDEADLK) { + eb_release_vmas(eb, false); + err = i915_gem_ww_ctx_backoff(&eb->ww); + if (!err) + goto repeat_validate; + } + if (err == -EAGAIN) goto repeat; @@ -1930,15 +1995,12 @@ static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; - err = eb_lookup_vmas(eb); - if (err) - return err; - - if (!list_empty(&eb->unbound)) { - err = eb_reserve(eb); - if (err) - return err; - } +retry: + err = eb_validate_vmas(eb); + if (err == -EAGAIN) + goto slow; + else if (err) + goto err; /* The objects are in their final locations, apply the relocations. */ if (eb->args->flags & __EXEC_HAS_RELOC) { @@ -1950,45 +2012,46 @@ static int eb_relocate_parse(struct i915_execbuffer *eb) break; } - if (err) - return eb_relocate_parse_slow(eb); + if (err == -EDEADLK) + goto err; + else if (err) + goto slow; + } + + if (!err) + err = eb_parse(eb); + +err: + if (err == -EDEADLK) { + eb_release_vmas(eb, false); + err = i915_gem_ww_ctx_backoff(&eb->ww); + if (!err) + goto retry; } - return eb_parse(eb); + return err; + +slow: + err = eb_relocate_parse_slow(eb); + if (err) + /* + * If the user expects the execobject.offset and + * reloc.presumed_offset to be an exact match, + * as for using NO_RELOC, then we cannot update + * the execobject.offset until we have completed + * relocation. + */ + eb->args->flags &= ~__EXEC_HAS_RELOC; + + return err; } static int eb_move_to_gpu(struct i915_execbuffer *eb) { const unsigned int count = eb->buffer_count; - struct ww_acquire_ctx acquire; - unsigned int i; + unsigned int i = count; int err = 0; - ww_acquire_init(&acquire, &reservation_ww_class); - - for (i = 0; i < count; i++) { - struct eb_vma *ev = &eb->vma[i]; - struct i915_vma *vma = ev->vma; - - err = ww_mutex_lock_interruptible(&vma->resv->lock, &acquire); - if (err == -EDEADLK) { - GEM_BUG_ON(i == 0); - do { - int j = i - 1; - - ww_mutex_unlock(&eb->vma[j].vma->resv->lock); - - swap(eb->vma[i], eb->vma[j]); - } while (--i); - - err = ww_mutex_lock_slow_interruptible(&vma->resv->lock, - &acquire); - } - if (err) - break; - } - ww_acquire_done(&acquire); - while (i--) { struct eb_vma *ev = &eb->vma[i]; struct i915_vma *vma = ev->vma; @@ -2032,10 +2095,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) if (err == 0) err = i915_vma_move_to_active(vma, eb->request, flags); - - i915_vma_unlock(vma); } - ww_acquire_fini(&acquire); if (unlikely(err)) goto err_skip; @@ -2227,36 +2287,26 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb, if (err) goto err_commit; - err = dma_resv_lock_interruptible(pw->batch->resv, NULL); - if (err) - goto err_commit; - err = dma_resv_reserve_shared(pw->batch->resv, 1); if (err) - goto err_commit_unlock; + goto err_commit; /* Wait for all writes (and relocs) into the batch to complete */ err = i915_sw_fence_await_reservation(&pw->base.chain, pw->batch->resv, NULL, false, 0, I915_FENCE_GFP); if (err < 0) - goto err_commit_unlock; + goto err_commit; /* Keep the batch alive and unwritten as we parse */ dma_resv_add_shared_fence(pw->batch->resv, &pw->base.dma); - dma_resv_unlock(pw->batch->resv); - /* Force execution to wait for completion of the parser */ - dma_resv_lock(shadow->resv, NULL); dma_resv_add_excl_fence(shadow->resv, &pw->base.dma); - dma_resv_unlock(shadow->resv); dma_fence_work_commit_imm(&pw->base); return 0; -err_commit_unlock: - dma_resv_unlock(pw->batch->resv); err_commit: i915_sw_fence_set_error_once(&pw->base.chain, err); dma_fence_work_commit_imm(&pw->base); @@ -2274,7 +2324,7 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb, static int eb_parse(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; - struct intel_gt_buffer_pool_node *pool; + struct intel_gt_buffer_pool_node *pool = eb->batch_pool; struct i915_vma *shadow, *trampoline; unsigned int len; int err; @@ -2297,9 +2347,16 @@ static int eb_parse(struct i915_execbuffer *eb) len += I915_CMD_PARSER_TRAMPOLINE_SIZE; } - pool = intel_gt_get_buffer_pool(eb->engine->gt, len); - if (IS_ERR(pool)) - return PTR_ERR(pool); + if (!pool) { + pool = intel_gt_get_buffer_pool(eb->engine->gt, len); + if (IS_ERR(pool)) + return PTR_ERR(pool); + eb->batch_pool = pool; + } + + err = i915_gem_object_lock(pool->obj, &eb->ww); + if (err) + goto err; shadow = shadow_batch_pin(pool->obj, eb->context->vm, PIN_USER); if (IS_ERR(shadow)) { @@ -2345,7 +2402,6 @@ static int eb_parse(struct i915_execbuffer *eb) err_shadow: i915_vma_unpin(shadow); err: - intel_gt_buffer_pool_put(pool); return err; } @@ -3000,6 +3056,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.exec = exec; eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); eb.vma[0].vma = NULL; + eb.reloc_pool = eb.batch_pool = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3072,6 +3129,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_context; + err = eb_lookup_vmas(&eb); + if (err) { + eb_release_vmas(&eb, true); + goto err_engine; + } + + i915_gem_ww_ctx_init(&eb.ww, true); + err = eb_relocate_parse(&eb); if (err) { /* @@ -3085,6 +3150,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_vma; } + ww_acquire_done(&eb.ww.ctx); + /* * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. @@ -3105,7 +3172,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { err = PTR_ERR(vma); - goto err_parse; + goto err_vma; } batch = vma; @@ -3157,8 +3224,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, * to explicitly hold another reference here. */ eb.request->batch = batch; - if (batch->private) - intel_gt_buffer_pool_mark_active(batch->private, eb.request); + if (eb.batch_pool) + intel_gt_buffer_pool_mark_active(eb.batch_pool, eb.request); trace_i915_request_queue(eb.request, eb.batch_flags); err = eb_submit(&eb, batch); @@ -3184,14 +3251,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, err_batch_unpin: if (eb.batch_flags & I915_DISPATCH_SECURE) i915_vma_unpin(batch); -err_parse: - if (batch->private) - intel_gt_buffer_pool_put(batch->private); err_vma: - if (eb.exec) - eb_release_vmas(&eb); + eb_release_vmas(&eb, true); if (eb.trampoline) i915_vma_unpin(eb.trampoline); + WARN_ON(err == -EDEADLK); + i915_gem_ww_ctx_fini(&eb.ww); + + if (eb.batch_pool) + intel_gt_buffer_pool_put(eb.batch_pool); + if (eb.reloc_pool) + intel_gt_buffer_pool_put(eb.reloc_pool); +err_engine: eb_unpin_engine(&eb); err_context: i915_gem_context_put(eb.gem_context); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 580884cffec36..bc08c02b57678 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -32,25 +32,23 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, if (IS_ERR(vma)) return PTR_ERR(vma); + err = i915_gem_object_lock(obj, &eb->ww); + if (err) + return err; + err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH); if (err) return err; /* 8-Byte aligned */ - if (!__reloc_entry_gpu(eb, vma, - offsets[0] * sizeof(u32), - 0)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0); + if (err <= 0) + goto reloc_err; /* !8-Byte aligned */ - if (!__reloc_entry_gpu(eb, vma, - offsets[1] * sizeof(u32), - 1)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1); + if (err <= 0) + goto reloc_err; /* Skip to the end of the cmd page */ i = PAGE_SIZE / sizeof(u32) - 1; @@ -60,16 +58,13 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, eb->reloc_cache.rq_size += i; /* Force next batch */ - if (!__reloc_entry_gpu(eb, vma, - offsets[2] * sizeof(u32), - 2)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2); + if (err <= 0) + goto reloc_err; GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); - reloc_gpu_flush(&eb->reloc_cache); + reloc_gpu_flush(eb, &eb->reloc_cache); GEM_BUG_ON(eb->reloc_cache.rq); err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, HZ / 2); @@ -101,6 +96,11 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, unpin_vma: i915_vma_unpin(vma); return err; + +reloc_err: + if (!err) + err = -EIO; + goto unpin_vma; } static int igt_gpu_reloc(void *arg) @@ -122,6 +122,8 @@ static int igt_gpu_reloc(void *arg) goto err_scratch; } + intel_gt_pm_get(&eb.i915->gt); + for_each_uabi_engine(eb.engine, eb.i915) { reloc_cache_init(&eb.reloc_cache, eb.i915); memset(map, POISON_INUSE, 4096); @@ -132,15 +134,26 @@ static int igt_gpu_reloc(void *arg) err = PTR_ERR(eb.context); goto err_pm; } + eb.reloc_pool = NULL; + i915_gem_ww_ctx_init(&eb.ww, false); +retry: err = intel_context_pin(eb.context); - if (err) - goto err_put; + if (!err) { + err = __igt_gpu_reloc(&eb, scratch); + + intel_context_unpin(eb.context); + } + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&eb.ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&eb.ww); - err = __igt_gpu_reloc(&eb, scratch); + if (eb.reloc_pool) + intel_gt_buffer_pool_put(eb.reloc_pool); - intel_context_unpin(eb.context); -err_put: intel_context_put(eb.context); err_pm: intel_engine_pm_put(eb.engine); @@ -151,6 +164,7 @@ static int igt_gpu_reloc(void *arg) if (igt_flush_test(eb.i915)) err = -EIO; + intel_gt_pm_put(&eb.i915->gt); err_scratch: i915_gem_object_put(scratch); return err; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 55158e487a7f4..f6615d942b60f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1360,6 +1360,12 @@ static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) } } +void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj) +{ + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); +} + void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww) { i915_gem_ww_ctx_unlock_all(ww); diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 427ebd02fceb0..a4cad3f154caf 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -126,5 +126,6 @@ struct i915_gem_ww_ctx { void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr); void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); +void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj); #endif /* __I915_GEM_H__ */ -- GitLab From bfdf8b1d38680dd40f43b95710b2b4e6c6f7f57f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:49 +0200 Subject: [PATCH 0831/1494] drm/i915: Use ww locking in intel_renderstate. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to start using ww locking in intel_context_pin, for this we need to lock multiple objects, and the single i915_gem_object_lock is not enough. Convert to using ww-waiting, and make sure we always pin intel_context_state, even if we don't have a renderstate object. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-10-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_gt.c | 21 +++--- drivers/gpu/drm/i915/gt/intel_renderstate.c | 73 +++++++++++++++------ drivers/gpu/drm/i915/gt/intel_renderstate.h | 9 ++- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index e0755f1a904b2..8694ddbdac4cc 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -406,21 +406,20 @@ static int __engines_record_defaults(struct intel_gt *gt) /* We must be able to switch to something! */ GEM_BUG_ON(!engine->kernel_context); - err = intel_renderstate_init(&so, engine); - if (err) - goto out; - ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); goto out; } - rq = intel_context_create_request(ce); + err = intel_renderstate_init(&so, ce); + if (err) + goto err; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - intel_context_put(ce); - goto out; + goto err_fini; } err = intel_engine_emit_ctx_wa(rq); @@ -434,9 +433,13 @@ static int __engines_record_defaults(struct intel_gt *gt) err_rq: requests[id] = i915_request_get(rq); i915_request_add(rq); - intel_renderstate_fini(&so); - if (err) +err_fini: + intel_renderstate_fini(&so, ce); +err: + if (err) { + intel_context_put(ce); goto out; + } } /* Flush the default context image to memory, and enable powersaving. */ diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c index 1bfad589c63b3..5164de04049d2 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.c +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c @@ -27,6 +27,7 @@ #include "i915_drv.h" #include "intel_renderstate.h" +#include "gt/intel_context.h" #include "intel_ring.h" static const struct intel_renderstate_rodata * @@ -157,33 +158,47 @@ static int render_state_setup(struct intel_renderstate *so, #undef OUT_BATCH int intel_renderstate_init(struct intel_renderstate *so, - struct intel_engine_cs *engine) + struct intel_context *ce) { - struct drm_i915_gem_object *obj; + struct intel_engine_cs *engine = ce->engine; + struct drm_i915_gem_object *obj = NULL; int err; memset(so, 0, sizeof(*so)); so->rodata = render_state_get_rodata(engine); - if (!so->rodata) - return 0; + if (so->rodata) { + if (so->rodata->batch_items * 4 > PAGE_SIZE) + return -EINVAL; + + obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); + if (IS_ERR(so->vma)) { + err = PTR_ERR(so->vma); + goto err_obj; + } + } - if (so->rodata->batch_items * 4 > PAGE_SIZE) - return -EINVAL; + i915_gem_ww_ctx_init(&so->ww, true); +retry: + err = intel_context_pin(ce); + if (err) + goto err_fini; - obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); - if (IS_ERR(obj)) - return PTR_ERR(obj); + /* return early if there's nothing to setup */ + if (!err && !so->rodata) + return 0; - so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); - if (IS_ERR(so->vma)) { - err = PTR_ERR(so->vma); - goto err_obj; - } + err = i915_gem_object_lock(so->vma->obj, &so->ww); + if (err) + goto err_context; err = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); if (err) - goto err_obj; + goto err_context; err = render_state_setup(so, engine->i915); if (err) @@ -193,8 +208,18 @@ int intel_renderstate_init(struct intel_renderstate *so, err_unpin: i915_vma_unpin(so->vma); +err_context: + intel_context_unpin(ce); +err_fini: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&so->ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&so->ww); err_obj: - i915_gem_object_put(obj); + if (obj) + i915_gem_object_put(obj); so->vma = NULL; return err; } @@ -208,11 +233,9 @@ int intel_renderstate_emit(struct intel_renderstate *so, if (!so->vma) return 0; - i915_vma_lock(so->vma); err = i915_request_await_object(rq, so->vma->obj, false); if (err == 0) err = i915_vma_move_to_active(so->vma, rq, 0); - i915_vma_unlock(so->vma); if (err) return err; @@ -233,7 +256,17 @@ int intel_renderstate_emit(struct intel_renderstate *so, return 0; } -void intel_renderstate_fini(struct intel_renderstate *so) +void intel_renderstate_fini(struct intel_renderstate *so, + struct intel_context *ce) { - i915_vma_unpin_and_release(&so->vma, 0); + if (so->vma) { + i915_vma_unpin(so->vma); + i915_vma_close(so->vma); + } + + intel_context_unpin(ce); + i915_gem_ww_ctx_fini(&so->ww); + + if (so->vma) + i915_gem_object_put(so->vma->obj); } diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.h b/drivers/gpu/drm/i915/gt/intel_renderstate.h index 5700be69a05a6..713aa1e86c80b 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.h +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.h @@ -25,9 +25,10 @@ #define _INTEL_RENDERSTATE_H_ #include <linux/types.h> +#include "i915_gem.h" struct i915_request; -struct intel_engine_cs; +struct intel_context; struct i915_vma; struct intel_renderstate_rodata { @@ -49,6 +50,7 @@ extern const struct intel_renderstate_rodata gen8_null_state; extern const struct intel_renderstate_rodata gen9_null_state; struct intel_renderstate { + struct i915_gem_ww_ctx ww; const struct intel_renderstate_rodata *rodata; struct i915_vma *vma; u32 batch_offset; @@ -58,9 +60,10 @@ struct intel_renderstate { }; int intel_renderstate_init(struct intel_renderstate *so, - struct intel_engine_cs *engine); + struct intel_context *ce); int intel_renderstate_emit(struct intel_renderstate *so, struct i915_request *rq); -void intel_renderstate_fini(struct intel_renderstate *so); +void intel_renderstate_fini(struct intel_renderstate *so, + struct intel_context *ce); #endif /* _INTEL_RENDERSTATE_H_ */ -- GitLab From 99f08d674e2d96f24d39452bd162b20e7d6bed12 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:50 +0200 Subject: [PATCH 0832/1494] drm/i915: Add ww context handling to context_barrier_task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is required if we want to pass a ww context in intel_context_pin and gen6_ppgtt_pin(). Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-11-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 55 ++++++++++++++----- .../drm/i915/gem/selftests/i915_gem_context.c | 22 +++----- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index db893f6c516b4..34c8b0dd85e0e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1106,6 +1106,7 @@ I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault); static int context_barrier_task(struct i915_gem_context *ctx, intel_engine_mask_t engines, bool (*skip)(struct intel_context *ce, void *data), + int (*pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data), int (*emit)(struct i915_request *rq, void *data), void (*task)(void *data), void *data) @@ -1113,6 +1114,7 @@ static int context_barrier_task(struct i915_gem_context *ctx, struct context_barrier_task *cb; struct i915_gem_engines_iter it; struct i915_gem_engines *e; + struct i915_gem_ww_ctx ww; struct intel_context *ce; int err = 0; @@ -1150,10 +1152,21 @@ static int context_barrier_task(struct i915_gem_context *ctx, if (skip && skip(ce, data)) continue; - rq = intel_context_create_request(ce); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = intel_context_pin(ce); + if (err) + goto err; + + if (pin) + err = pin(ce, &ww, data); + if (err) + goto err_unpin; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - break; + goto err_unpin; } err = 0; @@ -1163,6 +1176,16 @@ static int context_barrier_task(struct i915_gem_context *ctx, err = i915_active_add_request(&cb->base, rq); i915_request_add(rq); +err_unpin: + intel_context_unpin(ce); +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + if (err) break; } @@ -1218,6 +1241,17 @@ static void set_ppgtt_barrier(void *data) i915_vm_close(old); } +static int pin_ppgtt_update(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data) +{ + struct i915_address_space *vm = ce->vm; + + if (!HAS_LOGICAL_RING_CONTEXTS(vm->i915)) + /* ppGTT is not part of the legacy context image */ + return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm)); + + return 0; +} + static int emit_ppgtt_update(struct i915_request *rq, void *data) { struct i915_address_space *vm = rq->context->vm; @@ -1274,20 +1308,10 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) static bool skip_ppgtt_update(struct intel_context *ce, void *data) { - if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) - return true; - if (HAS_LOGICAL_RING_CONTEXTS(ce->engine->i915)) - return false; - - if (!atomic_read(&ce->pin_count)) - return true; - - /* ppGTT is not part of the legacy context image */ - if (gen6_ppgtt_pin(i915_vm_to_ppgtt(ce->vm))) - return true; - - return false; + return !ce->state; + else + return !atomic_read(&ce->pin_count); } static int set_ppgtt(struct drm_i915_file_private *file_priv, @@ -1338,6 +1362,7 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv, */ err = context_barrier_task(ctx, ALL_ENGINES, skip_ppgtt_update, + pin_ppgtt_update, emit_ppgtt_update, set_ppgtt_barrier, old); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 9160a335c684c..fa40006b453a6 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1920,8 +1920,8 @@ static int mock_context_barrier(void *arg) return -ENOMEM; counter = 0; - err = context_barrier_task(ctx, 0, - NULL, NULL, mock_barrier_task, &counter); + err = context_barrier_task(ctx, 0, NULL, NULL, NULL, + mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; @@ -1933,11 +1933,8 @@ static int mock_context_barrier(void *arg) } counter = 0; - err = context_barrier_task(ctx, ALL_ENGINES, - skip_unused_engines, - NULL, - mock_barrier_task, - &counter); + err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines, + NULL, NULL, mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; @@ -1957,8 +1954,8 @@ static int mock_context_barrier(void *arg) counter = 0; context_barrier_inject_fault = BIT(RCS0); - err = context_barrier_task(ctx, ALL_ENGINES, - NULL, NULL, mock_barrier_task, &counter); + err = context_barrier_task(ctx, ALL_ENGINES, NULL, NULL, NULL, + mock_barrier_task, &counter); context_barrier_inject_fault = 0; if (err == -ENXIO) err = 0; @@ -1972,11 +1969,8 @@ static int mock_context_barrier(void *arg) goto out; counter = 0; - err = context_barrier_task(ctx, ALL_ENGINES, - skip_unused_engines, - NULL, - mock_barrier_task, - &counter); + err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines, + NULL, NULL, mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; -- GitLab From b49a7d51c32e73b0e971247903e7e2a168c4482e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:51 +0200 Subject: [PATCH 0833/1494] drm/i915: Nuke arguments to eb_pin_engine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those arguments are already set as eb.file and eb.args, so kill off the extra arguments. This will allow us to move eb_pin_engine() to after we reserved all BO's. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-12-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 13b996830e25d..2ccc566f91549 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2610,11 +2610,10 @@ static void eb_unpin_engine(struct i915_execbuffer *eb) } static unsigned int -eb_select_legacy_ring(struct i915_execbuffer *eb, - struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args) +eb_select_legacy_ring(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; + struct drm_i915_gem_execbuffer2 *args = eb->args; unsigned int user_ring_id = args->flags & I915_EXEC_RING_MASK; if (user_ring_id != I915_EXEC_BSD && @@ -2629,7 +2628,7 @@ eb_select_legacy_ring(struct i915_execbuffer *eb, unsigned int bsd_idx = args->flags & I915_EXEC_BSD_MASK; if (bsd_idx == I915_EXEC_BSD_DEFAULT) { - bsd_idx = gen8_dispatch_bsd_engine(i915, file); + bsd_idx = gen8_dispatch_bsd_engine(i915, eb->file); } else if (bsd_idx >= I915_EXEC_BSD_RING1 && bsd_idx <= I915_EXEC_BSD_RING2) { bsd_idx >>= I915_EXEC_BSD_SHIFT; @@ -2654,18 +2653,16 @@ eb_select_legacy_ring(struct i915_execbuffer *eb, } static int -eb_pin_engine(struct i915_execbuffer *eb, - struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args) +eb_pin_engine(struct i915_execbuffer *eb) { struct intel_context *ce; unsigned int idx; int err; if (i915_gem_context_user_engines(eb->gem_context)) - idx = args->flags & I915_EXEC_RING_MASK; + idx = eb->args->flags & I915_EXEC_RING_MASK; else - idx = eb_select_legacy_ring(eb, file, args); + idx = eb_select_legacy_ring(eb); ce = i915_gem_context_get_engine(eb->gem_context, idx); if (IS_ERR(ce)) @@ -3125,7 +3122,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_destroy; - err = eb_pin_engine(&eb, file, args); + err = eb_pin_engine(&eb); if (unlikely(err)) goto err_context; -- GitLab From 2bf541ff6d06f4169e198adaa6c4133e178caaa5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:52 +0200 Subject: [PATCH 0834/1494] drm/i915: Pin engine before pinning all objects, v5. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to lock all gem objects, including the engine context objects, rework the throttling to ensure that we can do this. Now we only throttle once, but can take eb_pin_engine while acquiring objects. This means we will have to drop the lock to wait. If we don't have to throttle we can still take the fastpath, if not we will take the slowpath and wait for the throttle request while unlocked. The engine has to be pinned as first step, otherwise gpu relocations won't work. Changes since v1: - Only need to get a throttled request in the fastpath, no need for a global flag any more. - Always free the waited request correctly. Changes since v2: - Use intel_engine_pm_get()/put() to keeep engine pool alive during EDEADLK handling. Changes since v3: - Fix small rq leak. Changes since v4: - Use a single reloc_context, for intel_context_pin_ww(). Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-13-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 214 ++++++++++++------ .../i915/gem/selftests/i915_gem_execbuffer.c | 3 + 2 files changed, 152 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 2ccc566f91549..d3c47390ef530 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -56,7 +56,8 @@ enum { #define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE) #define __EXEC_HAS_RELOC BIT(31) -#define __EXEC_INTERNAL_FLAGS (~0u << 31) +#define __EXEC_ENGINE_PINNED BIT(30) +#define __EXEC_INTERNAL_FLAGS (~0u << 30) #define UPDATE PIN_OFFSET_FIXED #define BATCH_OFFSET_BIAS (256*1024) @@ -281,6 +282,7 @@ struct i915_execbuffer { } reloc_cache; struct intel_gt_buffer_pool_node *reloc_pool; /** relocation pool for -EDEADLK handling */ + struct intel_context *reloc_context; u64 invalid_flags; /** Set of execobj.flags that are invalid */ u32 context_flags; /** Set of execobj.flags to insert from the ctx */ @@ -303,6 +305,9 @@ struct i915_execbuffer { }; static int eb_parse(struct i915_execbuffer *eb); +static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, + bool throttle); +static void eb_unpin_engine(struct i915_execbuffer *eb); static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { @@ -935,7 +940,7 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } -static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) +static void eb_release_vmas(struct i915_execbuffer *eb, bool final) { const unsigned int count = eb->buffer_count; unsigned int i; @@ -952,6 +957,8 @@ static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) if (final) i915_vma_put(vma); } + + eb_unpin_engine(eb); } static void eb_destroy(const struct i915_execbuffer *eb) @@ -1292,19 +1299,26 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (engine == eb->context->engine) { rq = i915_request_create(eb->context); } else { - struct intel_context *ce; + struct intel_context *ce = eb->reloc_context; - ce = intel_context_create(engine); - if (IS_ERR(ce)) { - err = PTR_ERR(ce); - goto err_unpin; + if (!ce) { + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + goto err_unpin; + } + + i915_vm_put(ce->vm); + ce->vm = i915_vm_get(eb->context->vm); + eb->reloc_context = ce; } - i915_vm_put(ce->vm); - ce->vm = i915_vm_get(eb->context->vm); + err = intel_context_pin(ce); + if (err) + goto err_unpin; - rq = intel_context_create_request(ce); - intel_context_put(ce); + rq = i915_request_create(ce); + intel_context_unpin(ce); } if (IS_ERR(rq)) { err = PTR_ERR(rq); @@ -1871,7 +1885,8 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) return 0; } -static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) +static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb, + struct i915_request *rq) { bool have_copy = false; struct eb_vma *ev; @@ -1887,6 +1902,21 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) eb_release_vmas(eb, false); i915_gem_ww_ctx_fini(&eb->ww); + if (rq) { + /* nonblocking is always false */ + if (i915_request_wait(rq, I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT) < 0) { + i915_request_put(rq); + rq = NULL; + + err = -EINTR; + goto err_relock; + } + + i915_request_put(rq); + rq = NULL; + } + /* * We take 3 passes through the slowpatch. * @@ -1910,14 +1940,25 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) err = 0; } - flush_workqueue(eb->i915->mm.userptr_wq); + if (!err) + flush_workqueue(eb->i915->mm.userptr_wq); +err_relock: i915_gem_ww_ctx_init(&eb->ww, true); if (err) goto out; /* reacquire the objects */ repeat_validate: + rq = eb_pin_engine(eb, false); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto err; + } + + /* We didn't throttle, should be NULL */ + GEM_WARN_ON(rq); + err = eb_validate_vmas(eb); if (err) goto err; @@ -1988,14 +2029,49 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) } } + if (rq) + i915_request_put(rq); + return err; } static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; + struct i915_request *rq = NULL; + bool throttle = true; retry: + rq = eb_pin_engine(eb, throttle); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + rq = NULL; + if (err != -EDEADLK) + return err; + + goto err; + } + + if (rq) { + bool nonblock = eb->file->filp->f_flags & O_NONBLOCK; + + /* Need to drop all locks now for throttling, take slowpath */ + err = i915_request_wait(rq, I915_WAIT_INTERRUPTIBLE, 0); + if (err == -ETIME) { + if (nonblock) { + err = -EWOULDBLOCK; + i915_request_put(rq); + goto err; + } + goto slow; + } + i915_request_put(rq); + rq = NULL; + } + + /* only throttle once, even if we didn't need to throttle */ + throttle = false; + err = eb_validate_vmas(eb); if (err == -EAGAIN) goto slow; @@ -2032,7 +2108,7 @@ static int eb_relocate_parse(struct i915_execbuffer *eb) return err; slow: - err = eb_relocate_parse_slow(eb); + err = eb_relocate_parse_slow(eb, rq); if (err) /* * If the user expects the execobject.offset and @@ -2486,7 +2562,7 @@ static const enum intel_engine_id user_ring_map[] = { [I915_EXEC_VEBOX] = VECS0 }; -static struct i915_request *eb_throttle(struct intel_context *ce) +static struct i915_request *eb_throttle(struct i915_execbuffer *eb, struct intel_context *ce) { struct intel_ring *ring = ce->ring; struct intel_timeline *tl = ce->timeline; @@ -2520,22 +2596,17 @@ static struct i915_request *eb_throttle(struct intel_context *ce) return i915_request_get(rq); } -static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) +static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, bool throttle) { + struct intel_context *ce = eb->context; struct intel_timeline *tl; - struct i915_request *rq; + struct i915_request *rq = NULL; int err; - /* - * ABI: Before userspace accesses the GPU (e.g. execbuffer), report - * EIO if the GPU is already wedged. - */ - err = intel_gt_terminally_wedged(ce->engine->gt); - if (err) - return err; + GEM_BUG_ON(eb->args->flags & __EXEC_ENGINE_PINNED); if (unlikely(intel_context_is_banned(ce))) - return -EIO; + return ERR_PTR(-EIO); /* * Pinning the contexts may generate requests in order to acquire @@ -2544,7 +2615,7 @@ static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) */ err = intel_context_pin(ce); if (err) - return err; + return ERR_PTR(err); /* * Take a local wakeref for preparing to dispatch the execbuf as @@ -2556,45 +2627,17 @@ static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) */ tl = intel_context_timeline_lock(ce); if (IS_ERR(tl)) { - err = PTR_ERR(tl); - goto err_unpin; + intel_context_unpin(ce); + return ERR_CAST(tl); } intel_context_enter(ce); - rq = eb_throttle(ce); - + if (throttle) + rq = eb_throttle(eb, ce); intel_context_timeline_unlock(tl); - if (rq) { - bool nonblock = eb->file->filp->f_flags & O_NONBLOCK; - long timeout; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (nonblock) - timeout = 0; - - timeout = i915_request_wait(rq, - I915_WAIT_INTERRUPTIBLE, - timeout); - i915_request_put(rq); - - if (timeout < 0) { - err = nonblock ? -EWOULDBLOCK : timeout; - goto err_exit; - } - } - - eb->engine = ce->engine; - eb->context = ce; - return 0; - -err_exit: - mutex_lock(&tl->mutex); - intel_context_exit(ce); - intel_context_timeline_unlock(tl); -err_unpin: - intel_context_unpin(ce); - return err; + eb->args->flags |= __EXEC_ENGINE_PINNED; + return rq; } static void eb_unpin_engine(struct i915_execbuffer *eb) @@ -2602,6 +2645,11 @@ static void eb_unpin_engine(struct i915_execbuffer *eb) struct intel_context *ce = eb->context; struct intel_timeline *tl = ce->timeline; + if (!(eb->args->flags & __EXEC_ENGINE_PINNED)) + return; + + eb->args->flags &= ~__EXEC_ENGINE_PINNED; + mutex_lock(&tl->mutex); intel_context_exit(ce); mutex_unlock(&tl->mutex); @@ -2653,7 +2701,7 @@ eb_select_legacy_ring(struct i915_execbuffer *eb) } static int -eb_pin_engine(struct i915_execbuffer *eb) +eb_select_engine(struct i915_execbuffer *eb) { struct intel_context *ce; unsigned int idx; @@ -2668,12 +2716,45 @@ eb_pin_engine(struct i915_execbuffer *eb) if (IS_ERR(ce)) return PTR_ERR(ce); - err = __eb_pin_engine(eb, ce); - intel_context_put(ce); + intel_gt_pm_get(ce->engine->gt); + if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { + err = intel_context_alloc_state(ce); + if (err) + goto err; + } + + /* + * ABI: Before userspace accesses the GPU (e.g. execbuffer), report + * EIO if the GPU is already wedged. + */ + err = intel_gt_terminally_wedged(ce->engine->gt); + if (err) + goto err; + + eb->context = ce; + eb->engine = ce->engine; + + /* + * Make sure engine pool stays alive even if we call intel_context_put + * during ww handling. The pool is destroyed when last pm reference + * is dropped, which breaks our -EDEADLK handling. + */ + return err; + +err: + intel_gt_pm_put(ce->engine->gt); + intel_context_put(ce); return err; } +static void +eb_put_engine(struct i915_execbuffer *eb) +{ + intel_gt_pm_put(eb->engine->gt); + intel_context_put(eb->context); +} + static void __free_fence_array(struct eb_fence *fences, unsigned int n) { @@ -3054,6 +3135,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); eb.vma[0].vma = NULL; eb.reloc_pool = eb.batch_pool = NULL; + eb.reloc_context = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3122,7 +3204,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_destroy; - err = eb_pin_engine(&eb); + err = eb_select_engine(&eb); if (unlikely(err)) goto err_context; @@ -3259,8 +3341,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, intel_gt_buffer_pool_put(eb.batch_pool); if (eb.reloc_pool) intel_gt_buffer_pool_put(eb.reloc_pool); + if (eb.reloc_context) + intel_context_put(eb.reloc_context); err_engine: - eb_unpin_engine(&eb); + eb_put_engine(&eb); err_context: i915_gem_context_put(eb.gem_context); err_destroy: diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index bc08c02b57678..563839cbaf1c1 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -135,6 +135,7 @@ static int igt_gpu_reloc(void *arg) goto err_pm; } eb.reloc_pool = NULL; + eb.reloc_context = NULL; i915_gem_ww_ctx_init(&eb.ww, false); retry: @@ -153,6 +154,8 @@ static int igt_gpu_reloc(void *arg) if (eb.reloc_pool) intel_gt_buffer_pool_put(eb.reloc_pool); + if (eb.reloc_context) + intel_context_put(eb.reloc_context); intel_context_put(eb.context); err_pm: -- GitLab From 3999a7087989af0bfb9406b77d3d8444031aab7d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:53 +0200 Subject: [PATCH 0835/1494] drm/i915: Rework intel_context pinning to do everything outside of pin_mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of doing everything inside of pin_mutex, we move all pinning outside. Because i915_active has its own reference counting and pinning is also having the same issues vs mutexes, we make sure everything is pinned first, so the pinning in i915_active only needs to bump refcounts. This allows us to take pin refcounts correctly all the time. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-14-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_context.c | 232 +++++++++++------- drivers/gpu/drm/i915/gt/intel_context_types.h | 4 +- drivers/gpu/drm/i915/gt/intel_lrc.c | 34 ++- .../gpu/drm/i915/gt/intel_ring_submission.c | 13 +- drivers/gpu/drm/i915/gt/mock_engine.c | 13 +- 5 files changed, 190 insertions(+), 106 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 52db2bde44a3a..efe9a7a89edea 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -93,79 +93,6 @@ static void intel_context_active_release(struct intel_context *ce) i915_active_release(&ce->active); } -int __intel_context_do_pin(struct intel_context *ce) -{ - int err; - - if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { - err = intel_context_alloc_state(ce); - if (err) - return err; - } - - err = i915_active_acquire(&ce->active); - if (err) - return err; - - if (mutex_lock_interruptible(&ce->pin_mutex)) { - err = -EINTR; - goto out_release; - } - - if (unlikely(intel_context_is_closed(ce))) { - err = -ENOENT; - goto out_unlock; - } - - if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { - err = intel_context_active_acquire(ce); - if (unlikely(err)) - goto out_unlock; - - err = ce->ops->pin(ce); - if (unlikely(err)) - goto err_active; - - CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n", - i915_ggtt_offset(ce->ring->vma), - ce->ring->head, ce->ring->tail); - - smp_mb__before_atomic(); /* flush pin before it is visible */ - atomic_inc(&ce->pin_count); - } - - GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ - GEM_BUG_ON(i915_active_is_idle(&ce->active)); - goto out_unlock; - -err_active: - intel_context_active_release(ce); -out_unlock: - mutex_unlock(&ce->pin_mutex); -out_release: - i915_active_release(&ce->active); - return err; -} - -void intel_context_unpin(struct intel_context *ce) -{ - if (!atomic_dec_and_test(&ce->pin_count)) - return; - - CE_TRACE(ce, "unpin\n"); - ce->ops->unpin(ce); - - /* - * Once released, we may asynchronously drop the active reference. - * As that may be the only reference keeping the context alive, - * take an extra now so that it is not freed before we finish - * dereferencing it. - */ - intel_context_get(ce); - intel_context_active_release(ce); - intel_context_put(ce); -} - static int __context_pin_state(struct i915_vma *vma) { unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; @@ -225,6 +152,138 @@ static void __ring_retire(struct intel_ring *ring) intel_ring_unpin(ring); } +static int intel_context_pre_pin(struct intel_context *ce) +{ + int err; + + CE_TRACE(ce, "active\n"); + + err = __ring_active(ce->ring); + if (err) + return err; + + err = intel_timeline_pin(ce->timeline); + if (err) + goto err_ring; + + if (!ce->state) + return 0; + + err = __context_pin_state(ce->state); + if (err) + goto err_timeline; + + + return 0; + +err_timeline: + intel_timeline_unpin(ce->timeline); +err_ring: + __ring_retire(ce->ring); + return err; +} + +static void intel_context_post_unpin(struct intel_context *ce) +{ + if (ce->state) + __context_unpin_state(ce->state); + + intel_timeline_unpin(ce->timeline); + __ring_retire(ce->ring); +} + +int __intel_context_do_pin(struct intel_context *ce) +{ + bool handoff = false; + void *vaddr; + int err = 0; + + if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { + err = intel_context_alloc_state(ce); + if (err) + return err; + } + + /* + * We always pin the context/ring/timeline here, to ensure a pin + * refcount for __intel_context_active(), which prevent a lock + * inversion of ce->pin_mutex vs dma_resv_lock(). + */ + err = intel_context_pre_pin(ce); + if (err) + return err; + + err = i915_active_acquire(&ce->active); + if (err) + goto err_ctx_unpin; + + err = ce->ops->pre_pin(ce, &vaddr); + if (err) + goto err_release; + + err = mutex_lock_interruptible(&ce->pin_mutex); + if (err) + goto err_post_unpin; + + if (unlikely(intel_context_is_closed(ce))) { + err = -ENOENT; + goto err_unlock; + } + + if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { + err = intel_context_active_acquire(ce); + if (unlikely(err)) + goto err_unlock; + + err = ce->ops->pin(ce, vaddr); + if (err) { + intel_context_active_release(ce); + goto err_unlock; + } + + CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n", + i915_ggtt_offset(ce->ring->vma), + ce->ring->head, ce->ring->tail); + + handoff = true; + smp_mb__before_atomic(); /* flush pin before it is visible */ + atomic_inc(&ce->pin_count); + } + + GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ + +err_unlock: + mutex_unlock(&ce->pin_mutex); +err_post_unpin: + if (!handoff) + ce->ops->post_unpin(ce); +err_release: + i915_active_release(&ce->active); +err_ctx_unpin: + intel_context_post_unpin(ce); + return err; +} + +void intel_context_unpin(struct intel_context *ce) +{ + if (!atomic_dec_and_test(&ce->pin_count)) + return; + + CE_TRACE(ce, "unpin\n"); + ce->ops->unpin(ce); + ce->ops->post_unpin(ce); + + /* + * Once released, we may asynchronously drop the active reference. + * As that may be the only reference keeping the context alive, + * take an extra now so that it is not freed before we finish + * dereferencing it. + */ + intel_context_get(ce); + intel_context_active_release(ce); + intel_context_put(ce); +} + __i915_active_call static void __intel_context_retire(struct i915_active *active) { @@ -235,12 +294,7 @@ static void __intel_context_retire(struct i915_active *active) intel_context_get_avg_runtime_ns(ce)); set_bit(CONTEXT_VALID_BIT, &ce->flags); - if (ce->state) - __context_unpin_state(ce->state); - - intel_timeline_unpin(ce->timeline); - __ring_retire(ce->ring); - + intel_context_post_unpin(ce); intel_context_put(ce); } @@ -249,29 +303,25 @@ static int __intel_context_active(struct i915_active *active) struct intel_context *ce = container_of(active, typeof(*ce), active); int err; - CE_TRACE(ce, "active\n"); - intel_context_get(ce); + /* everything should already be activated by intel_context_pre_pin() */ err = __ring_active(ce->ring); - if (err) + if (GEM_WARN_ON(err)) goto err_put; err = intel_timeline_pin(ce->timeline); - if (err) + if (GEM_WARN_ON(err)) goto err_ring; - if (!ce->state) - return 0; - - err = __context_pin_state(ce->state); - if (err) - goto err_timeline; + if (ce->state) { + GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active)); + __i915_vma_pin(ce->state); + i915_vma_make_unshrinkable(ce->state); + } return 0; -err_timeline: - intel_timeline_unpin(ce->timeline); err_ring: __ring_retire(ce->ring); err_put: diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 4954b0df48646..ca8e05b4d3efc 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -30,8 +30,10 @@ struct intel_ring; struct intel_context_ops { int (*alloc)(struct intel_context *ce); - int (*pin)(struct intel_context *ce); + int (*pre_pin)(struct intel_context *ce, void **vaddr); + int (*pin)(struct intel_context *ce, void *vaddr); void (*unpin)(struct intel_context *ce); + void (*post_unpin)(struct intel_context *ce); void (*enter)(struct intel_context *ce); void (*exit)(struct intel_context *ce); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 801ebe1326f39..1f6dc69b24900 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3296,7 +3296,10 @@ static void execlists_context_unpin(struct intel_context *ce) { check_redzone((void *)ce->lrc_reg_state - LRC_STATE_OFFSET, ce->engine); +} +static void execlists_context_post_unpin(struct intel_context *ce) +{ i915_gem_object_unpin_map(ce->state->obj); } @@ -3458,20 +3461,23 @@ __execlists_update_reg_state(const struct intel_context *ce, } static int -__execlists_context_pin(struct intel_context *ce, - struct intel_engine_cs *engine) +execlists_context_pre_pin(struct intel_context *ce, void **vaddr) { - void *vaddr; - GEM_BUG_ON(!ce->state); GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); - vaddr = i915_gem_object_pin_map(ce->state->obj, - i915_coherent_map_type(engine->i915) | + *vaddr = i915_gem_object_pin_map(ce->state->obj, + i915_coherent_map_type(ce->engine->i915) | I915_MAP_OVERRIDE); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); + return PTR_ERR_OR_ZERO(*vaddr); +} + +static int +__execlists_context_pin(struct intel_context *ce, + struct intel_engine_cs *engine, + void *vaddr) +{ ce->lrc.lrca = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE; ce->lrc_reg_state = vaddr + LRC_STATE_OFFSET; __execlists_update_reg_state(ce, engine, ce->ring->tail); @@ -3479,9 +3485,9 @@ __execlists_context_pin(struct intel_context *ce, return 0; } -static int execlists_context_pin(struct intel_context *ce) +static int execlists_context_pin(struct intel_context *ce, void *vaddr) { - return __execlists_context_pin(ce, ce->engine); + return __execlists_context_pin(ce, ce->engine, vaddr); } static int execlists_context_alloc(struct intel_context *ce) @@ -3507,8 +3513,10 @@ static void execlists_context_reset(struct intel_context *ce) static const struct intel_context_ops execlists_context_ops = { .alloc = execlists_context_alloc, + .pre_pin = execlists_context_pre_pin, .pin = execlists_context_pin, .unpin = execlists_context_unpin, + .post_unpin = execlists_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, @@ -5447,12 +5455,12 @@ static int virtual_context_alloc(struct intel_context *ce) return __execlists_context_alloc(ce, ve->siblings[0]); } -static int virtual_context_pin(struct intel_context *ce) +static int virtual_context_pin(struct intel_context *ce, void *vaddr) { struct virtual_engine *ve = container_of(ce, typeof(*ve), context); /* Note: we must use a real engine class for setting up reg state */ - return __execlists_context_pin(ce, ve->siblings[0]); + return __execlists_context_pin(ce, ve->siblings[0], vaddr); } static void virtual_context_enter(struct intel_context *ce) @@ -5480,8 +5488,10 @@ static void virtual_context_exit(struct intel_context *ce) static const struct intel_context_ops virtual_context_ops = { .alloc = virtual_context_alloc, + .pre_pin = execlists_context_pre_pin, .pin = virtual_context_pin, .unpin = execlists_context_unpin, + .post_unpin = execlists_context_post_unpin, .enter = virtual_context_enter, .exit = virtual_context_exit, diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index a3b10f3c83ebc..93cf72cfd3181 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -499,6 +499,10 @@ static void __context_unpin_ppgtt(struct intel_context *ce) } static void ring_context_unpin(struct intel_context *ce) +{ +} + +static void ring_context_post_unpin(struct intel_context *ce) { __context_unpin_ppgtt(ce); } @@ -587,11 +591,16 @@ static int ring_context_alloc(struct intel_context *ce) return 0; } -static int ring_context_pin(struct intel_context *ce) +static int ring_context_pre_pin(struct intel_context *ce, void **unused) { return __context_pin_ppgtt(ce); } +static int ring_context_pin(struct intel_context *ce, void *unused) +{ + return 0; +} + static void ring_context_reset(struct intel_context *ce) { intel_ring_reset(ce->ring, ce->ring->emit); @@ -600,8 +609,10 @@ static void ring_context_reset(struct intel_context *ce) static const struct intel_context_ops ring_context_ops = { .alloc = ring_context_alloc, + .pre_pin = ring_context_pre_pin, .pin = ring_context_pin, .unpin = ring_context_unpin, + .post_unpin = ring_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 79764305b8ec0..c8e631222f236 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -131,6 +131,10 @@ static void mock_context_unpin(struct intel_context *ce) { } +static void mock_context_post_unpin(struct intel_context *ce) +{ +} + static void mock_context_destroy(struct kref *ref) { struct intel_context *ce = container_of(ref, typeof(*ce), ref); @@ -163,7 +167,12 @@ static int mock_context_alloc(struct intel_context *ce) return 0; } -static int mock_context_pin(struct intel_context *ce) +static int mock_context_pre_pin(struct intel_context *ce, void **unused) +{ + return 0; +} + +static int mock_context_pin(struct intel_context *ce, void *unused) { return 0; } @@ -175,8 +184,10 @@ static void mock_context_reset(struct intel_context *ce) static const struct intel_context_ops mock_context_ops = { .alloc = mock_context_alloc, + .pre_pin = mock_context_pre_pin, .pin = mock_context_pin, .unpin = mock_context_unpin, + .post_unpin = mock_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, -- GitLab From 47b086934f429561b3828a6b248e3406b5121939 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:54 +0200 Subject: [PATCH 0836/1494] drm/i915: Make sure execbuffer always passes ww state to i915_vma_pin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a preparation step for full object locking and wait/wound handling during pin and object mapping, ensure that we always pass the ww context in i915_gem_execbuffer.c to i915_vma_pin, use lockdep to ensure this happens. This also requires changing the order of eb_parse slightly, to ensure we pass ww at a point where we could still handle -EDEADLK safely. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-15-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 4 +- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 140 ++++++++++-------- .../i915/gem/selftests/i915_gem_execbuffer.c | 4 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 4 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.h | 4 +- drivers/gpu/drm/i915/gt/intel_context.c | 65 +++++--- drivers/gpu/drm/i915/gt/intel_context.h | 13 ++ drivers/gpu/drm/i915/gt/intel_context_types.h | 3 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- drivers/gpu/drm/i915/gt/intel_lrc.c | 5 +- drivers/gpu/drm/i915/gt/intel_renderstate.c | 2 +- drivers/gpu/drm/i915/gt/intel_ring.c | 10 +- drivers/gpu/drm/i915/gt/intel_ring.h | 3 +- .../gpu/drm/i915/gt/intel_ring_submission.c | 15 +- drivers/gpu/drm/i915/gt/intel_timeline.c | 12 +- drivers/gpu/drm/i915/gt/intel_timeline.h | 3 +- drivers/gpu/drm/i915/gt/mock_engine.c | 3 +- drivers/gpu/drm/i915/gt/selftest_lrc.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 13 +- drivers/gpu/drm/i915/i915_gem.c | 11 +- drivers/gpu/drm/i915/i915_vma.c | 13 +- drivers/gpu/drm/i915/i915_vma.h | 13 +- 26 files changed, 217 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 27c0a2140441d..c8b1dd1a9e467 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3451,7 +3451,7 @@ initial_plane_vma(struct drm_i915_private *i915, if (IS_ERR(vma)) goto err_obj; - if (i915_ggtt_pin(vma, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) + if (i915_ggtt_pin(vma, NULL, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) goto err_obj; if (i915_gem_object_is_tiled(obj) && diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 34c8b0dd85e0e..cf5ecbde9e069 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1154,7 +1154,7 @@ static int context_barrier_task(struct i915_gem_context *ctx, i915_gem_ww_ctx_init(&ww, true); retry: - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &ww); if (err) goto err; @@ -1247,7 +1247,7 @@ static int pin_ppgtt_update(struct intel_context *ce, struct i915_gem_ww_ctx *ww if (!HAS_LOGICAL_RING_CONTEXTS(vm->i915)) /* ppGTT is not part of the legacy context image */ - return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm)); + return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm), ww); return 0; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index d3c47390ef530..ae63748e90bdd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -436,16 +436,17 @@ eb_pin_vma(struct i915_execbuffer *eb, pin_flags |= PIN_GLOBAL; /* Attempt to reuse the current location if available */ - if (unlikely(i915_vma_pin(vma, 0, 0, pin_flags))) { + /* TODO: Add -EDEADLK handling here */ + if (unlikely(i915_vma_pin_ww(vma, &eb->ww, 0, 0, pin_flags))) { if (entry->flags & EXEC_OBJECT_PINNED) return false; /* Failing that pick any _free_ space if suitable */ - if (unlikely(i915_vma_pin(vma, - entry->pad_to_size, - entry->alignment, - eb_pin_flags(entry, ev->flags) | - PIN_USER | PIN_NOEVICT))) + if (unlikely(i915_vma_pin_ww(vma, &eb->ww, + entry->pad_to_size, + entry->alignment, + eb_pin_flags(entry, ev->flags) | + PIN_USER | PIN_NOEVICT))) return false; } @@ -586,7 +587,7 @@ static inline int use_cpu_reloc(const struct reloc_cache *cache, obj->cache_level != I915_CACHE_NONE); } -static int eb_reserve_vma(const struct i915_execbuffer *eb, +static int eb_reserve_vma(struct i915_execbuffer *eb, struct eb_vma *ev, u64 pin_flags) { @@ -601,7 +602,7 @@ static int eb_reserve_vma(const struct i915_execbuffer *eb, return err; } - err = i915_vma_pin(vma, + err = i915_vma_pin_ww(vma, &eb->ww, entry->pad_to_size, entry->alignment, eb_pin_flags(entry, ev->flags) | pin_flags); if (err) @@ -1132,9 +1133,10 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, } static void *reloc_iomap(struct drm_i915_gem_object *obj, - struct reloc_cache *cache, + struct i915_execbuffer *eb, unsigned long page) { + struct reloc_cache *cache = &eb->reloc_cache; struct i915_ggtt *ggtt = cache_to_ggtt(cache); unsigned long offset; void *vaddr; @@ -1156,10 +1158,13 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (err) return ERR_PTR(err); - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | - PIN_NONBLOCK /* NOWARN */ | - PIN_NOEVICT); + vma = i915_gem_object_ggtt_pin_ww(obj, &eb->ww, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (vma == ERR_PTR(-EDEADLK)) + return vma; + if (IS_ERR(vma)) { memset(&cache->node, 0, sizeof(cache->node)); mutex_lock(&ggtt->vm.mutex); @@ -1195,9 +1200,10 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, } static void *reloc_vaddr(struct drm_i915_gem_object *obj, - struct reloc_cache *cache, + struct i915_execbuffer *eb, unsigned long page) { + struct reloc_cache *cache = &eb->reloc_cache; void *vaddr; if (cache->page == page) { @@ -1205,7 +1211,7 @@ static void *reloc_vaddr(struct drm_i915_gem_object *obj, } else { vaddr = NULL; if ((cache->vaddr & KMAP) == 0) - vaddr = reloc_iomap(obj, cache, page); + vaddr = reloc_iomap(obj, eb, page); if (!vaddr) vaddr = reloc_kmap(obj, cache, page); } @@ -1292,7 +1298,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, goto err_unmap; } - err = i915_vma_pin(batch, 0, 0, PIN_USER | PIN_NONBLOCK); + err = i915_vma_pin_ww(batch, &eb->ww, 0, 0, PIN_USER | PIN_NONBLOCK); if (err) goto err_unmap; @@ -1313,7 +1319,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, eb->reloc_context = ce; } - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &eb->ww); if (err) goto err_unpin; @@ -1536,8 +1542,7 @@ relocate_entry(struct i915_vma *vma, void *vaddr; repeat: - vaddr = reloc_vaddr(vma->obj, - &eb->reloc_cache, + vaddr = reloc_vaddr(vma->obj, eb, offset >> PAGE_SHIFT); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -1953,6 +1958,7 @@ static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb, rq = eb_pin_engine(eb, false); if (IS_ERR(rq)) { err = PTR_ERR(rq); + rq = NULL; goto err; } @@ -2236,7 +2242,8 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq) } static struct i915_vma * -shadow_batch_pin(struct drm_i915_gem_object *obj, +shadow_batch_pin(struct i915_execbuffer *eb, + struct drm_i915_gem_object *obj, struct i915_address_space *vm, unsigned int flags) { @@ -2247,7 +2254,7 @@ shadow_batch_pin(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return vma; - err = i915_vma_pin(vma, 0, 0, flags); + err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, flags); if (err) return ERR_PTR(err); @@ -2397,16 +2404,33 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb, return err; } +static struct i915_vma *eb_dispatch_secure(struct i915_execbuffer *eb, struct i915_vma *vma) +{ + /* + * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure + * batch" bit. Hence we need to pin secure batches into the global gtt. + * hsw should have this fixed, but bdw mucks it up again. */ + if (eb->batch_flags & I915_DISPATCH_SECURE) + return i915_gem_object_ggtt_pin_ww(vma->obj, &eb->ww, NULL, 0, 0, 0); + + return NULL; +} + static int eb_parse(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; struct intel_gt_buffer_pool_node *pool = eb->batch_pool; - struct i915_vma *shadow, *trampoline; + struct i915_vma *shadow, *trampoline, *batch; unsigned int len; int err; - if (!eb_use_cmdparser(eb)) - return 0; + if (!eb_use_cmdparser(eb)) { + batch = eb_dispatch_secure(eb, eb->batch->vma); + if (IS_ERR(batch)) + return PTR_ERR(batch); + + goto secure_batch; + } len = eb->batch_len; if (!CMDPARSER_USES_GGTT(eb->i915)) { @@ -2434,7 +2458,7 @@ static int eb_parse(struct i915_execbuffer *eb) if (err) goto err; - shadow = shadow_batch_pin(pool->obj, eb->context->vm, PIN_USER); + shadow = shadow_batch_pin(eb, pool->obj, eb->context->vm, PIN_USER); if (IS_ERR(shadow)) { err = PTR_ERR(shadow); goto err; @@ -2446,7 +2470,7 @@ static int eb_parse(struct i915_execbuffer *eb) if (CMDPARSER_USES_GGTT(eb->i915)) { trampoline = shadow; - shadow = shadow_batch_pin(pool->obj, + shadow = shadow_batch_pin(eb, pool->obj, &eb->engine->gt->ggtt->vm, PIN_GLOBAL); if (IS_ERR(shadow)) { @@ -2459,19 +2483,34 @@ static int eb_parse(struct i915_execbuffer *eb) eb->batch_flags |= I915_DISPATCH_SECURE; } + batch = eb_dispatch_secure(eb, shadow); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto err_trampoline; + } + err = eb_parse_pipeline(eb, shadow, trampoline); if (err) - goto err_trampoline; + goto err_unpin_batch; - eb->vma[eb->buffer_count].vma = i915_vma_get(shadow); - eb->vma[eb->buffer_count].flags = __EXEC_OBJECT_HAS_PIN; eb->batch = &eb->vma[eb->buffer_count++]; + eb->batch->vma = i915_vma_get(shadow); + eb->batch->flags = __EXEC_OBJECT_HAS_PIN; eb->trampoline = trampoline; eb->batch_start_offset = 0; +secure_batch: + if (batch) { + eb->batch = &eb->vma[eb->buffer_count++]; + eb->batch->flags = __EXEC_OBJECT_HAS_PIN; + eb->batch->vma = i915_vma_get(batch); + } return 0; +err_unpin_batch: + if (batch) + i915_vma_unpin(batch); err_trampoline: if (trampoline) i915_vma_unpin(trampoline); @@ -2613,7 +2652,7 @@ static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, bool throt * GGTT space, so do this first before we reserve a seqno for * ourselves. */ - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &eb->ww); if (err) return ERR_PTR(err); @@ -3231,33 +3270,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, ww_acquire_done(&eb.ww.ctx); - /* - * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure - * batch" bit. Hence we need to pin secure batches into the global gtt. - * hsw should have this fixed, but bdw mucks it up again. */ - if (eb.batch_flags & I915_DISPATCH_SECURE) { - struct i915_vma *vma; - - /* - * So on first glance it looks freaky that we pin the batch here - * outside of the reservation loop. But: - * - The batch is already pinned into the relevant ppgtt, so we - * already have the backing storage fully allocated. - * - No other BO uses the global gtt (well contexts, but meh), - * so we don't really have issues with multiple objects not - * fitting due to fragmentation. - * So this is actually safe. - */ - vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err_vma; - } - - batch = vma; - } else { - batch = eb.batch->vma; - } + batch = eb.batch->vma; /* All GPU relocation batches must be submitted prior to the user rq */ GEM_BUG_ON(eb.reloc_cache.rq); @@ -3266,7 +3279,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.request = i915_request_create(eb.context); if (IS_ERR(eb.request)) { err = PTR_ERR(eb.request); - goto err_batch_unpin; + goto err_vma; } if (in_fence) { @@ -3327,9 +3340,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, } i915_request_put(eb.request); -err_batch_unpin: - if (eb.batch_flags & I915_DISPATCH_SECURE) - i915_vma_unpin(batch); err_vma: eb_release_vmas(&eb, true); if (eb.trampoline) @@ -3417,7 +3427,9 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, /* Copy in the exec list from userland */ exec_list = kvmalloc_array(count, sizeof(*exec_list), __GFP_NOWARN | GFP_KERNEL); - exec2_list = kvmalloc_array(count + 1, eb_element_size(), + + /* Allocate extra slots for use by the command parser */ + exec2_list = kvmalloc_array(count + 2, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec_list == NULL || exec2_list == NULL) { drm_dbg(&i915->drm, @@ -3494,8 +3506,8 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, if (err) return err; - /* Allocate an extra slot for use by the command parser */ - exec2_list = kvmalloc_array(count + 1, eb_element_size(), + /* Allocate extra slots for use by the command parser */ + exec2_list = kvmalloc_array(count + 2, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec2_list == NULL) { drm_dbg(&i915->drm, "Failed to allocate exec list for %zd buffers\n", diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 563839cbaf1c1..e1d50a5a1477c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -36,7 +36,7 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, if (err) return err; - err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH); + err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, PIN_USER | PIN_HIGH); if (err) return err; @@ -139,7 +139,7 @@ static int igt_gpu_reloc(void *arg) i915_gem_ww_ctx_init(&eb.ww, false); retry: - err = intel_context_pin(eb.context); + err = intel_context_pin_ww(eb.context, &eb.ww); if (!err) { err = __igt_gpu_reloc(&eb, scratch); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index 7e5a86b774a7a..fd0d24d28763f 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -368,7 +368,7 @@ static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size) return vma; } -int gen6_ppgtt_pin(struct i915_ppgtt *base) +int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww) { struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base); int err; @@ -394,7 +394,7 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base) */ err = 0; if (!atomic_read(&ppgtt->pin_count)) - err = i915_ggtt_pin(ppgtt->vma, GEN6_PD_ALIGN, PIN_HIGH); + err = i915_ggtt_pin(ppgtt->vma, ww, GEN6_PD_ALIGN, PIN_HIGH); if (!err) atomic_inc(&ppgtt->pin_count); mutex_unlock(&ppgtt->pin_mutex); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h index 7249672e5802d..3357228f3304a 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h @@ -8,6 +8,8 @@ #include "intel_gtt.h" +struct i915_gem_ww_ctx; + struct gen6_ppgtt { struct i915_ppgtt base; @@ -67,7 +69,7 @@ static inline struct gen6_ppgtt *to_gen6_ppgtt(struct i915_ppgtt *base) (pt = i915_pt_entry(pd, iter), true); \ ++iter) -int gen6_ppgtt_pin(struct i915_ppgtt *base); +int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww); void gen6_ppgtt_unpin(struct i915_ppgtt *base); void gen6_ppgtt_unpin_all(struct i915_ppgtt *base); void gen6_ppgtt_enable(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index efe9a7a89edea..c05ef213bdc21 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -93,12 +93,12 @@ static void intel_context_active_release(struct intel_context *ce) i915_active_release(&ce->active); } -static int __context_pin_state(struct i915_vma *vma) +static int __context_pin_state(struct i915_vma *vma, struct i915_gem_ww_ctx *ww) { unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; int err; - err = i915_ggtt_pin(vma, 0, bias | PIN_HIGH); + err = i915_ggtt_pin(vma, ww, 0, bias | PIN_HIGH); if (err) return err; @@ -127,11 +127,12 @@ static void __context_unpin_state(struct i915_vma *vma) __i915_vma_unpin(vma); } -static int __ring_active(struct intel_ring *ring) +static int __ring_active(struct intel_ring *ring, + struct i915_gem_ww_ctx *ww) { int err; - err = intel_ring_pin(ring); + err = intel_ring_pin(ring, ww); if (err) return err; @@ -152,24 +153,25 @@ static void __ring_retire(struct intel_ring *ring) intel_ring_unpin(ring); } -static int intel_context_pre_pin(struct intel_context *ce) +static int intel_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) { int err; CE_TRACE(ce, "active\n"); - err = __ring_active(ce->ring); + err = __ring_active(ce->ring, ww); if (err) return err; - err = intel_timeline_pin(ce->timeline); + err = intel_timeline_pin(ce->timeline, ww); if (err) goto err_ring; if (!ce->state) return 0; - err = __context_pin_state(ce->state); + err = __context_pin_state(ce->state, ww); if (err) goto err_timeline; @@ -192,7 +194,8 @@ static void intel_context_post_unpin(struct intel_context *ce) __ring_retire(ce->ring); } -int __intel_context_do_pin(struct intel_context *ce) +int __intel_context_do_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) { bool handoff = false; void *vaddr; @@ -209,7 +212,14 @@ int __intel_context_do_pin(struct intel_context *ce) * refcount for __intel_context_active(), which prevent a lock * inversion of ce->pin_mutex vs dma_resv_lock(). */ - err = intel_context_pre_pin(ce); + + err = i915_gem_object_lock(ce->timeline->hwsp_ggtt->obj, ww); + if (!err && ce->ring->vma->obj) + err = i915_gem_object_lock(ce->ring->vma->obj, ww); + if (!err && ce->state) + err = i915_gem_object_lock(ce->state->obj, ww); + if (!err) + err = intel_context_pre_pin(ce, ww); if (err) return err; @@ -217,7 +227,7 @@ int __intel_context_do_pin(struct intel_context *ce) if (err) goto err_ctx_unpin; - err = ce->ops->pre_pin(ce, &vaddr); + err = ce->ops->pre_pin(ce, ww, &vaddr); if (err) goto err_release; @@ -264,6 +274,23 @@ int __intel_context_do_pin(struct intel_context *ce) return err; } +int __intel_context_do_pin(struct intel_context *ce) +{ + struct i915_gem_ww_ctx ww; + int err; + + i915_gem_ww_ctx_init(&ww, true); +retry: + err = __intel_context_do_pin_ww(ce, &ww); + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + return err; +} + void intel_context_unpin(struct intel_context *ce) { if (!atomic_dec_and_test(&ce->pin_count)) @@ -301,18 +328,14 @@ static void __intel_context_retire(struct i915_active *active) static int __intel_context_active(struct i915_active *active) { struct intel_context *ce = container_of(active, typeof(*ce), active); - int err; intel_context_get(ce); /* everything should already be activated by intel_context_pre_pin() */ - err = __ring_active(ce->ring); - if (GEM_WARN_ON(err)) - goto err_put; + GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->ring->vma->active)); + __intel_ring_pin(ce->ring); - err = intel_timeline_pin(ce->timeline); - if (GEM_WARN_ON(err)) - goto err_ring; + __intel_timeline_pin(ce->timeline); if (ce->state) { GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active)); @@ -321,12 +344,6 @@ static int __intel_context_active(struct i915_active *active) } return 0; - -err_ring: - __ring_retire(ce->ring); -err_put: - intel_context_put(ce); - return err; } void diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 07be021882ccd..fda2eba81e222 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -25,6 +25,8 @@ ##__VA_ARGS__); \ } while (0) +struct i915_gem_ww_ctx; + void intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine); void intel_context_fini(struct intel_context *ce); @@ -81,6 +83,8 @@ static inline void intel_context_unlock_pinned(struct intel_context *ce) } int __intel_context_do_pin(struct intel_context *ce); +int __intel_context_do_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww); static inline bool intel_context_pin_if_active(struct intel_context *ce) { @@ -95,6 +99,15 @@ static inline int intel_context_pin(struct intel_context *ce) return __intel_context_do_pin(ce); } +static inline int intel_context_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) +{ + if (likely(intel_context_pin_if_active(ce))) + return 0; + + return __intel_context_do_pin_ww(ce, ww); +} + static inline void __intel_context_pin(struct intel_context *ce) { GEM_BUG_ON(!intel_context_is_pinned(ce)); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index ca8e05b4d3efc..552cb57a2e8cd 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -23,6 +23,7 @@ DECLARE_EWMA(runtime, 3, 8); struct i915_gem_context; +struct i915_gem_ww_ctx; struct i915_vma; struct intel_context; struct intel_ring; @@ -30,7 +31,7 @@ struct intel_ring; struct intel_context_ops { int (*alloc)(struct intel_context *ce); - int (*pre_pin)(struct intel_context *ce, void **vaddr); + int (*pre_pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void **vaddr); int (*pin)(struct intel_context *ce, void *vaddr); void (*unpin)(struct intel_context *ce); void (*post_unpin)(struct intel_context *ce); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index ea4ba2afe9f96..f231edd3fa3aa 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -635,7 +635,7 @@ static int pin_ggtt_status_page(struct intel_engine_cs *engine, else flags = PIN_HIGH; - return i915_ggtt_pin(vma, 0, flags); + return i915_ggtt_pin(vma, NULL, 0, flags); } static int init_status_page(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8694ddbdac4cc..39b428c5049c0 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -356,7 +356,7 @@ static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) goto err_unref; } - ret = i915_ggtt_pin(vma, 0, PIN_HIGH); + ret = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (ret) goto err_unref; diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 1f6dc69b24900..47a90dbf8b70c 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3461,7 +3461,8 @@ __execlists_update_reg_state(const struct intel_context *ce, } static int -execlists_context_pre_pin(struct intel_context *ce, void **vaddr) +execlists_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, void **vaddr) { GEM_BUG_ON(!ce->state); GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); @@ -3880,7 +3881,7 @@ static int lrc_setup_wa_ctx(struct intel_engine_cs *engine) goto err; } - err = i915_ggtt_pin(vma, 0, PIN_HIGH); + err = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (err) goto err; diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c index 5164de04049d2..ea2a77c7b4692 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.c +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c @@ -184,7 +184,7 @@ int intel_renderstate_init(struct intel_renderstate *so, i915_gem_ww_ctx_init(&so->ww, true); retry: - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &so->ww); if (err) goto err_fini; diff --git a/drivers/gpu/drm/i915/gt/intel_ring.c b/drivers/gpu/drm/i915/gt/intel_ring.c index bdb324167ef33..4034a4bac7f08 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.c +++ b/drivers/gpu/drm/i915/gt/intel_ring.c @@ -21,7 +21,13 @@ unsigned int intel_ring_update_space(struct intel_ring *ring) return space; } -int intel_ring_pin(struct intel_ring *ring) +void __intel_ring_pin(struct intel_ring *ring) +{ + GEM_BUG_ON(!atomic_read(&ring->pin_count)); + atomic_inc(&ring->pin_count); +} + +int intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww) { struct i915_vma *vma = ring->vma; unsigned int flags; @@ -39,7 +45,7 @@ int intel_ring_pin(struct intel_ring *ring) else flags |= PIN_HIGH; - ret = i915_ggtt_pin(vma, 0, flags); + ret = i915_ggtt_pin(vma, ww, 0, flags); if (unlikely(ret)) goto err_unpin; diff --git a/drivers/gpu/drm/i915/gt/intel_ring.h b/drivers/gpu/drm/i915/gt/intel_ring.h index cc0ebca65167f..1700579bdc93d 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.h +++ b/drivers/gpu/drm/i915/gt/intel_ring.h @@ -21,7 +21,8 @@ int intel_ring_cacheline_align(struct i915_request *rq); unsigned int intel_ring_update_space(struct intel_ring *ring); -int intel_ring_pin(struct intel_ring *ring); +void __intel_ring_pin(struct intel_ring *ring); +int intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww); void intel_ring_unpin(struct intel_ring *ring); void intel_ring_reset(struct intel_ring *ring, u32 tail); diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 93cf72cfd3181..1ca1bac81cf61 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -477,14 +477,16 @@ static void ring_context_destroy(struct kref *ref) intel_context_free(ce); } -static int __context_pin_ppgtt(struct intel_context *ce) +static int ring_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, + void **unused) { struct i915_address_space *vm; int err = 0; vm = vm_alias(ce->vm); if (vm) - err = gen6_ppgtt_pin(i915_vm_to_ppgtt((vm))); + err = gen6_ppgtt_pin(i915_vm_to_ppgtt((vm)), ww); return err; } @@ -591,11 +593,6 @@ static int ring_context_alloc(struct intel_context *ce) return 0; } -static int ring_context_pre_pin(struct intel_context *ce, void **unused) -{ - return __context_pin_ppgtt(ce); -} - static int ring_context_pin(struct intel_context *ce, void *unused) { return 0; @@ -1272,7 +1269,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) } GEM_BUG_ON(timeline->has_initial_breadcrumb); - err = intel_timeline_pin(timeline); + err = intel_timeline_pin(timeline, NULL); if (err) goto err_timeline; @@ -1282,7 +1279,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) goto err_timeline_unpin; } - err = intel_ring_pin(ring); + err = intel_ring_pin(ring, NULL); if (err) goto err_ring; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 2baecf414acb4..a2f74cefe4c3f 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -317,14 +317,20 @@ __intel_timeline_create(struct intel_gt *gt, return timeline; } -int intel_timeline_pin(struct intel_timeline *tl) +void __intel_timeline_pin(struct intel_timeline *tl) +{ + GEM_BUG_ON(!atomic_read(&tl->pin_count)); + atomic_inc(&tl->pin_count); +} + +int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww) { int err; if (atomic_add_unless(&tl->pin_count, 1, 0)) return 0; - err = i915_ggtt_pin(tl->hwsp_ggtt, 0, PIN_HIGH); + err = i915_ggtt_pin(tl->hwsp_ggtt, ww, 0, PIN_HIGH); if (err) return err; @@ -467,7 +473,7 @@ __intel_timeline_get_seqno(struct intel_timeline *tl, goto err_rollback; } - err = i915_ggtt_pin(vma, 0, PIN_HIGH); + err = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (err) { __idle_hwsp_free(vma->private, cacheline); goto err_rollback; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.h b/drivers/gpu/drm/i915/gt/intel_timeline.h index 06bd06c6595fe..9882cd911d8ed 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline.h @@ -88,7 +88,8 @@ static inline bool intel_timeline_sync_is_later(struct intel_timeline *tl, return __intel_timeline_sync_is_later(tl, fence->context, fence->seqno); } -int intel_timeline_pin(struct intel_timeline *tl); +void __intel_timeline_pin(struct intel_timeline *tl); +int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww); void intel_timeline_enter(struct intel_timeline *tl); int intel_timeline_get_seqno(struct intel_timeline *tl, struct i915_request *rq, diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index c8e631222f236..dfd1cfb8a7ec5 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -167,7 +167,8 @@ static int mock_context_alloc(struct intel_context *ce) return 0; } -static int mock_context_pre_pin(struct intel_context *ce, void **unused) +static int mock_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, void **unused) { return 0; } diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index f749071f54a7f..7faba9f912244 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -3089,7 +3089,7 @@ static struct i915_vma *create_global(struct intel_gt *gt, size_t sz) return vma; } - err = i915_ggtt_pin(vma, 0, 0); + err = i915_ggtt_pin(vma, NULL, 0, 0); if (err) { i915_vma_put(vma); return ERR_PTR(err); diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 98ceac2fb77de..96d164a3841dc 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -455,7 +455,7 @@ tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value) struct i915_request *rq; int err; - err = intel_timeline_pin(tl); + err = intel_timeline_pin(tl, NULL); if (err) { rq = ERR_PTR(err); goto out; @@ -667,7 +667,7 @@ static int live_hwsp_wrap(void *arg) if (!tl->has_initial_breadcrumb || !tl->hwsp_cacheline) goto out_free; - err = intel_timeline_pin(tl); + err = intel_timeline_pin(tl, NULL); if (err) goto out_free; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 861657897c0f9..942c7c187adba 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -677,7 +677,7 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) goto err; flags = PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma); - ret = i915_ggtt_pin(vma, 0, flags); + ret = i915_ggtt_pin(vma, NULL, 0, flags); if (ret) { vma = ERR_PTR(ret); goto err; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b95467b760ad..ab17084af0ff4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1816,11 +1816,18 @@ static inline void i915_gem_drain_workqueue(struct drm_i915_private *i915) } struct i915_vma * __must_check +i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + const struct i915_ggtt_view *view, + u64 size, u64 alignment, u64 flags); + +static inline struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags); + u64 size, u64 alignment, u64 flags) +{ + return i915_gem_object_ggtt_pin_ww(obj, NULL, view, size, alignment, flags); +} int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f6615d942b60f..bb0c12975f38e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -962,11 +962,10 @@ static void discard_ggtt_vma(struct i915_vma *vma) } struct i915_vma * -i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags) +i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + const struct i915_ggtt_view *view, + u64 size, u64 alignment, u64 flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_ggtt *ggtt = &i915->ggtt; @@ -1032,7 +1031,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, return ERR_PTR(ret); } - ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL); + ret = i915_vma_pin_ww(vma, ww, size, alignment, flags | PIN_GLOBAL); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index c6bf04ca20328..495d28f6d1601 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -852,13 +852,19 @@ static void vma_unbind_pages(struct i915_vma *vma) __vma_put_pages(vma, count | count << I915_VMA_PAGES_BIAS); } -int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) +int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u64 size, u64 alignment, u64 flags) { struct i915_vma_work *work = NULL; intel_wakeref_t wakeref = 0; unsigned int bound; int err; +#ifdef CONFIG_PROVE_LOCKING + if (debug_locks && lockdep_is_held(&vma->vm->i915->drm.struct_mutex)) + WARN_ON(!ww); +#endif + BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND); BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND); @@ -1002,7 +1008,8 @@ static void flush_idle_contexts(struct intel_gt *gt) intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT); } -int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags) +int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u32 align, unsigned int flags) { struct i915_address_space *vm = vma->vm; int err; @@ -1010,7 +1017,7 @@ int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags) GEM_BUG_ON(!i915_vma_is_ggtt(vma)); do { - err = i915_vma_pin(vma, 0, align, flags | PIN_GLOBAL); + err = i915_vma_pin_ww(vma, ww, 0, align, flags | PIN_GLOBAL); if (err != -ENOSPC) { if (!err) { err = i915_vma_wait_for_bind(vma); diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index d0d01f9095486..5b3a3c6534540 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -237,8 +237,17 @@ static inline void i915_vma_unlock(struct i915_vma *vma) } int __must_check -i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags); -int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags); +i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u64 size, u64 alignment, u64 flags); + +static inline int __must_check +i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) +{ + return i915_vma_pin_ww(vma, NULL, size, alignment, flags); +} + +int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u32 align, unsigned int flags); static inline int i915_vma_pin_count(const struct i915_vma *vma) { -- GitLab From 6b05030496f773f35f24299b1bd49dc8aa10a580 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:55 +0200 Subject: [PATCH 0837/1494] drm/i915: Convert i915_gem_object/client_blt.c to use ww locking as well, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the last part outside of selftests that still don't use the correct lock ordering of timeline->mutex vs resv_lock. With gem fixed, there are a few places that still get locking wrong: - gvt/scheduler.c - i915_perf.c - Most if not all selftests. Changes since v1: - Add intel_engine_pm_get/put() calls to fix use-after-free when using intel_engine_get_pool(). Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-16-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../gpu/drm/i915/gem/i915_gem_client_blt.c | 78 +++++++-- .../gpu/drm/i915/gem/i915_gem_object_blt.c | 152 ++++++++++++------ .../gpu/drm/i915/gem/i915_gem_object_blt.h | 3 + 3 files changed, 163 insertions(+), 70 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index a85907f29c538..272cf3ea68d56 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -158,6 +158,7 @@ static void clear_pages_worker(struct work_struct *work) struct clear_pages_work *w = container_of(work, typeof(*w), work); struct drm_i915_gem_object *obj = w->sleeve->vma->obj; struct i915_vma *vma = w->sleeve->vma; + struct i915_gem_ww_ctx ww; struct i915_request *rq; struct i915_vma *batch; int err = w->dma.error; @@ -173,17 +174,20 @@ static void clear_pages_worker(struct work_struct *work) obj->read_domains = I915_GEM_GPU_DOMAINS; obj->write_domain = 0; - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (unlikely(err)) + i915_gem_ww_ctx_init(&ww, false); + intel_engine_pm_get(w->ce->engine); +retry: + err = intel_context_pin_ww(w->ce, &ww); + if (err) goto out_signal; - batch = intel_emit_vma_fill_blt(w->ce, vma, w->value); + batch = intel_emit_vma_fill_blt(w->ce, vma, &ww, w->value); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto out_unpin; + goto out_ctx; } - rq = intel_context_create_request(w->ce); + rq = i915_request_create(w->ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -225,9 +229,19 @@ static void clear_pages_worker(struct work_struct *work) i915_request_add(rq); out_batch: intel_emit_vma_release(w->ce, batch); -out_unpin: - i915_vma_unpin(vma); +out_ctx: + intel_context_unpin(w->ce); out_signal: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + i915_vma_unpin(w->sleeve->vma); + intel_engine_pm_put(w->ce->engine); + if (unlikely(err)) { dma_fence_set_error(&w->dma, err); dma_fence_signal(&w->dma); @@ -235,6 +249,44 @@ static void clear_pages_worker(struct work_struct *work) } } +static int pin_wait_clear_pages_work(struct clear_pages_work *w, + struct intel_context *ce) +{ + struct i915_vma *vma = w->sleeve->vma; + struct i915_gem_ww_ctx ww; + int err; + + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out; + + err = i915_sw_fence_await_reservation(&w->wait, + vma->obj->base.resv, NULL, + true, 0, I915_FENCE_GFP); + if (err) + goto err_unpin_vma; + + dma_resv_add_excl_fence(vma->obj->base.resv, &w->dma); + +err_unpin_vma: + if (err) + i915_vma_unpin(vma); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + return err; +} + static int __i915_sw_fence_call clear_pages_work_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) @@ -288,17 +340,9 @@ int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj, dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0); i915_sw_fence_init(&work->wait, clear_pages_work_notify); - i915_gem_object_lock(obj, NULL); - err = i915_sw_fence_await_reservation(&work->wait, - obj->base.resv, NULL, true, 0, - I915_FENCE_GFP); - if (err < 0) { + err = pin_wait_clear_pages_work(work, ce); + if (err < 0) dma_fence_set_error(&work->dma, err); - } else { - dma_resv_add_excl_fence(obj->base.resv, &work->dma); - err = 0; - } - i915_gem_object_unlock(obj); dma_fence_get(&work->dma); i915_sw_fence_commit(&work->wait); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c index bfdb32d46877b..d93eb36160c90 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c @@ -14,6 +14,7 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, struct i915_vma *vma, + struct i915_gem_ww_ctx *ww, u32 value) { struct drm_i915_private *i915 = ce->vm->i915; @@ -39,10 +40,24 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, goto out_pm; } + err = i915_gem_object_lock(pool->obj, ww); + if (err) + goto out_put; + + batch = i915_vma_instance(pool->obj, ce->vm, NULL); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto out_put; + } + + err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out_put; + cmd = i915_gem_object_pin_map(pool->obj, I915_MAP_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_put; + goto out_unpin; } rem = vma->size; @@ -84,19 +99,11 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, intel_gt_chipset_flush(ce->vm->gt); - batch = i915_vma_instance(pool->obj, ce->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_put; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER); - if (unlikely(err)) - goto out_put; - batch->private = pool; return batch; +out_unpin: + i915_vma_unpin(batch); out_put: intel_gt_buffer_pool_put(pool); out_pm: @@ -108,11 +115,9 @@ int intel_emit_vma_mark_active(struct i915_vma *vma, struct i915_request *rq) { int err; - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (err == 0) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); if (unlikely(err)) return err; @@ -141,6 +146,7 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, struct intel_context *ce, u32 value) { + struct i915_gem_ww_ctx ww; struct i915_request *rq; struct i915_vma *batch; struct i915_vma *vma; @@ -150,17 +156,28 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (unlikely(err)) - return err; + i915_gem_ww_ctx_init(&ww, true); + intel_engine_pm_get(ce->engine); +retry: + err = i915_gem_object_lock(obj, &ww); + if (err) + goto out; - batch = intel_emit_vma_fill_blt(ce, vma, value); + err = intel_context_pin_ww(ce, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (err) + goto out_ctx; + + batch = intel_emit_vma_fill_blt(ce, vma, &ww, value); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto out_unpin; + goto out_vma; } - rq = intel_context_create_request(ce); + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -170,11 +187,9 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, if (unlikely(err)) goto out_request; - i915_vma_lock(vma); err = move_obj_to_gpu(vma->obj, rq, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); if (unlikely(err)) goto out_request; @@ -193,8 +208,18 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, i915_request_add(rq); out_batch: intel_emit_vma_release(ce, batch); -out_unpin: +out_vma: i915_vma_unpin(vma); +out_ctx: + intel_context_unpin(ce); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); return err; } @@ -210,6 +235,7 @@ static bool wa_1209644611_applies(struct drm_i915_private *i915, u32 size) } struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, struct i915_vma *src, struct i915_vma *dst) { @@ -236,10 +262,24 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, goto out_pm; } + err = i915_gem_object_lock(pool->obj, ww); + if (err) + goto out_put; + + batch = i915_vma_instance(pool->obj, ce->vm, NULL); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto out_put; + } + + err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out_put; + cmd = i915_gem_object_pin_map(pool->obj, I915_MAP_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_put; + goto out_unpin; } rem = src->size; @@ -296,20 +336,11 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, i915_gem_object_unpin_map(pool->obj); intel_gt_chipset_flush(ce->vm->gt); - - batch = i915_vma_instance(pool->obj, ce->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_put; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER); - if (unlikely(err)) - goto out_put; - batch->private = pool; return batch; +out_unpin: + i915_vma_unpin(batch); out_put: intel_gt_buffer_pool_put(pool); out_pm: @@ -321,10 +352,9 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, struct drm_i915_gem_object *dst, struct intel_context *ce) { - struct drm_gem_object *objs[] = { &src->base, &dst->base }; struct i915_address_space *vm = ce->vm; struct i915_vma *vma[2], *batch; - struct ww_acquire_ctx acquire; + struct i915_gem_ww_ctx ww; struct i915_request *rq; int err, i; @@ -332,25 +362,36 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, if (IS_ERR(vma[0])) return PTR_ERR(vma[0]); - err = i915_vma_pin(vma[0], 0, 0, PIN_USER); - if (unlikely(err)) - return err; - vma[1] = i915_vma_instance(dst, vm, NULL); if (IS_ERR(vma[1])) - goto out_unpin_src; + return PTR_ERR(vma); - err = i915_vma_pin(vma[1], 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, true); + intel_engine_pm_get(ce->engine); +retry: + err = i915_gem_object_lock(src, &ww); + if (!err) + err = i915_gem_object_lock(dst, &ww); + if (!err) + err = intel_context_pin_ww(ce, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma[0], &ww, 0, 0, PIN_USER); + if (err) + goto out_ctx; + + err = i915_vma_pin_ww(vma[1], &ww, 0, 0, PIN_USER); if (unlikely(err)) goto out_unpin_src; - batch = intel_emit_vma_copy_blt(ce, vma[0], vma[1]); + batch = intel_emit_vma_copy_blt(ce, &ww, vma[0], vma[1]); if (IS_ERR(batch)) { err = PTR_ERR(batch); goto out_unpin_dst; } - rq = intel_context_create_request(ce); + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -360,14 +401,10 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, if (unlikely(err)) goto out_request; - err = drm_gem_lock_reservations(objs, ARRAY_SIZE(objs), &acquire); - if (unlikely(err)) - goto out_request; - for (i = 0; i < ARRAY_SIZE(vma); i++) { err = move_obj_to_gpu(vma[i]->obj, rq, i); if (unlikely(err)) - goto out_unlock; + goto out_request; } for (i = 0; i < ARRAY_SIZE(vma); i++) { @@ -375,20 +412,19 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, err = i915_vma_move_to_active(vma[i], rq, flags); if (unlikely(err)) - goto out_unlock; + goto out_request; } if (rq->engine->emit_init_breadcrumb) { err = rq->engine->emit_init_breadcrumb(rq); if (unlikely(err)) - goto out_unlock; + goto out_request; } err = rq->engine->emit_bb_start(rq, batch->node.start, batch->node.size, 0); -out_unlock: - drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire); + out_request: if (unlikely(err)) i915_request_set_error_once(rq, err); @@ -400,6 +436,16 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, i915_vma_unpin(vma[1]); out_unpin_src: i915_vma_unpin(vma[0]); +out_ctx: + intel_context_unpin(ce); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); return err; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h index 8bcd336a90dc6..2409fdcccf0ed 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h @@ -13,12 +13,15 @@ #include "i915_vma.h" struct drm_i915_gem_object; +struct i915_gem_ww_ctx; struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, struct i915_vma *vma, + struct i915_gem_ww_ctx *ww, u32 value); struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, struct i915_vma *src, struct i915_vma *dst); -- GitLab From c8d225946a7803230ae48fead6652b6b5943233f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:56 +0200 Subject: [PATCH 0838/1494] drm/i915: Kill last user of intel_context_create_request outside of selftests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using intel_context_create_request(), use intel_context_pin() and i915_create_request directly. Now all those calls are gone outside of selftests. :) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-17-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 43 ++++++++++++++------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index be5a4685c9915..a3f72b75c61e7 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2088,6 +2088,7 @@ static int engine_wa_list_verify(struct intel_context *ce, const struct i915_wa *wa; struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; unsigned int i; u32 *results; int err; @@ -2100,29 +2101,34 @@ static int engine_wa_list_verify(struct intel_context *ce, return PTR_ERR(vma); intel_engine_pm_get(ce->engine); - rq = intel_context_create_request(ce); - intel_engine_pm_put(ce->engine); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err == 0) + err = intel_context_pin_ww(ce, &ww); + if (err) + goto err_pm; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_vma; + goto err_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - if (err) { - i915_request_add(rq); - goto err_vma; - } - - err = wa_list_srm(rq, wal, vma); - if (err) - goto err_vma; + if (err == 0) + err = wa_list_srm(rq, wal, vma); i915_request_get(rq); + if (err) + i915_request_set_error_once(rq, err); i915_request_add(rq); + + if (err) + goto err_rq; + if (i915_request_wait(rq, 0, HZ / 5) < 0) { err = -ETIME; goto err_rq; @@ -2147,7 +2153,16 @@ static int engine_wa_list_verify(struct intel_context *ce, err_rq: i915_request_put(rq); -err_vma: +err_unpin: + intel_context_unpin(ce); +err_pm: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); i915_vma_unpin(vma); i915_vma_put(vma); return err; -- GitLab From f00ecc2ef55861c3cbc3dde93c082b612114efdc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:57 +0200 Subject: [PATCH 0839/1494] drm/i915: Convert i915_perf to ww locking as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have the ordering of timeline->mutex vs resv_lock wrong, convert the i915_pin_vma and intel_context_pin as well to future-proof this. We may need to do future changes to do this more transaction-like, and only get down to a single i915_gem_ww_ctx, but for now this should work. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-18-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_perf.c | 57 +++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index c6f6370283cf4..e94976976571f 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1195,24 +1195,39 @@ static struct intel_context *oa_pin_context(struct i915_perf_stream *stream) struct i915_gem_engines_iter it; struct i915_gem_context *ctx = stream->ctx; struct intel_context *ce; - int err; + struct i915_gem_ww_ctx ww; + int err = -ENODEV; for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) { if (ce->engine != stream->engine) /* first match! */ continue; - /* - * As the ID is the gtt offset of the context's vma we - * pin the vma to ensure the ID remains fixed. - */ - err = intel_context_pin(ce); - if (err == 0) { - stream->pinned_ctx = ce; - break; - } + err = 0; + break; } i915_gem_context_unlock_engines(ctx); + if (err) + return ERR_PTR(err); + + i915_gem_ww_ctx_init(&ww, true); +retry: + /* + * As the ID is the gtt offset of the context's vma we + * pin the vma to ensure the ID remains fixed. + */ + err = intel_context_pin_ww(ce, &ww); + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + if (err) + return ERR_PTR(err); + + stream->pinned_ctx = ce; return stream->pinned_ctx; } @@ -1923,15 +1938,22 @@ emit_oa_config(struct i915_perf_stream *stream, { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; int err; vma = get_oa_vma(stream, oa_config); if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err) + goto err; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_GLOBAL | PIN_HIGH); if (err) - goto err_vma_put; + goto err; intel_engine_pm_get(ce->engine); rq = i915_request_create(ce); @@ -1953,11 +1975,9 @@ emit_oa_config(struct i915_perf_stream *stream, goto err_add_request; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, 0); if (!err) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); if (err) goto err_add_request; @@ -1971,7 +1991,14 @@ emit_oa_config(struct i915_perf_stream *stream, i915_request_add(rq); err_vma_unpin: i915_vma_unpin(vma); -err_vma_put: +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + + i915_gem_ww_ctx_fini(&ww); i915_vma_put(vma); return err; } -- GitLab From dd878c0cec75530ca3ffdb6c759f798eb91cc1df Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:58 +0200 Subject: [PATCH 0840/1494] drm/i915: Dirty hack to fix selftests locking inversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some i915 selftests still use i915_vma_lock() as inner lock, and intel_context_create_request() intel_timeline->mutex as outer lock. Fortunately for selftests this is not an issue, they should be fixed but we can move ahead and cleanify lockdep now. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-19-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_context.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index c05ef213bdc21..671081b0e4d63 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -459,6 +459,18 @@ struct i915_request *intel_context_create_request(struct intel_context *ce) rq = i915_request_create(ce); intel_context_unpin(ce); + if (IS_ERR(rq)) + return rq; + + /* + * timeline->mutex should be the inner lock, but is used as outer lock. + * Hack around this to shut up lockdep in selftests.. + */ + lockdep_unpin_lock(&ce->timeline->mutex, rq->cookie); + mutex_release(&ce->timeline->mutex.dep_map, _RET_IP_); + mutex_acquire(&ce->timeline->mutex.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_); + rq->cookie = lockdep_pin_lock(&ce->timeline->mutex); + return rq; } -- GitLab From 052e04f170561b38665fd227365c523347bdba03 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:08:59 +0200 Subject: [PATCH 0841/1494] drm/i915/selftests: Fix locking inversion in lrc selftest. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function does not use intel_context_create_request, so it has to use the same locking order as normal code. This is required to shut up lockdep in selftests. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-20-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/selftest_lrc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 7faba9f912244..95d41c01d0e04 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -4996,6 +4996,7 @@ static int __live_lrc_state(struct intel_engine_cs *engine, { struct intel_context *ce; struct i915_request *rq; + struct i915_gem_ww_ctx ww; enum { RING_START_IDX = 0, RING_TAIL_IDX, @@ -5010,7 +5011,11 @@ static int __live_lrc_state(struct intel_engine_cs *engine, if (IS_ERR(ce)) return PTR_ERR(ce); - err = intel_context_pin(ce); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(scratch->obj, &ww); + if (!err) + err = intel_context_pin_ww(ce, &ww); if (err) goto err_put; @@ -5039,11 +5044,9 @@ static int __live_lrc_state(struct intel_engine_cs *engine, *cs++ = i915_ggtt_offset(scratch) + RING_TAIL_IDX * sizeof(u32); *cs++ = 0; - i915_vma_lock(scratch); err = i915_request_await_object(rq, scratch->obj, true); if (!err) err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(scratch); i915_request_get(rq); i915_request_add(rq); @@ -5080,6 +5083,12 @@ static int __live_lrc_state(struct intel_engine_cs *engine, err_unpin: intel_context_unpin(ce); err_put: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); intel_context_put(ce); return err; } -- GitLab From 8a929c9eb1c298e7f12ce9062e57bd00d2c40bc3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:09:00 +0200 Subject: [PATCH 0842/1494] drm/i915: Use ww pinning for intel_context_create_request() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to get rid of intel_context_pin(), convert intel_context_create_request() first. :) Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-21-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_context.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 671081b0e4d63..61b05cd4c47ae 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -449,15 +449,25 @@ int intel_context_prepare_remote_request(struct intel_context *ce, struct i915_request *intel_context_create_request(struct intel_context *ce) { + struct i915_gem_ww_ctx ww; struct i915_request *rq; int err; - err = intel_context_pin(ce); - if (unlikely(err)) - return ERR_PTR(err); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = intel_context_pin_ww(ce, &ww); + if (!err) { + rq = i915_request_create(ce); + intel_context_unpin(ce); + } else if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } else { + rq = ERR_PTR(err); + } - rq = i915_request_create(ce); - intel_context_unpin(ce); + i915_gem_ww_ctx_fini(&ww); if (IS_ERR(rq)) return rq; -- GitLab From 15b6c92498704975b741a87c5c85d7b7f2489790 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:09:01 +0200 Subject: [PATCH 0843/1494] drm/i915: Move i915_vma_lock in the selftests to avoid lock inversion, v3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure vma_lock is not used as inner lock when kernel context is used, and add ww handling where appropriate. Ensure that execbuf selftests keep passing by using ww handling. Changes since v2: - Fix i915_gem_context finally. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-22-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- .../i915/gem/selftests/i915_gem_coherency.c | 26 +++-- .../drm/i915/gem/selftests/i915_gem_context.c | 106 +++++++++--------- .../drm/i915/gem/selftests/i915_gem_mman.c | 41 +++++-- drivers/gpu/drm/i915/gt/selftest_rps.c | 30 +++-- drivers/gpu/drm/i915/selftests/i915_request.c | 18 ++- 5 files changed, 125 insertions(+), 96 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index dcdfc396f2f84..7049a6bbc03dd 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -201,25 +201,25 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); - i915_gem_object_unlock(ctx->obj); if (err) - return err; + goto out_unlock; vma = i915_gem_object_ggtt_pin(ctx->obj, NULL, 0, 0, 0); - if (IS_ERR(vma)) - return PTR_ERR(vma); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_unlock; + } rq = intel_engine_create_kernel_request(ctx->engine); if (IS_ERR(rq)) { - i915_vma_unpin(vma); - return PTR_ERR(rq); + err = PTR_ERR(rq); + goto out_unpin; } cs = intel_ring_begin(rq, 4); if (IS_ERR(cs)) { - i915_request_add(rq); - i915_vma_unpin(vma); - return PTR_ERR(cs); + err = PTR_ERR(cs); + goto out_rq; } if (INTEL_GEN(ctx->engine->i915) >= 8) { @@ -240,14 +240,16 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) } intel_ring_advance(rq, cs); - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - i915_vma_unpin(vma); +out_rq: i915_request_add(rq); +out_unpin: + i915_vma_unpin(vma); +out_unlock: + i915_gem_object_unlock(ctx->obj); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index fa40006b453a6..99becb86abd33 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -893,24 +893,15 @@ static int igt_shared_ctx_exec(void *arg) return err; } -static struct i915_vma *rpcs_query_batch(struct i915_vma *vma) +static int rpcs_query_batch(struct drm_i915_gem_object *rpcs, struct i915_vma *vma) { - struct drm_i915_gem_object *obj; u32 *cmd; - int err; - if (INTEL_GEN(vma->vm->i915) < 8) - return ERR_PTR(-EINVAL); + GEM_BUG_ON(INTEL_GEN(vma->vm->i915) < 8); - obj = i915_gem_object_create_internal(vma->vm->i915, PAGE_SIZE); - if (IS_ERR(obj)) - return ERR_CAST(obj); - - cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); - if (IS_ERR(cmd)) { - err = PTR_ERR(cmd); - goto err; - } + cmd = i915_gem_object_pin_map(rpcs, I915_MAP_WB); + if (IS_ERR(cmd)) + return PTR_ERR(cmd); *cmd++ = MI_STORE_REGISTER_MEM_GEN8; *cmd++ = i915_mmio_reg_offset(GEN8_R_PWR_CLK_STATE); @@ -918,26 +909,12 @@ static struct i915_vma *rpcs_query_batch(struct i915_vma *vma) *cmd++ = upper_32_bits(vma->node.start); *cmd = MI_BATCH_BUFFER_END; - __i915_gem_object_flush_map(obj, 0, 64); - i915_gem_object_unpin_map(obj); + __i915_gem_object_flush_map(rpcs, 0, 64); + i915_gem_object_unpin_map(rpcs); intel_gt_chipset_flush(vma->vm->gt); - vma = i915_vma_instance(obj, vma->vm, NULL); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err; - } - - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) - goto err; - - return vma; - -err: - i915_gem_object_put(obj); - return ERR_PTR(err); + return 0; } static int @@ -945,52 +922,68 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, struct intel_context *ce, struct i915_request **rq_out) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_request *rq; + struct i915_gem_ww_ctx ww; struct i915_vma *batch; struct i915_vma *vma; + struct drm_i915_gem_object *rpcs; int err; GEM_BUG_ON(!intel_engine_can_store_dword(ce->engine)); + if (INTEL_GEN(i915) < 8) + return -EINVAL; + vma = i915_vma_instance(obj, ce->vm, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); - i915_gem_object_lock(obj, NULL); - err = i915_gem_object_set_to_gtt_domain(obj, false); - i915_gem_object_unlock(obj); - if (err) - return err; + rpcs = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(rpcs)) + return PTR_ERR(rpcs); - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) - return err; - - batch = rpcs_query_batch(vma); + batch = i915_vma_instance(rpcs, ce->vm, NULL); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto err_vma; + goto err_put; } + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_gem_object_lock(rpcs, &ww); + if (!err) + err = i915_gem_object_set_to_gtt_domain(obj, false); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (err) + goto err_put; + + err = i915_vma_pin_ww(batch, &ww, 0, 0, PIN_USER); + if (err) + goto err_vma; + + err = rpcs_query_batch(rpcs, vma); + if (err) + goto err_batch; + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_batch; } - i915_vma_lock(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); if (err) goto skip_request; - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); if (err) goto skip_request; @@ -1006,23 +999,24 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, if (err) goto skip_request; - i915_vma_unpin_and_release(&batch, 0); - i915_vma_unpin(vma); - *rq_out = i915_request_get(rq); - i915_request_add(rq); - - return 0; - skip_request: - i915_request_set_error_once(rq, err); + if (err) + i915_request_set_error_once(rq, err); i915_request_add(rq); err_batch: - i915_vma_unpin_and_release(&batch, 0); + i915_vma_unpin(batch); err_vma: i915_vma_unpin(vma); - +err_put: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + i915_gem_object_put(rpcs); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 9fb95a45bcad3..d27d87a678c8f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -528,31 +528,42 @@ static int make_obj_busy(struct drm_i915_gem_object *obj) for_each_uabi_engine(engine, i915) { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; int err; vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); if (err) - return err; + goto err; rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { - i915_vma_unpin(vma); - return PTR_ERR(rq); + err = PTR_ERR(rq); + goto err_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); i915_request_add(rq); +err_unpin: i915_vma_unpin(vma); +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); if (err) return err; } @@ -1123,6 +1134,7 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, for_each_uabi_engine(engine, i915) { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; vma = i915_vma_instance(obj, engine->kernel_context->vm, NULL); if (IS_ERR(vma)) { @@ -1130,9 +1142,13 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, goto out_unmap; } - err = i915_vma_pin(vma, 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); if (err) - goto out_unmap; + goto out_ww; rq = i915_request_create(engine->kernel_context); if (IS_ERR(rq)) { @@ -1140,11 +1156,9 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, goto out_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (err == 0) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); err = engine->emit_bb_start(rq, vma->node.start, 0, 0); i915_request_get(rq); @@ -1166,6 +1180,13 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, out_unpin: i915_vma_unpin(vma); +out_ww: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); if (err) goto out_unmap; } diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 34b403d47840c..3540ba9bd4599 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -77,20 +77,20 @@ create_spin_counter(struct intel_engine_cs *engine, vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { - i915_gem_object_put(obj); - return vma; + err = PTR_ERR(vma); + goto err_put; } err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) { - i915_vma_put(vma); - return ERR_PTR(err); - } + if (err) + goto err_unlock; + + i915_vma_lock(vma); base = i915_gem_object_pin_map(obj, I915_MAP_WC); if (IS_ERR(base)) { - i915_gem_object_put(obj); - return ERR_CAST(base); + err = PTR_ERR(base); + goto err_unpin; } cs = base; @@ -134,6 +134,14 @@ create_spin_counter(struct intel_engine_cs *engine, *cancel = base + loop; *counter = srm ? memset32(base + end, 0, 1) : NULL; return vma; + +err_unpin: + i915_vma_unpin(vma); +err_unlock: + i915_vma_unlock(vma); +err_put: + i915_gem_object_put(obj); + return ERR_PTR(err); } static u8 wait_for_freq(struct intel_rps *rps, u8 freq, int timeout_ms) @@ -639,7 +647,6 @@ int live_rps_frequency_cs(void *arg) goto err_vma; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (!err) err = i915_vma_move_to_active(vma, rq, 0); @@ -647,7 +654,6 @@ int live_rps_frequency_cs(void *arg) err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); - i915_vma_unlock(vma); i915_request_add(rq); if (err) goto err_vma; @@ -708,6 +714,7 @@ int live_rps_frequency_cs(void *arg) i915_gem_object_flush_map(vma->obj); i915_gem_object_unpin_map(vma->obj); i915_vma_unpin(vma); + i915_vma_unlock(vma); i915_vma_put(vma); st_engine_heartbeat_enable(engine); @@ -781,7 +788,6 @@ int live_rps_frequency_srm(void *arg) goto err_vma; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (!err) err = i915_vma_move_to_active(vma, rq, 0); @@ -789,7 +795,6 @@ int live_rps_frequency_srm(void *arg) err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); - i915_vma_unlock(vma); i915_request_add(rq); if (err) goto err_vma; @@ -849,6 +854,7 @@ int live_rps_frequency_srm(void *arg) i915_gem_object_flush_map(vma->obj); i915_gem_object_unpin_map(vma->obj); i915_vma_unpin(vma); + i915_vma_unlock(vma); i915_vma_put(vma); st_engine_heartbeat_enable(engine); diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index c1dcd4b91bda0..3092ca763789c 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -862,6 +862,8 @@ static int live_all_engines(void *arg) goto out_free; } + i915_vma_lock(batch); + idx = 0; for_each_uabi_engine(engine, i915) { request[idx] = intel_engine_create_kernel_request(engine); @@ -872,11 +874,9 @@ static int live_all_engines(void *arg) goto out_request; } - i915_vma_lock(batch); err = i915_request_await_object(request[idx], batch->obj, 0); if (err == 0) err = i915_vma_move_to_active(batch, request[idx], 0); - i915_vma_unlock(batch); GEM_BUG_ON(err); err = engine->emit_bb_start(request[idx], @@ -891,6 +891,8 @@ static int live_all_engines(void *arg) idx++; } + i915_vma_unlock(batch); + idx = 0; for_each_uabi_engine(engine, i915) { if (i915_request_completed(request[idx])) { @@ -981,12 +983,13 @@ static int live_sequential_engines(void *arg) goto out_free; } + i915_vma_lock(batch); request[idx] = intel_engine_create_kernel_request(engine); if (IS_ERR(request[idx])) { err = PTR_ERR(request[idx]); pr_err("%s: Request allocation failed for %s with err=%d\n", __func__, engine->name, err); - goto out_request; + goto out_unlock; } if (prev) { @@ -996,16 +999,14 @@ static int live_sequential_engines(void *arg) i915_request_add(request[idx]); pr_err("%s: Request await failed for %s with err=%d\n", __func__, engine->name, err); - goto out_request; + goto out_unlock; } } - i915_vma_lock(batch); err = i915_request_await_object(request[idx], batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, request[idx], 0); - i915_vma_unlock(batch); GEM_BUG_ON(err); err = engine->emit_bb_start(request[idx], @@ -1020,6 +1021,11 @@ static int live_sequential_engines(void *arg) prev = request[idx]; idx++; + +out_unlock: + i915_vma_unlock(batch); + if (err) + goto out_request; } idx = 0; -- GitLab From 3c0ffa277ef6fb3a26ff0be730564b1bd81ca139 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:09:02 +0200 Subject: [PATCH 0844/1494] drm/i915: Add ww locking to vm_fault_gtt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to start requiring the reservation_lock instead of obj->mm.lock for pinning objects, take the ww lock inside vm_fault_gtt as a first step towards the legacy lock removal. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-23-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 51 +++++++++++++++--------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index b23368529a409..548ed9fb427d3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -283,37 +283,46 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) struct intel_runtime_pm *rpm = &i915->runtime_pm; struct i915_ggtt *ggtt = &i915->ggtt; bool write = area->vm_flags & VM_WRITE; + struct i915_gem_ww_ctx ww; intel_wakeref_t wakeref; struct i915_vma *vma; pgoff_t page_offset; int srcu; int ret; - /* Sanity check that we allow writing into this object */ - if (i915_gem_object_is_readonly(obj) && write) - return VM_FAULT_SIGBUS; - /* We don't use vmf->pgoff since that has the fake offset */ page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT; trace_i915_gem_object_fault(obj, page_offset, true, write); - ret = i915_gem_object_pin_pages(obj); + wakeref = intel_runtime_pm_get(rpm); + + i915_gem_ww_ctx_init(&ww, true); +retry: + ret = i915_gem_object_lock(obj, &ww); if (ret) - goto err; + goto err_rpm; - wakeref = intel_runtime_pm_get(rpm); + /* Sanity check that we allow writing into this object */ + if (i915_gem_object_is_readonly(obj) && write) { + ret = -EFAULT; + goto err_rpm; + } - ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu); + ret = i915_gem_object_pin_pages(obj); if (ret) goto err_rpm; + ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu); + if (ret) + goto err_pages; + /* Now pin it into the GTT as needed */ - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | - PIN_NONBLOCK /* NOWARN */ | - PIN_NOEVICT); - if (IS_ERR(vma)) { + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { /* Use a partial view if it is bigger than available space */ struct i915_ggtt_view view = compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES); @@ -328,11 +337,11 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) * all hope that the hardware is able to track future writes. */ - vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); - if (IS_ERR(vma)) { + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { flags = PIN_MAPPABLE; view.type = I915_GGTT_VIEW_PARTIAL; - vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); } /* The entire mappable GGTT is pinned? Unexpected! */ @@ -389,10 +398,16 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) __i915_vma_unpin(vma); err_reset: intel_gt_reset_unlock(ggtt->vm.gt, srcu); +err_pages: + i915_gem_object_unpin_pages(obj); err_rpm: + if (ret == -EDEADLK) { + ret = i915_gem_ww_ctx_backoff(&ww); + if (!ret) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); intel_runtime_pm_put(rpm, wakeref); - i915_gem_object_unpin_pages(obj); -err: return i915_error_to_vmf_fault(ret); } -- GitLab From c1793ba86a41f420a3497d08c5755210783656bc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Wed, 19 Aug 2020 16:09:03 +0200 Subject: [PATCH 0845/1494] drm/i915: Add ww locking to pin_to_display_plane, v2. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ww locking for pin_to_display_plane for all the pinning and locking. With the locking removed from set_cache_level, we need to fix i915_gem_set_caching_ioctl to take the object reservation lock. As this is a single lock, we don't need to use the ww dance. Changes since v1: - Do not use ww locking in i915_gem_set_caching_ioctl (Thomas). Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-24-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 56 +++++++++++++++------- drivers/gpu/drm/i915/gem/i915_gem_object.h | 1 + 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 8ebceebd11b09..7c90a63c273d8 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -37,6 +37,12 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) i915_gem_object_unlock(obj); } +void i915_gem_object_flush_if_display_locked(struct drm_i915_gem_object *obj) +{ + if (i915_gem_object_is_framebuffer(obj)) + __i915_gem_object_flush_for_display(obj); +} + /** * Moves a single object to the WC read, and possibly write domain. * @obj: object to act on @@ -197,18 +203,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; - /* Always invalidate stale cachelines */ if (obj->cache_level != cache_level) { i915_gem_object_set_cache_coherency(obj, cache_level); obj->cache_dirty = true; } - i915_gem_object_unlock(obj); - /* The cache-level will be applied when each vma is rebound. */ return i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE | @@ -293,7 +293,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, goto out; } + ret = i915_gem_object_lock_interruptible(obj, NULL); + if (ret) + goto out; + ret = i915_gem_object_set_cache_level(obj, level); + i915_gem_object_unlock(obj); out: i915_gem_object_put(obj); @@ -313,6 +318,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, unsigned int flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_gem_ww_ctx ww; struct i915_vma *vma; int ret; @@ -320,6 +326,11 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) return ERR_PTR(-EINVAL); + i915_gem_ww_ctx_init(&ww, true); +retry: + ret = i915_gem_object_lock(obj, &ww); + if (ret) + goto err; /* * The display engine is not coherent with the LLC cache on gen6. As * a result, we make sure that the pinning that is about to occur is @@ -334,7 +345,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE); if (ret) - return ERR_PTR(ret); + goto err; /* * As the user may map the buffer once pinned in the display plane @@ -347,18 +358,31 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, vma = ERR_PTR(-ENOSPC); if ((flags & PIN_MAPPABLE) == 0 && (!view || view->type == I915_GGTT_VIEW_NORMAL)) - vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, - flags | - PIN_MAPPABLE | - PIN_NONBLOCK); - if (IS_ERR(vma)) - vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); - if (IS_ERR(vma)) - return vma; + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, view, 0, alignment, + flags | PIN_MAPPABLE | + PIN_NONBLOCK); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, view, 0, + alignment, flags); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; + } vma->display_alignment = max_t(u64, vma->display_alignment, alignment); - i915_gem_object_flush_if_display(obj); + i915_gem_object_flush_if_display_locked(obj); + +err: + if (ret == -EDEADLK) { + ret = i915_gem_ww_ctx_backoff(&ww); + if (!ret) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + if (ret) + return ERR_PTR(ret); return vma; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 45d79d75e73a2..afde1952c1192 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -454,6 +454,7 @@ i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj) void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj, unsigned int cache_level); void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj); +void i915_gem_object_flush_if_display_locked(struct drm_i915_gem_object *obj); int __must_check i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write); -- GitLab From b4d9145b0154f8c71dafc2db5fd445f1f3db9426 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 16 Jul 2020 15:22:06 +0100 Subject: [PATCH 0846/1494] drm/i915: Be wary of data races when reading the active execlists To implement preempt-to-busy (and so efficient timeslicing and best utilization of the hardware submission ports) we let the GPU run asynchronously in respect to the ELSP submission queue. This created challenges in keeping and accessing the driver state mirroring the asynchronous GPU execution. The latest occurence of this was spotted by KCSAN: [ 1413.563200] BUG: KCSAN: data-race in __await_execution+0x217/0x370 [i915] [ 1413.563221] [ 1413.563236] race at unknown origin, with read to 0xffff88885bb6c478 of 8 bytes by task 9654 on cpu 1: [ 1413.563548] __await_execution+0x217/0x370 [i915] [ 1413.563891] i915_request_await_dma_fence+0x4eb/0x6a0 [i915] [ 1413.564235] i915_request_await_object+0x421/0x490 [i915] [ 1413.564577] i915_gem_do_execbuffer+0x29b7/0x3c40 [i915] [ 1413.564967] i915_gem_execbuffer2_ioctl+0x22f/0x5c0 [i915] [ 1413.564998] drm_ioctl_kernel+0x156/0x1b0 [ 1413.565022] drm_ioctl+0x2ff/0x480 [ 1413.565046] __x64_sys_ioctl+0x87/0xd0 [ 1413.565069] do_syscall_64+0x4d/0x80 [ 1413.565094] entry_SYSCALL_64_after_hwframe+0x44/0xa9 To complicate matters, we have to both avoid the read tearing of *active and avoid any write tearing as perform the pending[] -> inflight[] promotion of the execlists. This is because we cannot rely on the memcpy doing u64 aligned copies on all kernels/platforms and so we opt to open-code it with explicit WRITE_ONCE annotations to satisfy KCSAN. v2: When in doubt, write the same comment again. v3: Expanded commit message. Fixes: b55230e5e800 ("drm/i915: Check for awaits on still currently executing requests") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716142207.13003-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added expanded commit message from Tvrtko and Chris] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_request.c | 25 +++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 47a90dbf8b70c..0412a44f25f2e 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -2062,6 +2062,14 @@ static inline void clear_ports(struct i915_request **ports, int count) memset_p((void **)ports, NULL, count); } +static inline void +copy_ports(struct i915_request **dst, struct i915_request **src, int count) +{ + /* A memcpy_p() would be very useful here! */ + while (count--) + WRITE_ONCE(*dst++, *src++); /* avoid write tearing */ +} + static void execlists_dequeue(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; @@ -2635,10 +2643,9 @@ static void process_csb(struct intel_engine_cs *engine) /* switch pending to inflight */ GEM_BUG_ON(!assert_pending_valid(execlists, "promote")); - memcpy(execlists->inflight, - execlists->pending, - execlists_num_ports(execlists) * - sizeof(*execlists->pending)); + copy_ports(execlists->inflight, + execlists->pending, + execlists_num_ports(execlists)); smp_wmb(); /* complete the seqlock */ WRITE_ONCE(execlists->active, execlists->inflight); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 20ba3d9fcc5eb..4f7f67a785acb 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -379,17 +379,38 @@ static bool __request_in_flight(const struct i915_request *signal) * As we know that there are always preemption points between * requests, we know that only the currently executing request * may be still active even though we have cleared the flag. - * However, we can't rely on our tracking of ELSP[0] to known + * However, we can't rely on our tracking of ELSP[0] to know * which request is currently active and so maybe stuck, as * the tracking maybe an event behind. Instead assume that * if the context is still inflight, then it is still active * even if the active flag has been cleared. + * + * To further complicate matters, if there a pending promotion, the HW + * may either perform a context switch to the second inflight execlists, + * or it may switch to the pending set of execlists. In the case of the + * latter, it may send the ACK and we process the event copying the + * pending[] over top of inflight[], _overwriting_ our *active. Since + * this implies the HW is arbitrating and not struck in *active, we do + * not worry about complete accuracy, but we do require no read/write + * tearing of the pointer [the read of the pointer must be valid, even + * as the array is being overwritten, for which we require the writes + * to avoid tearing.] + * + * Note that the read of *execlists->active may race with the promotion + * of execlists->pending[] to execlists->inflight[], overwritting + * the value at *execlists->active. This is fine. The promotion implies + * that we received an ACK from the HW, and so the context is not + * stuck -- if we do not see ourselves in *active, the inflight status + * is valid. If instead we see ourselves being copied into *active, + * we are inflight and may signal the callback. */ if (!intel_context_inflight(signal->context)) return false; rcu_read_lock(); - for (port = __engine_active(signal->engine); (rq = *port); port++) { + for (port = __engine_active(signal->engine); + (rq = READ_ONCE(*port)); /* may race with promotion of pending[] */ + port++) { if (rq->context == signal->context) { inflight = i915_seqno_passed(rq->fence.seqno, signal->fence.seqno); -- GitLab From 2e4c6c1a9db5e12556a12ea722df71096247e178 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 16 Jul 2020 15:22:07 +0100 Subject: [PATCH 0847/1494] drm/i915: Remove i915_request.lock requirement for execution callbacks To implement preempt-to-busy (and so efficient timeslicing and best utilization of the hardware submission ports) we let the GPU run asynchronously in respect to the ELSP submission queue. This created challenges in keeping and accessing the driver state mirroring the asynchronous GPU execution. Previous fix 1d9221e9d395 ("drm/i915: Skip signaling a signaled request") however did not correctly serialize request retirement with the execution callbacks. We were using the i915_request.lock to serialise adding an execution callback with __i915_request_submit. However, if we use an atomic llist_add to serialise multiple waiters and then check to see if the request is already executing, we can remove the irq-spinlock and fix serialization between retirement and execution callbacks in one go. v2: Avoid using the irq_work when outside of the irq-spinlocks, where we can execute the callbacks immediately. v3: Pay close attention to the order of setting ACTIVE on retirement, we need to ensure the request is signaled and breadcrumbs detached before we finish removing the request from the engine. v4: Expanded commit message. Fixes: 1d9221e9d395 ("drm/i915: Skip signaling a signaled request") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200716142207.13003-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added expanded commit message from Tvrtko and Chris] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_request.c | 105 +++++++++++++++------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 4f7f67a785acb..11e272422fb75 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -187,30 +187,34 @@ static void irq_execute_cb_hook(struct irq_work *wrk) irq_execute_cb(wrk); } -static void __notify_execute_cb(struct i915_request *rq) +static __always_inline void +__notify_execute_cb(struct i915_request *rq, bool (*fn)(struct irq_work *wrk)) { struct execute_cb *cb, *cn; - lockdep_assert_held(&rq->lock); - - GEM_BUG_ON(!i915_request_is_active(rq)); if (llist_empty(&rq->execute_cb)) return; - llist_for_each_entry_safe(cb, cn, rq->execute_cb.first, work.llnode) - irq_work_queue(&cb->work); + llist_for_each_entry_safe(cb, cn, + llist_del_all(&rq->execute_cb), + work.llnode) + fn(&cb->work); +} - /* - * XXX Rollback on __i915_request_unsubmit() - * - * In the future, perhaps when we have an active time-slicing scheduler, - * it will be interesting to unsubmit parallel execution and remove - * busywaits from the GPU until their master is restarted. This is - * quite hairy, we have to carefully rollback the fence and do a - * preempt-to-idle cycle on the target engine, all the while the - * master execute_cb may refire. - */ - init_llist_head(&rq->execute_cb); +static void __notify_execute_cb_irq(struct i915_request *rq) +{ + __notify_execute_cb(rq, irq_work_queue); +} + +static bool irq_work_imm(struct irq_work *wrk) +{ + wrk->func(wrk); + return false; +} + +static void __notify_execute_cb_imm(struct i915_request *rq) +{ + __notify_execute_cb(rq, irq_work_imm); } static void free_capture_list(struct i915_request *request) @@ -257,9 +261,16 @@ static void remove_from_engine(struct i915_request *rq) locked = engine; } list_del_init(&rq->sched.link); + clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags); clear_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags); + + /* Prevent further __await_execution() registering a cb, then flush */ + set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags); + spin_unlock_irq(&locked->active.lock); + + __notify_execute_cb_imm(rq); } bool i915_request_retire(struct i915_request *rq) @@ -271,6 +282,7 @@ bool i915_request_retire(struct i915_request *rq) GEM_BUG_ON(!i915_sw_fence_signaled(&rq->submit)); trace_i915_request_retire(rq); + i915_request_mark_complete(rq); /* * We know the GPU must have read the request to have @@ -288,15 +300,6 @@ bool i915_request_retire(struct i915_request *rq) __i915_request_fill(rq, POISON_FREE); rq->ring->head = rq->postfix; - /* - * We only loosely track inflight requests across preemption, - * and so we may find ourselves attempting to retire a _completed_ - * request that we have removed from the HW and put back on a run - * queue. - */ - remove_from_engine(rq); - - i915_request_mark_complete(rq); if (!i915_request_signaled(rq)) { spin_lock_irq(&rq->lock); dma_fence_signal_locked(&rq->fence); @@ -320,7 +323,6 @@ bool i915_request_retire(struct i915_request *rq) */ remove_from_engine(rq); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); - spin_unlock_irq(&rq->lock); __list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */ @@ -348,12 +350,6 @@ void i915_request_retire_upto(struct i915_request *rq) } while (i915_request_retire(tmp) && tmp != rq); } -static void __llist_add(struct llist_node *node, struct llist_head *head) -{ - node->next = head->first; - head->first = node; -} - static struct i915_request * const * __engine_active(struct intel_engine_cs *engine) { @@ -451,18 +447,24 @@ __await_execution(struct i915_request *rq, cb->work.func = irq_execute_cb_hook; } - spin_lock_irq(&signal->lock); - if (i915_request_is_active(signal) || __request_in_flight(signal)) { - if (hook) { - hook(rq, &signal->fence); - i915_request_put(signal); - } - i915_sw_fence_complete(cb->fence); - kmem_cache_free(global.slab_execute_cbs, cb); - } else { - __llist_add(&cb->work.llnode, &signal->execute_cb); + /* + * Register the callback first, then see if the signaler is already + * active. This ensures that if we race with the + * __notify_execute_cb from i915_request_submit() and we are not + * included in that list, we get a second bite of the cherry and + * execute it ourselves. After this point, a future + * i915_request_submit() will notify us. + * + * In i915_request_retire() we set the ACTIVE bit on a completed + * request (then flush the execute_cb). So by registering the + * callback first, then checking the ACTIVE bit, we serialise with + * the completed/retired request. + */ + if (llist_add(&cb->work.llnode, &signal->execute_cb)) { + if (i915_request_is_active(signal) || + __request_in_flight(signal)) + __notify_execute_cb_imm(signal); } - spin_unlock_irq(&signal->lock); return 0; } @@ -588,10 +590,19 @@ bool __i915_request_submit(struct i915_request *request) * preempt-to-idle cycle on the target engine, all the while the * master execute_cb may refire. */ - __notify_execute_cb(request); + __notify_execute_cb_irq(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) - i915_request_enable_breadcrumb(request); + /* We may be recursing from the signal callback of another i915 fence */ + if (!i915_request_signaled(request)) { + spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); + + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &request->fence.flags) && + !i915_request_enable_breadcrumb(request)) + intel_engine_signal_breadcrumbs(engine); + + spin_unlock(&request->lock); + } return result; } -- GitLab From f4b3c395540aa3d4f5a6275c5bdd83ab89034806 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 28 Jul 2020 16:21:44 +0100 Subject: [PATCH 0848/1494] drm/i915: Filter wake_flags passed to default_wake_function (NOTE: This is the minimal backportable fix, a full fix is being developed at https://patchwork.freedesktop.org/patch/388048/) The flags passed to the wait_entry.func are passed onwards to try_to_wake_up(), which has a very particular interpretation for its wake_flags. In particular, beyond the published WF_SYNC, it has a few internal flags as well. Since we passed the fence->error down the chain via the flags argument, these ended up in the default_wake_function confusing the kernel/sched. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2110 Fixes: ef4688497512 ("drm/i915: Propagate fence errors") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Matthew Auld <matthew.auld@intel.com> Cc: <stable@vger.kernel.org> # v5.4+ Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728152144.1100-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added a note and link about more complete fix] Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/i915_sw_fence.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 295b9829e2da5..4cd2038cbe359 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -164,9 +164,13 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence, do { list_for_each_entry_safe(pos, next, &x->head, entry) { - pos->func(pos, - TASK_NORMAL, fence->error, - &extra); + int wake_flags; + + wake_flags = fence->error; + if (pos->func == autoremove_wake_function) + wake_flags = 0; + + pos->func(pos, TASK_NORMAL, wake_flags, &extra); } if (list_empty(&extra)) -- GitLab From e0ee152fce25dc9269c7ea5280c98aa4b3682759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@intel.com> Date: Thu, 3 Sep 2020 15:07:17 +0200 Subject: [PATCH 0849/1494] drm/i915: Unlock the shared hwsp_gtt object after pinning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hwsp_gtt object is used for sub-allocation and could therefore be shared by many contexts causing unnecessary contention during concurrent context pinning. However since we're currently locking it only for pinning, it remains resident until we unpin it, and therefore it's safe to drop the lock early, allowing for concurrent thread access. Signed-off-by: Thomas Hellström <thomas.hellstrom@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> --- drivers/gpu/drm/i915/gt/intel_context.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 61b05cd4c47ae..d301dda1b2617 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -271,6 +271,15 @@ int __intel_context_do_pin_ww(struct intel_context *ce, i915_active_release(&ce->active); err_ctx_unpin: intel_context_post_unpin(ce); + + /* + * Unlock the hwsp_ggtt object since it's shared. + * In principle we can unlock all the global state locked above + * since it's pinned and doesn't need fencing, and will + * thus remain resident until it is explicitly unpinned. + */ + i915_gem_ww_unlock_single(ce->timeline->hwsp_ggtt->obj); + return err; } -- GitLab From 3ac929e722c4899d26516bec49f947b4c49b3f76 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:33 +0200 Subject: [PATCH 0850/1494] dt-bindings: display: Add support for the BCM2711 HVS The HVS found in the BCM2711 is slightly different from the previous generations, let's add a compatible for it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/a6b4c9ee03bc8f950adc6c493db70cd540c2f902.1599120059.git-series.maxime@cerno.tech --- .../bindings/display/brcm,bcm2835-hvs.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml index 02410f8d6d498..e826ab0adb75d 100644 --- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml +++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml @@ -11,7 +11,9 @@ maintainers: properties: compatible: - const: brcm,bcm2835-hvs + enum: + - brcm,bcm2711-hvs + - brcm,bcm2835-hvs reg: maxItems: 1 @@ -19,6 +21,10 @@ properties: interrupts: maxItems: 1 + clocks: + maxItems: 1 + description: Core Clock + required: - compatible - reg @@ -26,6 +32,16 @@ required: additionalProperties: false +if: + properties: + compatible: + contains: + const: brcm,bcm2711-hvs" + +then: + required: + - clocks + examples: - | hvs@7e400000 { -- GitLab From c54619b0bfb35c4153b3fb34916a6fa50dcf2dc1 Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:00:34 +0200 Subject: [PATCH 0851/1494] drm/vc4: Add support for the BCM2711 HVS5 The HVS found in the BCM2711 is slightly different from the previous generations. Most notably, the display list layout changes a bit, the LBM doesn't have the same size and the formats ordering for some formats is swapped. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/1d02fab3b916d639c2dc05608c117bbd8230ebe8.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 4 + drivers/gpu/drm/vc4/vc4_hvs.c | 34 ++++-- drivers/gpu/drm/vc4/vc4_plane.c | 194 +++++++++++++++++++++++--------- drivers/gpu/drm/vc4/vc4_regs.h | 67 +++++++++++ 4 files changed, 240 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index fa19160c801f8..e4cde1f9224b0 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -329,7 +329,11 @@ struct vc4_hvs { spinlock_t mm_lock; struct drm_mm_node mitchell_netravali_filter; + struct debugfs_regset32 regset; + + /* HVS version 5 flag, therefore requires updated dlist structures */ + bool hvs5; }; struct vc4_plane { diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 2d2bf59c05032..836d8799d79e0 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -277,11 +277,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, * mode. */ dispctrl = SCALER_DISPCTRLX_ENABLE; - dispctrl |= VC4_SET_FIELD(mode->hdisplay, - SCALER_DISPCTRLX_WIDTH) | - VC4_SET_FIELD(mode->vdisplay, - SCALER_DISPCTRLX_HEIGHT) | - (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0); + + if (!vc4->hvs->hvs5) + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, + SCALER_DISPCTRLX_HEIGHT) | + (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0); + else + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER5_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, + SCALER5_DISPCTRLX_HEIGHT) | + (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0); HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl); } @@ -521,6 +529,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) hvs->pdev = pdev; + if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs")) + hvs->hvs5 = true; + hvs->regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(hvs->regs)) return PTR_ERR(hvs->regs); @@ -529,7 +540,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) hvs->regset.regs = hvs_regs; hvs->regset.nregs = ARRAY_SIZE(hvs_regs); - hvs->dlist = hvs->regs + SCALER_DLIST_START; + if (!hvs->hvs5) + hvs->dlist = hvs->regs + SCALER_DLIST_START; + else + hvs->dlist = hvs->regs + SCALER5_DLIST_START; spin_lock_init(&hvs->mm_lock); @@ -547,7 +561,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) * between planes when they don't overlap on the screen, but * for now we just allocate globally. */ - drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024); + if (!hvs->hvs5) + /* 96kB */ + drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024); + else + /* 70k words */ + drm_mm_init(&hvs->lbm_mm, 0, 70 * 2 * 1024); /* Upload filter kernels. We only have the one for now, so we * keep it around for the lifetime of the driver. @@ -632,6 +651,7 @@ static int vc4_hvs_dev_remove(struct platform_device *pdev) } static const struct of_device_id vc4_hvs_dt_match[] = { + { .compatible = "brcm,bcm2711-hvs" }, { .compatible = "brcm,bcm2835-hvs" }, {} }; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index d040d9f12c6d7..20c949b578273 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -32,45 +32,60 @@ static const struct hvs_format { u32 drm; /* DRM_FORMAT_* */ u32 hvs; /* HVS_FORMAT_* */ u32 pixel_order; + u32 pixel_order_hvs5; } hvs_formats[] = { { - .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, + .drm = DRM_FORMAT_XRGB8888, + .hvs = HVS_PIXEL_FORMAT_RGBA8888, .pixel_order = HVS_PIXEL_ORDER_ABGR, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, }, { - .drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, + .drm = DRM_FORMAT_ARGB8888, + .hvs = HVS_PIXEL_FORMAT_RGBA8888, .pixel_order = HVS_PIXEL_ORDER_ABGR, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB, }, { - .drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, + .drm = DRM_FORMAT_ABGR8888, + .hvs = HVS_PIXEL_FORMAT_RGBA8888, .pixel_order = HVS_PIXEL_ORDER_ARGB, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, }, { - .drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888, + .drm = DRM_FORMAT_XBGR8888, + .hvs = HVS_PIXEL_FORMAT_RGBA8888, .pixel_order = HVS_PIXEL_ORDER_ARGB, + .pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR, }, { - .drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565, + .drm = DRM_FORMAT_RGB565, + .hvs = HVS_PIXEL_FORMAT_RGB565, .pixel_order = HVS_PIXEL_ORDER_XRGB, }, { - .drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565, + .drm = DRM_FORMAT_BGR565, + .hvs = HVS_PIXEL_FORMAT_RGB565, .pixel_order = HVS_PIXEL_ORDER_XBGR, }, { - .drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, + .drm = DRM_FORMAT_ARGB1555, + .hvs = HVS_PIXEL_FORMAT_RGBA5551, .pixel_order = HVS_PIXEL_ORDER_ABGR, }, { - .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551, + .drm = DRM_FORMAT_XRGB1555, + .hvs = HVS_PIXEL_FORMAT_RGBA5551, .pixel_order = HVS_PIXEL_ORDER_ABGR, }, { - .drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888, + .drm = DRM_FORMAT_RGB888, + .hvs = HVS_PIXEL_FORMAT_RGB888, .pixel_order = HVS_PIXEL_ORDER_XRGB, }, { - .drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888, + .drm = DRM_FORMAT_BGR888, + .hvs = HVS_PIXEL_FORMAT_RGB888, .pixel_order = HVS_PIXEL_ORDER_XBGR, }, { @@ -776,35 +791,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane, return -EINVAL; } - /* Control word */ - vc4_dlist_write(vc4_state, - SCALER_CTL0_VALID | - (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) | - (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | - VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | - (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | - (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | - VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | - (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | - VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | - VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1)); - - /* Position Word 0: Image Positions and Alpha Value */ - vc4_state->pos0_offset = vc4_state->dlist_count; - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) | - VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) | - VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y)); - - /* Position Word 1: Scaled Image Dimensions. */ - if (!vc4_state->is_unity) { - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(vc4_state->crtc_w, - SCALER_POS1_SCL_WIDTH) | - VC4_SET_FIELD(vc4_state->crtc_h, - SCALER_POS1_SCL_HEIGHT)); - } - /* Don't waste cycles mixing with plane alpha if the set alpha * is opaque or there is no per-pixel alpha information. * In any case we use the alpha property value as the fixed alpha. @@ -812,20 +798,120 @@ static int vc4_plane_mode_set(struct drm_plane *plane, mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && fb->format->has_alpha; - /* Position Word 2: Source Image Size, Alpha */ - vc4_state->pos2_offset = vc4_state->dlist_count; - vc4_dlist_write(vc4_state, - VC4_SET_FIELD(fb->format->has_alpha ? - SCALER_POS2_ALPHA_MODE_PIPELINE : - SCALER_POS2_ALPHA_MODE_FIXED, - SCALER_POS2_ALPHA_MODE) | - (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) | - (fb->format->has_alpha ? SCALER_POS2_ALPHA_PREMULT : 0) | - VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) | - VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT)); + if (!vc4->hvs->hvs5) { + /* Control word */ + vc4_dlist_write(vc4_state, + SCALER_CTL0_VALID | + (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) | + (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | + VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | + (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | + (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | + VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | + (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) | + VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | + VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1)); + + /* Position Word 0: Image Positions and Alpha Value */ + vc4_state->pos0_offset = vc4_state->dlist_count; + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) | + VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) | + VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y)); + + /* Position Word 1: Scaled Image Dimensions. */ + if (!vc4_state->is_unity) { + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(vc4_state->crtc_w, + SCALER_POS1_SCL_WIDTH) | + VC4_SET_FIELD(vc4_state->crtc_h, + SCALER_POS1_SCL_HEIGHT)); + } + + /* Position Word 2: Source Image Size, Alpha */ + vc4_state->pos2_offset = vc4_state->dlist_count; + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(fb->format->has_alpha ? + SCALER_POS2_ALPHA_MODE_PIPELINE : + SCALER_POS2_ALPHA_MODE_FIXED, + SCALER_POS2_ALPHA_MODE) | + (mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) | + (fb->format->has_alpha ? + SCALER_POS2_ALPHA_PREMULT : 0) | + VC4_SET_FIELD(vc4_state->src_w[0], + SCALER_POS2_WIDTH) | + VC4_SET_FIELD(vc4_state->src_h[0], + SCALER_POS2_HEIGHT)); + + /* Position Word 3: Context. Written by the HVS. */ + vc4_dlist_write(vc4_state, 0xc0c0c0c0); + + } else { + u32 hvs_pixel_order = format->pixel_order; - /* Position Word 3: Context. Written by the HVS. */ - vc4_dlist_write(vc4_state, 0xc0c0c0c0); + if (format->pixel_order_hvs5) + hvs_pixel_order = format->pixel_order_hvs5; + + /* Control word */ + vc4_dlist_write(vc4_state, + SCALER_CTL0_VALID | + (hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) | + (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | + VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) | + (vc4_state->is_unity ? + SCALER5_CTL0_UNITY : 0) | + VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) | + VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) | + SCALER5_CTL0_ALPHA_EXPAND | + SCALER5_CTL0_RGB_EXPAND); + + /* Position Word 0: Image Positions and Alpha Value */ + vc4_state->pos0_offset = vc4_state->dlist_count; + vc4_dlist_write(vc4_state, + (rotation & DRM_MODE_REFLECT_Y ? + SCALER5_POS0_VFLIP : 0) | + VC4_SET_FIELD(vc4_state->crtc_x, + SCALER_POS0_START_X) | + (rotation & DRM_MODE_REFLECT_X ? + SCALER5_POS0_HFLIP : 0) | + VC4_SET_FIELD(vc4_state->crtc_y, + SCALER5_POS0_START_Y) + ); + + /* Control Word 2 */ + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(state->alpha >> 4, + SCALER5_CTL2_ALPHA) | + fb->format->has_alpha ? + SCALER5_CTL2_ALPHA_PREMULT : 0 | + (mix_plane_alpha ? + SCALER5_CTL2_ALPHA_MIX : 0) | + VC4_SET_FIELD(fb->format->has_alpha ? + SCALER5_CTL2_ALPHA_MODE_PIPELINE : + SCALER5_CTL2_ALPHA_MODE_FIXED, + SCALER5_CTL2_ALPHA_MODE) + ); + + /* Position Word 1: Scaled Image Dimensions. */ + if (!vc4_state->is_unity) { + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(vc4_state->crtc_w, + SCALER_POS1_SCL_WIDTH) | + VC4_SET_FIELD(vc4_state->crtc_h, + SCALER_POS1_SCL_HEIGHT)); + } + + /* Position Word 2: Source Image Size */ + vc4_state->pos2_offset = vc4_state->dlist_count; + vc4_dlist_write(vc4_state, + VC4_SET_FIELD(vc4_state->src_w[0], + SCALER5_POS2_WIDTH) | + VC4_SET_FIELD(vc4_state->src_h[0], + SCALER5_POS2_HEIGHT)); + + /* Position Word 3: Context. Written by the HVS. */ + vc4_dlist_write(vc4_state, 0xc0c0c0c0); + } /* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers @@ -1203,6 +1289,10 @@ static bool vc4_format_mod_supported(struct drm_plane *plane, default: return false; } + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: case DRM_FORMAT_YUV422: case DRM_FORMAT_YVU422: case DRM_FORMAT_YUV420: diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 324462cc9cd41..91b785725555e 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -327,6 +327,20 @@ # define SCALER_DISPCTRLX_HEIGHT_MASK VC4_MASK(11, 0) # define SCALER_DISPCTRLX_HEIGHT_SHIFT 0 +# define SCALER5_DISPCTRLX_WIDTH_MASK VC4_MASK(28, 16) +# define SCALER5_DISPCTRLX_WIDTH_SHIFT 16 +/* Generates a single frame when VSTART is seen and stops at the last + * pixel read from the FIFO. + */ +# define SCALER5_DISPCTRLX_ONESHOT BIT(15) +/* Processes a single context in the dlist and then task switch, + * instead of an entire line. + */ +# define SCALER5_DISPCTRLX_ONECTX_MASK VC4_MASK(14, 13) +# define SCALER5_DISPCTRLX_ONECTX_SHIFT 13 +# define SCALER5_DISPCTRLX_HEIGHT_MASK VC4_MASK(12, 0) +# define SCALER5_DISPCTRLX_HEIGHT_SHIFT 0 + #define SCALER_DISPBKGND0 0x00000044 # define SCALER_DISPBKGND_AUTOHS BIT(31) # define SCALER_DISPBKGND_INTERLACE BIT(30) @@ -460,6 +474,8 @@ #define SCALER_DLIST_START 0x00002000 #define SCALER_DLIST_SIZE 0x00004000 +#define SCALER5_DLIST_START 0x00004000 + #define VC4_HDMI_CORE_REV 0x000 #define VC4_HDMI_SW_RESET_CONTROL 0x004 @@ -825,6 +841,8 @@ enum hvs_pixel_format { HVS_PIXEL_FORMAT_PALETTE = 13, HVS_PIXEL_FORMAT_YUV444_RGB = 14, HVS_PIXEL_FORMAT_AYUV444_RGB = 15, + HVS_PIXEL_FORMAT_RGBA1010102 = 16, + HVS_PIXEL_FORMAT_YCBCR_10BIT = 17, }; /* Note: the LSB is the rightmost character shown. Only valid for @@ -879,6 +897,10 @@ enum hvs_pixel_format { #define SCALER_CTL0_RGBA_EXPAND_MSB 2 #define SCALER_CTL0_RGBA_EXPAND_ROUND 3 +#define SCALER5_CTL0_ALPHA_EXPAND BIT(12) + +#define SCALER5_CTL0_RGB_EXPAND BIT(11) + #define SCALER_CTL0_SCL1_MASK VC4_MASK(10, 8) #define SCALER_CTL0_SCL1_SHIFT 8 @@ -896,10 +918,13 @@ enum hvs_pixel_format { /* Set to indicate no scaling. */ #define SCALER_CTL0_UNITY BIT(4) +#define SCALER5_CTL0_UNITY BIT(15) #define SCALER_CTL0_PIXEL_FORMAT_MASK VC4_MASK(3, 0) #define SCALER_CTL0_PIXEL_FORMAT_SHIFT 0 +#define SCALER5_CTL0_PIXEL_FORMAT_MASK VC4_MASK(4, 0) + #define SCALER_POS0_FIXED_ALPHA_MASK VC4_MASK(31, 24) #define SCALER_POS0_FIXED_ALPHA_SHIFT 24 @@ -909,12 +934,48 @@ enum hvs_pixel_format { #define SCALER_POS0_START_X_MASK VC4_MASK(11, 0) #define SCALER_POS0_START_X_SHIFT 0 +#define SCALER5_POS0_START_Y_MASK VC4_MASK(27, 16) +#define SCALER5_POS0_START_Y_SHIFT 16 + +#define SCALER5_POS0_START_X_MASK VC4_MASK(13, 0) +#define SCALER5_POS0_START_X_SHIFT 0 + +#define SCALER5_POS0_VFLIP BIT(31) +#define SCALER5_POS0_HFLIP BIT(15) + +#define SCALER5_CTL2_ALPHA_MODE_MASK VC4_MASK(31, 30) +#define SCALER5_CTL2_ALPHA_MODE_SHIFT 30 +#define SCALER5_CTL2_ALPHA_MODE_PIPELINE 0 +#define SCALER5_CTL2_ALPHA_MODE_FIXED 1 +#define SCALER5_CTL2_ALPHA_MODE_FIXED_NONZERO 2 +#define SCALER5_CTL2_ALPHA_MODE_FIXED_OVER_0x07 3 + +#define SCALER5_CTL2_ALPHA_PREMULT BIT(29) + +#define SCALER5_CTL2_ALPHA_MIX BIT(28) + +#define SCALER5_CTL2_ALPHA_LOC BIT(25) + +#define SCALER5_CTL2_MAP_SEL_MASK VC4_MASK(18, 17) +#define SCALER5_CTL2_MAP_SEL_SHIFT 17 + +#define SCALER5_CTL2_GAMMA BIT(16) + +#define SCALER5_CTL2_ALPHA_MASK VC4_MASK(15, 4) +#define SCALER5_CTL2_ALPHA_SHIFT 4 + #define SCALER_POS1_SCL_HEIGHT_MASK VC4_MASK(27, 16) #define SCALER_POS1_SCL_HEIGHT_SHIFT 16 #define SCALER_POS1_SCL_WIDTH_MASK VC4_MASK(11, 0) #define SCALER_POS1_SCL_WIDTH_SHIFT 0 +#define SCALER5_POS1_SCL_HEIGHT_MASK VC4_MASK(28, 16) +#define SCALER5_POS1_SCL_HEIGHT_SHIFT 16 + +#define SCALER5_POS1_SCL_WIDTH_MASK VC4_MASK(12, 0) +#define SCALER5_POS1_SCL_WIDTH_SHIFT 0 + #define SCALER_POS2_ALPHA_MODE_MASK VC4_MASK(31, 30) #define SCALER_POS2_ALPHA_MODE_SHIFT 30 #define SCALER_POS2_ALPHA_MODE_PIPELINE 0 @@ -930,6 +991,12 @@ enum hvs_pixel_format { #define SCALER_POS2_WIDTH_MASK VC4_MASK(11, 0) #define SCALER_POS2_WIDTH_SHIFT 0 +#define SCALER5_POS2_HEIGHT_MASK VC4_MASK(28, 16) +#define SCALER5_POS2_HEIGHT_SHIFT 16 + +#define SCALER5_POS2_WIDTH_MASK VC4_MASK(12, 0) +#define SCALER5_POS2_WIDTH_SHIFT 0 + /* Color Space Conversion words. Some values are S2.8 signed * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1, * 0x2: 2, 0x3: -1} -- GitLab From d7d96c00e585ceef29783c6b94e6497c6bb2f452 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:35 +0200 Subject: [PATCH 0852/1494] drm/vc4: hvs: Boost the core clock during modeset In order to prevent timeouts and stalls in the pipeline, the core clock needs to be maxed at 500MHz during a modeset on the BCM2711. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/37ed9e0124c5cce005ddc8dafe821d8b0da036ff.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ drivers/gpu/drm/vc4/vc4_hvs.c | 18 ++++++++++++++++++ drivers/gpu/drm/vc4/vc4_kms.c | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index e4cde1f9224b0..6358f6ca8d56f 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -320,6 +320,8 @@ struct vc4_hvs { void __iomem *regs; u32 __iomem *dlist; + struct clk *core_clk; + /* Memory manager for CRTCs to allocate space in the display * list. Units are dwords. */ diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 836d8799d79e0..abdb43c4cc10d 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -19,6 +19,7 @@ * each CRTC. */ +#include <linux/clk.h> #include <linux/component.h> #include <linux/platform_device.h> @@ -540,6 +541,20 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) hvs->regset.regs = hvs_regs; hvs->regset.nregs = ARRAY_SIZE(hvs_regs); + if (hvs->hvs5) { + hvs->core_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(hvs->core_clk)) { + dev_err(&pdev->dev, "Couldn't get core clock\n"); + return PTR_ERR(hvs->core_clk); + } + + ret = clk_prepare_enable(hvs->core_clk); + if (ret) { + dev_err(&pdev->dev, "Couldn't enable the core clock\n"); + return ret; + } + } + if (!hvs->hvs5) hvs->dlist = hvs->regs + SCALER_DLIST_START; else @@ -624,6 +639,7 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master, { struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = drm->dev_private; + struct vc4_hvs *hvs = vc4->hvs; if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter)) drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter); @@ -631,6 +647,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master, drm_mm_takedown(&vc4->hvs->dlist_mm); drm_mm_takedown(&vc4->hvs->lbm_mm); + clk_disable_unprepare(hvs->core_clk); + vc4->hvs = NULL; } diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 08318e69061be..210cc24080877 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -11,6 +11,8 @@ * crtc, HDMI encoder). */ +#include <linux/clk.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hvs *hvs = vc4->hvs; struct vc4_crtc *vc4_crtc; int i; @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) vc4_hvs_mask_underrun(dev, vc4_crtc->channel); } + if (vc4->hvs->hvs5) + clk_set_min_rate(hvs->core_clk, 500000000); + drm_atomic_helper_wait_for_fences(dev, state, false); drm_atomic_helper_wait_for_dependencies(state); @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) drm_atomic_helper_commit_cleanup_done(state); + if (vc4->hvs->hvs5) + clk_set_min_rate(hvs->core_clk, 0); + drm_atomic_state_put(state); up(&vc4->async_modeset); -- GitLab From 31e0ecb39b592cc836470d3f76a61c7df4b24084 Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:00:36 +0200 Subject: [PATCH 0853/1494] drm/vc4: plane: Change LBM alignment constraint on LBM The HVS5 needs an alignment of 64bytes for its LBM memory, so let's reflect it. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/6f9c4fe1eb9258a3f1d0f21af6a99c42472ac531.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_plane.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 20c949b578273..d0771ebd5f75b 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -578,7 +578,9 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags); ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, &vc4_state->lbm, - lbm_size, 32, 0, 0); + lbm_size, + vc4->hvs->hvs5 ? 64 : 32, + 0, 0); spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); if (ret) -- GitLab From 5630b27ec577953bde59f0e6414c382f0745387a Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:00:37 +0200 Subject: [PATCH 0854/1494] drm/vc4: plane: Optimize the LBM allocation size The current code is using the maximum of the source line size and the destination line size to compute the size of the LBM to allocate. While this is simpler, it starts to be an issue with modes such as 4k with a quite long that will consume all the available memory, so we no longer have that luxury. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/b9e091883a4f7395c5b6a4f7c6070225934293db.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_plane.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index d0771ebd5f75b..23916814b4e3a 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -437,10 +437,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst) static u32 vc4_lbm_size(struct drm_plane_state *state) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); - /* This is the worst case number. One of the two sizes will - * be used depending on the scaling configuration. - */ - u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w); + u32 pix_per_line; u32 lbm; /* LBM is not needed when there's no vertical scaling. */ @@ -448,6 +445,18 @@ static u32 vc4_lbm_size(struct drm_plane_state *state) vc4_state->y_scaling[1] == VC4_SCALING_NONE) return 0; + /* + * This can be further optimized in the RGB/YUV444 case if the PPF + * decimation factor is between 0.5 and 1.0 by using crtc_w. + * + * It's not an issue though, since in that case since src_w[0] is going + * to be greater than or equal to crtc_w. + */ + if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ) + pix_per_line = vc4_state->crtc_w; + else + pix_per_line = vc4_state->src_w[0]; + if (!vc4_state->is_yuv) { if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ) lbm = pix_per_line * 8; -- GitLab From 0ddd59c56e6b18919dc3f62ebaa615d4ec7daabd Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:38 +0200 Subject: [PATCH 0855/1494] drm/vc4: plane: Create more planes Let's now create more planes that can be affected to all the CRTCs. vc4 has 3 CRTCs, 1 primary and 1 cursor each, and was having 24 (8 planes per CRTC) overlays. However, vc5 has 5 CRTCs, so keeping the same logic would put us at 50 planes which is well above the 32 planes limit imposed by DRM. Using 16 seems like a good tradeoff between staying under 32 and yet providing enough planes. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/b41003001541fc2bb23668c699c0369ff7983be8.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 23916814b4e3a..1e38e603f83b9 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1384,7 +1384,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm) * modest number of planes to expose, that should hopefully * still cover any sane usecase. */ - for (i = 0; i < 8; i++) { + for (i = 0; i < 16; i++) { struct drm_plane *plane = vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY); -- GitLab From 644df22fe305d7f2a07302b03327641f91b3ab67 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:39 +0200 Subject: [PATCH 0856/1494] drm/vc4: crtc: Deal with different number of pixel per clock Some of the HDMI pixelvalves in vc5 output two pixels per clock cycle. Let's put the number of pixel output per clock cycle in the CRTC data and update the various calculations to reflect that. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/18a3bb079981ba820132b37e736a4bb371234d2e.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++++++++++------- drivers/gpu/drm/vc4/vc4_drv.h | 3 +++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 6d8fa6118fc1a..e55b2208b4b71 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -235,6 +235,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); struct drm_crtc_state *state = crtc->state; struct drm_display_mode *mode = &state->adjusted_mode; bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -242,6 +243,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; + u8 ppc = pv_data->pixels_per_clock; /* Reset the PV fifo. */ CRTC_WRITE(PV_CONTROL, 0); @@ -249,17 +251,16 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) CRTC_WRITE(PV_CONTROL, 0); CRTC_WRITE(PV_HORZA, - VC4_SET_FIELD((mode->htotal - - mode->hsync_end) * pixel_rep, + VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, PV_HORZA_HBP) | - VC4_SET_FIELD((mode->hsync_end - - mode->hsync_start) * pixel_rep, + VC4_SET_FIELD((mode->hsync_end - mode->hsync_start) * pixel_rep / ppc, PV_HORZA_HSYNC)); + CRTC_WRITE(PV_HORZB, - VC4_SET_FIELD((mode->hsync_start - - mode->hdisplay) * pixel_rep, + VC4_SET_FIELD((mode->hsync_start - mode->hdisplay) * pixel_rep / ppc, PV_HORZB_HFP) | - VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE)); + VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc, + PV_HORZB_HACTIVE)); CRTC_WRITE(PV_VERTA, VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, @@ -761,6 +762,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = { .hvs_channel = 0, }, .debugfs_name = "crtc0_regs", + .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0, [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI, @@ -772,6 +774,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = { .hvs_channel = 2, }, .debugfs_name = "crtc1_regs", + .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1, [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI, @@ -783,6 +786,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = { .hvs_channel = 1, }, .debugfs_name = "crtc2_regs", + .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI, [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 6358f6ca8d56f..0bc150daafb24 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -454,6 +454,9 @@ struct vc4_crtc_data { struct vc4_pv_data { struct vc4_crtc_data base; + /* Number of pixels output per clock period */ + u8 pixels_per_clock; + enum vc4_encoder_type encoder_types[4]; const char *debugfs_name; -- GitLab From a1962d6e326965558119fe6b8497aebe55fa03db Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:40 +0200 Subject: [PATCH 0857/1494] drm/vc4: crtc: Use a shared interrupt Some pixelvalves in vc5 use the same interrupt line so let's register our interrupt handler as a shared one. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/5a915d374357f41083ac71779fa9b2c35a339c2f.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index e55b2208b4b71..9faae22cb0f80 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -919,7 +919,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data) CRTC_WRITE(PV_INTEN, 0); CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START); ret = devm_request_irq(dev, platform_get_irq(pdev, 0), - vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc); + vc4_crtc_irq_handler, + IRQF_SHARED, + "vc4 crtc", vc4_crtc); if (ret) goto err_destroy_planes; -- GitLab From 78cbcc38b9043a736ca97577bd47a2d291c67981 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:41 +0200 Subject: [PATCH 0858/1494] drm/vc4: crtc: Move the cob allocation outside of bind The COB allocation depends on the HVS channel used for a given pixelvalve. While the channel allocation was entirely static in vc4, vc5 changes that and at bind time, a pixelvalve can be assigned to multiple HVS channels. Let's prepare that rework by allocating the COB when it's actually needed. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/484cbd4b00cfeee425295df438222258cc39a3dd.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 35 +++++++++++++++++----------------- drivers/gpu/drm/vc4/vc4_drv.h | 2 -- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 9faae22cb0f80..fdecaba778363 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -65,6 +65,20 @@ static const struct debugfs_reg32 crtc_regs[] = { VC4_REG32(PV_HACT_ACT), }; +static unsigned int +vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel) +{ + u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel)); + /* Top/base are supposed to be 4-pixel aligned, but the + * Raspberry Pi firmware fills the low bits (which are + * presumably ignored). + */ + u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; + u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; + + return top - base + 4; +} + static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, bool in_vblank_irq, int *vpos, int *hpos, @@ -74,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + unsigned int cob_size; u32 val; int fifo_lines; int vblank_lines; @@ -109,8 +124,9 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, *hpos += mode->crtc_htotal / 2; } + cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel); /* This is the offset we need for translating hvs -> pv scanout pos. */ - fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; + fifo_lines = cob_size / mode->crtc_hdisplay; if (fifo_lines > 0) ret = true; @@ -823,22 +839,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm, } } -static void -vc4_crtc_get_cob_allocation(struct vc4_crtc *vc4_crtc) -{ - struct drm_device *drm = vc4_crtc->base.dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); - u32 dispbase = HVS_READ(SCALER_DISPBASEX(vc4_crtc->channel)); - /* Top/base are supposed to be 4-pixel aligned, but the - * Raspberry Pi firmware fills the low bits (which are - * presumably ignored). - */ - u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3; - u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3; - - vc4_crtc->cob_size = top - base + 4; -} - int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, const struct drm_crtc_funcs *crtc_funcs, const struct drm_crtc_helper_funcs *crtc_helper_funcs) @@ -870,7 +870,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, * implemented as private driver state in vc4_kms, not here. */ drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); - vc4_crtc_get_cob_allocation(vc4_crtc); for (i = 0; i < crtc->gamma_size; i++) { vc4_crtc->lut_r[i] = i; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 0bc150daafb24..d80fc3bbb4503 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -477,8 +477,6 @@ struct vc4_crtc { u8 lut_r[256]; u8 lut_g[256]; u8 lut_b[256]; - /* Size in pixels of the COB memory allocated to this CRTC. */ - u32 cob_size; struct drm_pending_vblank_event *event; -- GitLab From 8ebb2cf0f6f42be258795a87fbe31d77440be20d Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:42 +0200 Subject: [PATCH 0859/1494] drm/vc4: crtc: Rename HVS channel to output In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with pixelvalves each being assigned to a given output, but each output can then be muxed to feed from multiple FIFOs. Since vc4 had that entirely static, both were probably equivalent, but since that changes, let's rename hvs_channel to hvs_output in the vc4_crtc_data, since a pixelvalve is really connected to an output, and not to a FIFO. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/b7618bb17b1c435c5d6ce50bcde2fe9243281d02.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++---- drivers/gpu/drm/vc4/vc4_drv.h | 4 ++-- drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- drivers/gpu/drm/vc4/vc4_txp.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index fdecaba778363..d3126fe04d9a3 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { static const struct vc4_pv_data bcm2835_pv0_data = { .base = { - .hvs_channel = 0, + .hvs_output = 0, }, .debugfs_name = "crtc0_regs", .pixels_per_clock = 1, @@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = { static const struct vc4_pv_data bcm2835_pv1_data = { .base = { - .hvs_channel = 2, + .hvs_output = 2, }, .debugfs_name = "crtc1_regs", .pixels_per_clock = 1, @@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = { static const struct vc4_pv_data bcm2835_pv2_data = { .base = { - .hvs_channel = 1, + .hvs_output = 1, }, .debugfs_name = "crtc2_regs", .pixels_per_clock = 1, @@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, crtc_funcs, NULL); drm_crtc_helper_add(crtc, crtc_helper_funcs); - vc4_crtc->channel = vc4_crtc->data->hvs_channel; + vc4_crtc->channel = vc4_crtc->data->hvs_output; drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index d80fc3bbb4503..d1cf4c038180c 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder) } struct vc4_crtc_data { - /* Which channel of the HVS this pixelvalve sources from. */ - int hvs_channel; + /* Which output of the HVS this pixelvalve sources from. */ + int hvs_output; }; struct vc4_pv_data { diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index abdb43c4cc10d..365425d67f3f4 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc) struct drm_display_mode *mode = &crtc->state->adjusted_mode; bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; - if (vc4_crtc->data->hvs_channel == 2) { + if (vc4_crtc->data->hvs_output == 2) { u32 dispctrl; u32 dsp3_mux; diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index a7c3af0005a0a..f39d9900d027b 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data) } static const struct vc4_crtc_data vc4_txp_crtc_data = { - .hvs_channel = 2, + .hvs_output = 2, }; static int vc4_txp_bind(struct device *dev, struct device *master, void *data) -- GitLab From 32a851c217b72217ccb8c03a1fc230d34f98e223 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:43 +0200 Subject: [PATCH 0860/1494] drm/vc4: crtc: Use local chan variable The vc4_crtc_handle_page_flip already has a local variable holding the value of vc4_crtc->channel, so let's use it instead. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/439c589baec72ddb89159857a2d078fdd77b02a2.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d3126fe04d9a3..cdeaa0cd981f0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) * the CRTC and encoder already reconfigured, leading to * underruns. This can be seen when reconfiguring the CRTC. */ - vc4_hvs_unmask_underrun(dev, vc4_crtc->channel); + vc4_hvs_unmask_underrun(dev, chan); } spin_unlock_irqrestore(&dev->event_lock, flags); } -- GitLab From a5c4b75f1ea00f18e2b47c46df705dab22137a3e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:44 +0200 Subject: [PATCH 0861/1494] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable The VIDEN bit in the pixelvalve currently being used to enable or disable the pixelvalve seems to not be enough in some situations, which whill end up with the pixelvalve stalling. In such a case, even re-enabling VIDEN doesn't bring it back and we need to clear the FIFO. This can only be done if the pixelvalve is disabled though. In order to overcome this, we can configure the pixelvalve during mode_set_no_fb by calling vc4_crtc_config_pv, but only enable it in atomic_enable and flush the FIFO there, and in atomic_disable disable the pixelvalve again. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/e97596f62f4df83424d994a23465463ac60f986e.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index cdeaa0cd981f0..fe2e5675aed43 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) PV_CONTROL_TRIGGER_UNDERFLOW | PV_CONTROL_WAIT_HSTART | VC4_SET_FIELD(vc4_encoder->clock_select, - PV_CONTROL_CLK_SELECT) | - PV_CONTROL_FIFO_CLR | - PV_CONTROL_EN); + PV_CONTROL_CLK_SELECT)); } static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) @@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); + vc4_hvs_atomic_disable(crtc, old_state); /* @@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, require_hvs_enabled(dev); + /* Reset the PV fifo. */ + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | + PV_CONTROL_FIFO_CLR | PV_CONTROL_EN); + /* Enable vblank irq handling before crtc is started otherwise * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist(). */ -- GitLab From 596356678fb429cc181c30971b5cb6c4244b58ad Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:45 +0200 Subject: [PATCH 0862/1494] drm/vc4: kms: Convert to for_each_new_crtc_state The vc4 atomic commit loop has an handrolled loop that is basically identical to for_each_new_crtc_state, let's convert it to that helper. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/a712d2b70aaee20379cfc52c2141aa2f6e2a9d5b.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_kms.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 210cc24080877..a41d105d4e3c2 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -152,14 +152,16 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) struct drm_device *dev = state->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_hvs *hvs = vc4->hvs; - struct vc4_crtc *vc4_crtc; + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; int i; - for (i = 0; i < dev->mode_config.num_crtc; i++) { - if (!state->crtcs[i].ptr || !state->crtcs[i].commit) + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + + if (!new_crtc_state->commit) continue; - vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr); vc4_hvs_mask_underrun(dev, vc4_crtc->channel); } -- GitLab From 87ebcd42fb7b8d1d3269007a621e41ae96a0077e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:46 +0200 Subject: [PATCH 0863/1494] drm/vc4: crtc: Assign output to channel automatically The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output being connected to a pixelvalve, and some muxing between the FIFOs and outputs. Any output cannot feed from any FIFO though, and they all have a bunch of constraints. In order to support this, let's store the possible FIFOs each output can be assigned to in the vc4_crtc_data, and use that information at atomic_check time to iterate over all the CRTCs enabled and assign them FIFOs. The channel assigned is then set in the vc4_crtc_state so that the rest of the driver can use it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/f9aba3814ef37156ff36f310118cdd3954dd3dc5.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++- drivers/gpu/drm/vc4/vc4_drv.h | 7 +- drivers/gpu/drm/vc4/vc4_hvs.c | 28 +++--- drivers/gpu/drm/vc4/vc4_kms.c | 168 ++++++++++++++++++++++++++++++++- drivers/gpu/drm/vc4/vc4_regs.h | 10 ++ drivers/gpu/drm/vc4/vc4_txp.c | 1 + 6 files changed, 200 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index fe2e5675aed43..b7e47ce1476cb 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); unsigned int cob_size; u32 val; int fifo_lines; @@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, * Read vertical scanline which is currently composed for our * pixelvalve by the HVS, and also the scaler status. */ - val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel)); + val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel)); /* Get optional system timestamp after query. */ if (etime) @@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc, *hpos += mode->crtc_htotal / 2; } - cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel); + cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel); /* This is the offset we need for translating hvs -> pv scanout pos. */ fifo_lines = cob_size / mode->crtc_hdisplay; @@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); - u32 chan = vc4_crtc->channel; + u32 chan = vc4_state->assigned_channel; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); @@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) old_vc4_state = to_vc4_crtc_state(crtc->state); vc4_state->feed_txp = old_vc4_state->feed_txp; vc4_state->margins = old_vc4_state->margins; + vc4_state->assigned_channel = old_vc4_state->assigned_channel; __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); return &vc4_state->base; @@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { static const struct vc4_pv_data bcm2835_pv0_data = { .base = { + .hvs_available_channels = BIT(0), .hvs_output = 0, }, .debugfs_name = "crtc0_regs", @@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = { static const struct vc4_pv_data bcm2835_pv1_data = { .base = { + .hvs_available_channels = BIT(2), .hvs_output = 2, }, .debugfs_name = "crtc1_regs", @@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = { static const struct vc4_pv_data bcm2835_pv2_data = { .base = { + .hvs_available_channels = BIT(1), .hvs_output = 1, }, .debugfs_name = "crtc2_regs", @@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, crtc_funcs, NULL); drm_crtc_helper_add(crtc, crtc_helper_funcs); - vc4_crtc->channel = vc4_crtc->data->hvs_output; drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index d1cf4c038180c..9e81ad8331f18 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder) } struct vc4_crtc_data { + /* Bitmask of channels (FIFOs) of the HVS that the output can source from */ + unsigned int hvs_available_channels; + /* Which output of the HVS this pixelvalve sources from. */ int hvs_output; }; @@ -471,9 +474,6 @@ struct vc4_crtc { /* Timestamp at start of vblank irq - unaffected by lock delays. */ ktime_t t_vblank; - /* Which HVS channel we're using for our CRTC. */ - int channel; - u8 lut_r[256]; u8 lut_g[256]; u8 lut_b[256]; @@ -509,6 +509,7 @@ struct vc4_crtc_state { struct drm_mm_node mm; bool feed_txp; bool txp_armed; + unsigned int assigned_channel; struct { unsigned int left; diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 365425d67f3f4..31a9bc5ef84e2 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); u32 i; /* The LUT memory is laid out with each HVS channel in order, @@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc) */ HVS_WRITE(SCALER_GAMADDR, SCALER_GAMADDR_AUTOINC | - (vc4_crtc->channel * 3 * crtc->gamma_size)); + (vc4_state->assigned_channel * 3 * crtc->gamma_size)); for (i = 0; i < crtc->gamma_size; i++) HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]); @@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc) crtc->state->event = NULL; } - HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel), + HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), vc4_state->mm.start); spin_unlock_irqrestore(&dev->event_lock, flags); } else { - HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel), + HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel), vc4_state->mm.start); } } @@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; bool oneshot = vc4_state->feed_txp; @@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, SCALER5_DISPCTRLX_HEIGHT) | (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0); - HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl); + HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl); } void vc4_hvs_atomic_disable(struct drm_crtc *crtc, @@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - u32 chan = vc4_crtc->channel; + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state); + unsigned int chan = vc4_state->assigned_channel; if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) { @@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_plane *plane; struct vc4_plane_state *vc4_plane_state; @@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, /* This sets a black background color fill, as is the case * with other DRM drivers. */ - HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), - HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) | + HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), + HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) | SCALER_DISPBKGND_FILL); /* Only update DISPLIST if the CRTC was already running and is not @@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, vc4_hvs_update_dlist(crtc); if (crtc->state->color_mgmt_changed) { - u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)); + u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)); if (crtc->state->gamma_lut) { vc4_hvs_update_gamma_lut(crtc); @@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, */ dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; } - HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx); + HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx); } if (debug_dump_regs) { @@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; - if (vc4_crtc->data->hvs_output == 2) { + if (vc4_state->assigned_channel == 2) { u32 dispctrl; u32 dsp3_mux; @@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc) HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux); } - HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), + HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), SCALER_DISPBKGND_AUTOHS | SCALER_DISPBKGND_GAMMA | (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index a41d105d4e3c2..bfc7ddd49ac58 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO)); } +static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + unsigned int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + u32 dispctrl; + u32 dsp3_mux; + + if (!crtc_state->active) + continue; + + if (vc4_state->assigned_channel != 2) + continue; + + /* + * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to + * FIFO X'. + * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'. + * + * DSP3 is connected to FIFO2 unless the transposer is + * enabled. In this case, FIFO 2 is directly accessed by the + * TXP IP, and we need to disable the FIFO2 -> pixelvalve1 + * route. + */ + if (vc4_state->feed_txp) + dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX); + else + dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); + + dispctrl = HVS_READ(SCALER_DISPCTRL) & + ~SCALER_DISPCTRL_DSP3_MUX_MASK; + HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux); + } +} + +static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, + struct drm_atomic_state *state) +{ + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + unsigned char dsp2_mux = 0; + unsigned char dsp3_mux = 3; + unsigned char dsp4_mux = 3; + unsigned char dsp5_mux = 3; + unsigned int i; + u32 reg; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + + if (!crtc_state->active) + continue; + + switch (vc4_crtc->data->hvs_output) { + case 2: + dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1; + break; + + case 3: + dsp3_mux = vc4_state->assigned_channel; + break; + + case 4: + dsp4_mux = vc4_state->assigned_channel; + break; + + case 5: + dsp5_mux = vc4_state->assigned_channel; + break; + + default: + break; + } + } + + reg = HVS_READ(SCALER_DISPECTRL); + HVS_WRITE(SCALER_DISPECTRL, + (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) | + VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX)); + + reg = HVS_READ(SCALER_DISPCTRL); + HVS_WRITE(SCALER_DISPCTRL, + (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) | + VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX)); + + reg = HVS_READ(SCALER_DISPEOLN); + HVS_WRITE(SCALER_DISPEOLN, + (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) | + VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX)); + + reg = HVS_READ(SCALER_DISPDITHER); + HVS_WRITE(SCALER_DISPDITHER, + (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) | + VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX)); +} + static void vc4_atomic_complete_commit(struct drm_atomic_state *state) { @@ -157,12 +258,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) int i; for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct vc4_crtc_state *vc4_crtc_state; if (!new_crtc_state->commit) continue; - vc4_hvs_mask_underrun(dev, vc4_crtc->channel); + vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); + vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); } if (vc4->hvs->hvs5) @@ -176,6 +278,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state) vc4_ctm_commit(vc4, state); + if (vc4->hvs->hvs5) + vc5_hvs_pv_muxing_commit(vc4, state); + else + vc4_hvs_pv_muxing_commit(vc4, state); + drm_atomic_helper_commit_planes(dev, state, 0); drm_atomic_helper_commit_modeset_enables(dev, state); @@ -385,8 +492,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) /* CTM is being enabled or the matrix changed. */ if (new_crtc_state->ctm) { + struct vc4_crtc_state *vc4_crtc_state = + to_vc4_crtc_state(new_crtc_state); + /* fifo is 1-based since 0 disables CTM. */ - int fifo = to_vc4_crtc(crtc)->channel + 1; + int fifo = vc4_crtc_state->assigned_channel + 1; /* Check userland isn't trying to turn on CTM for more * than one CRTC at a time. @@ -496,10 +606,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { .atomic_destroy_state = vc4_load_tracker_destroy_state, }; +#define NUM_OUTPUTS 6 +#define NUM_CHANNELS 3 + static int vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - int ret; + unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + int i, ret; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_crtc_state = + to_vc4_crtc_state(crtc_state); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + unsigned int matching_channels; + + if (!crtc_state->active) + continue; + + /* + * The problem we have to solve here is that we have + * up to 7 encoders, connected to up to 6 CRTCs. + * + * Those CRTCs, depending on the instance, can be + * routed to 1, 2 or 3 HVS FIFOs, and we need to set + * the change the muxing between FIFOs and outputs in + * the HVS accordingly. + * + * It would be pretty hard to come up with an + * algorithm that would generically solve + * this. However, the current routing trees we support + * allow us to simplify a bit the problem. + * + * Indeed, with the current supported layouts, if we + * try to assign in the ascending crtc index order the + * FIFOs, we can't fall into the situation where an + * earlier CRTC that had multiple routes is assigned + * one that was the only option for a later CRTC. + * + * If the layout changes and doesn't give us that in + * the future, we will need to have something smarter, + * but it works so far. + */ + matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels; + if (matching_channels) { + unsigned int channel = ffs(matching_channels) - 1; + + vc4_crtc_state->assigned_channel = channel; + unassigned_channels &= ~BIT(channel); + } else { + return -EINVAL; + } + } ret = vc4_ctm_atomic_check(dev, state); if (ret < 0) diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 91b785725555e..7fbac68b6fe12 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -286,9 +286,19 @@ #define SCALER_DISPID 0x00000008 #define SCALER_DISPECTRL 0x0000000c +# define SCALER_DISPECTRL_DSP2_MUX_SHIFT 31 +# define SCALER_DISPECTRL_DSP2_MUX_MASK VC4_MASK(31, 31) + #define SCALER_DISPPROF 0x00000010 + #define SCALER_DISPDITHER 0x00000014 +# define SCALER_DISPDITHER_DSP5_MUX_SHIFT 30 +# define SCALER_DISPDITHER_DSP5_MUX_MASK VC4_MASK(31, 30) + #define SCALER_DISPEOLN 0x00000018 +# define SCALER_DISPEOLN_DSP4_MUX_SHIFT 30 +# define SCALER_DISPEOLN_DSP4_MUX_MASK VC4_MASK(31, 30) + #define SCALER_DISPLIST0 0x00000020 #define SCALER_DISPLIST1 0x00000024 #define SCALER_DISPLIST2 0x00000028 diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index f39d9900d027b..a2380d8560000 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data) } static const struct vc4_crtc_data vc4_txp_crtc_data = { + .hvs_available_channels = BIT(2), .hvs_output = 2, }; -- GitLab From 649abf2f5d328a5a19824f712987f0a1de095332 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:47 +0200 Subject: [PATCH 0864/1494] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data Not all pixelvalve FIFOs in vc5 have the same depth, so we need to add that to our vc4_crtc_data structure to be able to compute the fill level properly later on. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/7df3549c1bea9b0a27c784dc416bb9a831e4e18f.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++--- drivers/gpu/drm/vc4/vc4_drv.h | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index b7e47ce1476cb..2c64efd2d3d97 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -206,10 +206,21 @@ void vc4_crtc_destroy(struct drm_crtc *crtc) drm_crtc_cleanup(crtc); } -static u32 vc4_get_fifo_full_level(u32 format) +static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) { - static const u32 fifo_len_bytes = 64; + const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); + u32 fifo_len_bytes = pv_data->fifo_depth; + /* + * Pixels are pulled from the HVS if the number of bytes is + * lower than the FIFO full level. + * + * The latency of the pixel fetch mechanism is 6 pixels, so we + * need to convert those 6 pixels in bytes, depending on the + * format, and then subtract that from the length of the FIFO + * to make sure we never end up in a situation where the FIFO + * is full. + */ switch (format) { case PV_CONTROL_FORMAT_DSIV_16: case PV_CONTROL_FORMAT_DSIC_16: @@ -326,7 +337,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) CRTC_WRITE(PV_CONTROL, VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | - VC4_SET_FIELD(vc4_get_fifo_full_level(format), + VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format), PV_CONTROL_FIFO_LEVEL) | VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | PV_CONTROL_CLR_AT_START | @@ -785,6 +796,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = { .hvs_output = 0, }, .debugfs_name = "crtc0_regs", + .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0, @@ -798,6 +810,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = { .hvs_output = 2, }, .debugfs_name = "crtc1_regs", + .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1, @@ -811,6 +824,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = { .hvs_output = 1, }, .debugfs_name = "crtc2_regs", + .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 9e81ad8331f18..179010b9a010d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -457,6 +457,9 @@ struct vc4_crtc_data { struct vc4_pv_data { struct vc4_crtc_data base; + /* Depth of the PixelValve FIFO in bytes */ + unsigned int fifo_depth; + /* Number of pixels output per clock period */ u8 pixels_per_clock; -- GitLab From 62c5d55e25cb5ce87b7add4a9a3ec0acd8d125b3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:48 +0200 Subject: [PATCH 0865/1494] drm/vc4: crtc: Add function to compute FIFO level bits The longer FIFOs in vc5 pixelvalves means that the FIFO full level doesn't fit in the original register field and that we also have a secondary field. In order to prepare for this, let's move the registers fill part to a helper function. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/e46a3823128af50c1c833de8fa9b95e9b86c2f66.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 2c64efd2d3d97..1d9e3658ae59b 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -234,6 +234,15 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) } } +static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, + u32 format) +{ + u32 level = vc4_get_fifo_full_level(vc4_crtc, format); + + return VC4_SET_FIELD(level & 0x3f, + PV_CONTROL_FIFO_LEVEL); +} + /* * Returns the encoder attached to the CRTC. * @@ -336,9 +345,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); CRTC_WRITE(PV_CONTROL, + vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | - VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format), - PV_CONTROL_FIFO_LEVEL) | VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | PV_CONTROL_CLR_AT_START | PV_CONTROL_TRIGGER_UNDERFLOW | -- GitLab From ed024b229dfdcff0402f16f5bc11e05ef07cd188 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:49 +0200 Subject: [PATCH 0866/1494] drm/vc4: crtc: Rename HDMI encoder type to HDMI0 The previous generations were only supporting a single HDMI controller, but that's about to change, so put an index as well to differentiate between the two controllers. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/84e11e4793aaa30d6e5c56e305d22404ac5a932d.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- drivers/gpu/drm/vc4/vc4_drv.h | 2 +- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 1d9e3658ae59b..04744223460a2 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -835,7 +835,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = { .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { - [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI, + [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0, [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, }, }; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 179010b9a010d..5781773aec4b4 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -426,7 +426,7 @@ to_vc4_plane_state(struct drm_plane_state *state) enum vc4_encoder_type { VC4_ENCODER_TYPE_NONE, - VC4_ENCODER_TYPE_HDMI, + VC4_ENCODER_TYPE_HDMI0, VC4_ENCODER_TYPE_VEC, VC4_ENCODER_TYPE_DSI0, VC4_ENCODER_TYPE_DSI1, diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 15a11cd4de256..ec34c08b16df6 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1309,7 +1309,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) GFP_KERNEL); if (!vc4_hdmi_encoder) return -ENOMEM; - vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI; + vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0; hdmi->encoder = &vc4_hdmi_encoder->base.base; hdmi->pdev = pdev; -- GitLab From aa2fd1ca7f16e9fdb5658977e3d24912f54bdcfd Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:50 +0200 Subject: [PATCH 0867/1494] drm/vc4: crtc: Add HDMI1 encoder type The BCM2711 sports a second HDMI controller, so let's add that second HDMI encoder type. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/6ba56d2421a4ad59ce72178e8f37eacfbd72cb33.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 5781773aec4b4..4126506b3a693 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -427,6 +427,7 @@ to_vc4_plane_state(struct drm_plane_state *state) enum vc4_encoder_type { VC4_ENCODER_TYPE_NONE, VC4_ENCODER_TYPE_HDMI0, + VC4_ENCODER_TYPE_HDMI1, VC4_ENCODER_TYPE_VEC, VC4_ENCODER_TYPE_DSI0, VC4_ENCODER_TYPE_DSI1, -- GitLab From eb92bc72cdab2550fa1c5b05b866bf209df9fd08 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:51 +0200 Subject: [PATCH 0868/1494] drm/vc4: crtc: Disable color management for HVS5 The HVS5 uses different color matrices. Disable color management support for now. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/e528e2edf0a1be3930196d437e548114dd9fcf59.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------ drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 04744223460a2..41bc61d5a61ff 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -874,6 +874,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, const struct drm_crtc_funcs *crtc_funcs, const struct drm_crtc_helper_funcs *crtc_helper_funcs) { + struct vc4_dev *vc4 = to_vc4_dev(drm); struct drm_crtc *crtc = &vc4_crtc->base; struct drm_plane *primary_plane; unsigned int i; @@ -893,13 +894,17 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, crtc_funcs, NULL); drm_crtc_helper_add(crtc, crtc_helper_funcs); - drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); - drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); - /* We support CTM, but only for one CRTC at a time. It's therefore - * implemented as private driver state in vc4_kms, not here. - */ - drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); + if (!vc4->hvs->hvs5) { + drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); + + drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); + + /* We support CTM, but only for one CRTC at a time. It's therefore + * implemented as private driver state in vc4_kms, not here. + */ + drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size); + } for (i = 0; i < crtc->gamma_size; i++) { vc4_crtc->lut_r[i] = i; diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 31a9bc5ef84e2..fa61cad3a53d8 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -443,7 +443,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc) HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), SCALER_DISPBKGND_AUTOHS | - SCALER_DISPBKGND_GAMMA | + ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); /* Reload the LUT, since the SRAMs would have been disabled if -- GitLab From 5ffabf5001b9cdcb0a73da6cbf316833077aa4b8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:52 +0200 Subject: [PATCH 0869/1494] drm/vc4: crtc: Turn pixelvalve reset into a function The driver resets the pixelvalve FIFO in a number of occurences without always using the same sequence. Since this will be critical for BCM2711, let's move that sequence to a function so that we are consistent. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/fb31003a9eee02c4b949556299ff41f0a113499a.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 41bc61d5a61ff..c2ab907611e32 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -267,6 +267,15 @@ static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc) return NULL; } +static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) +{ + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + + /* The PV needs to be disabled before it can be flushed */ + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR); +} + static void vc4_crtc_config_pv(struct drm_crtc *crtc) { struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); @@ -282,10 +291,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; u8 ppc = pv_data->pixels_per_clock; - /* Reset the PV fifo. */ - CRTC_WRITE(PV_CONTROL, 0); - CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN); - CRTC_WRITE(PV_CONTROL, 0); + vc4_crtc_pixelvalve_reset(crtc); CRTC_WRITE(PV_HORZA, VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc, @@ -430,9 +436,9 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, require_hvs_enabled(dev); - /* Reset the PV fifo. */ - CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | - PV_CONTROL_FIFO_CLR | PV_CONTROL_EN); + vc4_crtc_pixelvalve_reset(crtc); + + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); /* Enable vblank irq handling before crtc is started otherwise * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist(). -- GitLab From be26296a259dcce9c89b517ee95e5924334086dc Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:53 +0200 Subject: [PATCH 0870/1494] drm/vc4: crtc: Move PV dump to config_pv Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't really make much sense to dump its register content in its caller. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/c195af7d9e140a2a6db32992ee7e54071c6f94ba.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index c2ab907611e32..181d3fd57bc76 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; u8 ppc = pv_data->pixels_per_clock; + bool debug_dump_regs = false; + + if (debug_dump_regs) { + struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); + dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n", + drm_crtc_index(crtc)); + drm_print_regset32(&p, &vc4_crtc->regset); + } vc4_crtc_pixelvalve_reset(crtc); @@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) PV_CONTROL_WAIT_HSTART | VC4_SET_FIELD(vc4_encoder->clock_select, PV_CONTROL_CLK_SELECT)); -} - -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) -{ - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - bool debug_dump_regs = false; if (debug_dump_regs) { struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); - dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n", + dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n", drm_crtc_index(crtc)); drm_print_regset32(&p, &vc4_crtc->regset); } +} +static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) +{ vc4_crtc_config_pv(crtc); vc4_hvs_mode_set_nofb(crtc); - - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev); - dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n", - drm_crtc_index(crtc)); - drm_print_regset32(&p, &vc4_crtc->regset); - } } static void require_hvs_enabled(struct drm_device *dev) -- GitLab From 6d01a106b4c88f0c9ff5240c54d26d3d08e5943e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:54 +0200 Subject: [PATCH 0871/1494] drm/vc4: crtc: Move HVS init and close to a function In order to make further refactoring easier, let's move the HVS channel setup / teardown to their own function. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/fb1b5299d1636ddce8340b51a80d51641839f83b.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index fa61cad3a53d8..dde931233d4aa 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc) vc4_hvs_lut_load(crtc); } +static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, + struct drm_display_mode *mode, bool oneshot) +{ + struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); + unsigned int chan = vc4_crtc_state->assigned_channel; + u32 dispctrl; + + /* Turn on the scaler, which will wait for vstart to start + * compositing. + * When feeding the transposer, we should operate in oneshot + * mode. + */ + dispctrl = SCALER_DISPCTRLX_ENABLE; + + if (!vc4->hvs->hvs5) + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, + SCALER_DISPCTRLX_HEIGHT) | + (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0); + else + dispctrl |= VC4_SET_FIELD(mode->hdisplay, + SCALER5_DISPCTRLX_WIDTH) | + VC4_SET_FIELD(mode->vdisplay, + SCALER5_DISPCTRLX_HEIGHT) | + (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0); + + HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl); + + return 0; +} + +static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + + if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE) + return; + + HVS_WRITE(SCALER_DISPCTRLX(chan), + HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET); + HVS_WRITE(SCALER_DISPCTRLX(chan), + HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE); + + /* Once we leave, the scaler should be disabled and its fifo empty. */ + WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET); + + WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)), + SCALER_DISPSTATX_MODE) != + SCALER_DISPSTATX_MODE_DISABLED); + + WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & + (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != + SCALER_DISPSTATX_EMPTY); +} + int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; bool oneshot = vc4_state->feed_txp; - u32 dispctrl; vc4_hvs_update_dlist(crtc); - - /* Turn on the scaler, which will wait for vstart to start - * compositing. - * When feeding the transposer, we should operate in oneshot - * mode. - */ - dispctrl = SCALER_DISPCTRLX_ENABLE; - - if (!vc4->hvs->hvs5) - dispctrl |= VC4_SET_FIELD(mode->hdisplay, - SCALER_DISPCTRLX_WIDTH) | - VC4_SET_FIELD(mode->vdisplay, - SCALER_DISPCTRLX_HEIGHT) | - (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0); - else - dispctrl |= VC4_SET_FIELD(mode->hdisplay, - SCALER5_DISPCTRLX_WIDTH) | - VC4_SET_FIELD(mode->vdisplay, - SCALER5_DISPCTRLX_HEIGHT) | - (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0); - - HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl); + vc4_hvs_init_channel(vc4, crtc, mode, oneshot); } void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state); unsigned int chan = vc4_state->assigned_channel; - if (HVS_READ(SCALER_DISPCTRLX(chan)) & - SCALER_DISPCTRLX_ENABLE) { - HVS_WRITE(SCALER_DISPCTRLX(chan), - SCALER_DISPCTRLX_RESET); - - /* While the docs say that reset is self-clearing, it - * seems it doesn't actually. - */ - HVS_WRITE(SCALER_DISPCTRLX(chan), 0); - } - - /* Once we leave, the scaler should be disabled and its fifo empty. */ - - WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET); - - WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)), - SCALER_DISPSTATX_MODE) != - SCALER_DISPSTATX_MODE_DISABLED); - - WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) & - (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != - SCALER_DISPSTATX_EMPTY); + vc4_hvs_stop_channel(dev, chan); } void vc4_hvs_atomic_flush(struct drm_crtc *crtc, -- GitLab From d2f06525f67d1c224589087feca70c9a214237b2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:55 +0200 Subject: [PATCH 0872/1494] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function Since most of the HVS channel is setup in the init function, let's move the gamma setup there too. As this makes the HVS mode_set function empty, let's remove it in the process. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/d439da8f1592a450a6ad35ab1f9e77def17c7965.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 -- drivers/gpu/drm/vc4/vc4_drv.h | 1 - drivers/gpu/drm/vc4/vc4_hvs.c | 59 +++++++++------------------------- drivers/gpu/drm/vc4/vc4_txp.c | 1 - 4 files changed, 16 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 181d3fd57bc76..284a85b9d7d48 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) { vc4_crtc_config_pv(crtc); - - vc4_hvs_mode_set_nofb(crtc); } static void require_hvs_enabled(struct drm_device *dev) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 4126506b3a693..dfcc684f5d283 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state); void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state); -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc); void vc4_hvs_dump_state(struct drm_device *dev); void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel); void vc4_hvs_mask_underrun(struct drm_device *dev, int channel); diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index dde931233d4aa..efaae60bb3231 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, { struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); unsigned int chan = vc4_crtc_state->assigned_channel; + bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; + u32 dispbkgndx; u32 dispctrl; /* Turn on the scaler, which will wait for vstart to start @@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl); + dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan)); + dispbkgndx &= ~SCALER_DISPBKGND_GAMMA; + dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE; + + HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | + SCALER_DISPBKGND_AUTOHS | + ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | + (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); + + /* Reload the LUT, since the SRAMs would have been disabled if + * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. + */ + vc4_hvs_lut_load(crtc); + return 0; } @@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, } } -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); - struct drm_display_mode *mode = &crtc->state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; - - if (vc4_state->assigned_channel == 2) { - u32 dispctrl; - u32 dsp3_mux; - - /* - * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to - * FIFO X'. - * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'. - * - * DSP3 is connected to FIFO2 unless the transposer is - * enabled. In this case, FIFO 2 is directly accessed by the - * TXP IP, and we need to disable the FIFO2 -> pixelvalve1 - * route. - */ - if (vc4_state->feed_txp) - dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX); - else - dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); - - dispctrl = HVS_READ(SCALER_DISPCTRL) & - ~SCALER_DISPCTRL_DSP3_MUX_MASK; - HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux); - } - - HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), - SCALER_DISPBKGND_AUTOHS | - ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | - (interlace ? SCALER_DISPBKGND_INTERLACE : 0)); - - /* Reload the LUT, since the SRAMs would have been disabled if - * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once. - */ - vc4_hvs_lut_load(crtc); -} - void vc4_hvs_mask_underrun(struct drm_device *dev, int channel) { struct vc4_dev *vc4 = to_vc4_dev(dev); diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index a2380d8560000..849dcafbfff17 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = { .atomic_flush = vc4_hvs_atomic_flush, .atomic_enable = vc4_txp_atomic_enable, .atomic_disable = vc4_txp_atomic_disable, - .mode_set_nofb = vc4_hvs_mode_set_nofb, }; static irqreturn_t vc4_txp_interrupt(int irq, void *data) -- GitLab From f8b13d9bcc674efa3af2d75414fa612936a5a2ea Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:56 +0200 Subject: [PATCH 0873/1494] drm/vc4: hvs: Make sure our channel is reset In order to clear our intermediate FIFOs that might end up with a stale pixel, let's make sure our FIFO channel is reset every time our channel is setup. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/b34c562b36177c758dd2e9d84bceb07689bfbe05.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index efaae60bb3231..0f56a7b579168 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, u32 dispbkgndx; u32 dispctrl; + HVS_WRITE(SCALER_DISPCTRLX(chan), 0); + HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET); + HVS_WRITE(SCALER_DISPCTRLX(chan), 0); + /* Turn on the scaler, which will wait for vstart to start * compositing. * When feeding the transposer, we should operate in oneshot -- GitLab From a4d89568735b1bbce01ef282e49a590c5cb09597 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:57 +0200 Subject: [PATCH 0874/1494] drm/vc4: crtc: Remove mode_set_nofb On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the pixelvalve needs to be setup each time there's a mode change or enable / disable sequence. Therefore, we can't really use mode_set_nofb anymore to configure it, but we need to move it to atomic_enable. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/f86c7a6946f98262f1cf59a461596a796d4bcc5f.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 284a85b9d7d48..2eda2e6429ecc 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) } } -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) -{ - vc4_crtc_config_pv(crtc); -} - static void require_hvs_enabled(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, require_hvs_enabled(dev); vc4_crtc_pixelvalve_reset(crtc); + vc4_crtc_config_pv(crtc); CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); @@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = { }; static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { - .mode_set_nofb = vc4_crtc_mode_set_nofb, .mode_valid = vc4_crtc_mode_valid, .atomic_check = vc4_crtc_atomic_check, .atomic_flush = vc4_hvs_atomic_flush, -- GitLab From 6370be84d81ec717b0353cb29441db3bc19811a0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:58 +0200 Subject: [PATCH 0875/1494] drm/vc4: crtc: Remove redundant pixelvalve reset Since we moved the pixelvalve configuration to atomic_enable, we're now first calling the function that resets the pixelvalve and then the one that configures it. However, the first thing the latter is doing is calling the reset function, meaning that we reset twice our pixelvalve. Let's remove the first call. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/a0a31af0d4a7a070de979f0e5b618d9e2c730e7f.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 2eda2e6429ecc..2c5ff45dc3155 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, require_hvs_enabled(dev); - vc4_crtc_pixelvalve_reset(crtc); vc4_crtc_config_pv(crtc); CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); -- GitLab From 4b72b10a64ba70ce0b7d840ffc34d5841a660a5b Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:00:59 +0200 Subject: [PATCH 0876/1494] drm/vc4: crtc: Move HVS channel init before the PV initialisation In order to avoid stale pixels getting stuck in an intermediate FIFO between the HVS and the pixelvalve on BCM2711, we need to configure the HVS channel before the pixelvalve is reset and configured. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/9d7c5a03bc1a1e6d50f7b617cc2d8a46a4bbb7bc.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 2c5ff45dc3155..b7b0e19e2fe12 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, require_hvs_enabled(dev); - vc4_crtc_config_pv(crtc); - - CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); - /* Enable vblank irq handling before crtc is started otherwise * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist(). */ @@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, vc4_hvs_atomic_enable(crtc, old_state); + vc4_crtc_config_pv(crtc); + + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); + /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. */ -- GitLab From 792c3132bc1b0990db8e3dbef2e9a49bdf80cd62 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:00 +0200 Subject: [PATCH 0877/1494] drm/vc4: encoder: Add finer-grained encoder callbacks In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller requires very precise ordering and timing that the regular atomic callbacks don't provide. Let's add new callbacks on top of the regular ones to be able to split the configuration as needed. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/1dd78efe8f29add73c97d0148cfd4ec8e34aaf22.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index b7b0e19e2fe12..d0b326e1df0af 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); int ret; require_hvs_enabled(dev); @@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); + if (vc4_encoder->post_crtc_disable) + vc4_encoder->post_crtc_disable(encoder); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); vc4_hvs_atomic_disable(crtc, old_state); + if (vc4_encoder->post_crtc_powerdown) + vc4_encoder->post_crtc_powerdown(encoder); + /* * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. @@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); require_hvs_enabled(dev); @@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, vc4_hvs_atomic_enable(crtc, old_state); + if (vc4_encoder->pre_crtc_configure) + vc4_encoder->pre_crtc_configure(encoder); + vc4_crtc_config_pv(crtc); CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN); + if (vc4_encoder->pre_crtc_enable) + vc4_encoder->pre_crtc_enable(encoder); + /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. */ CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); + + if (vc4_encoder->post_crtc_enable) + vc4_encoder->post_crtc_enable(encoder); } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index dfcc684f5d283..251fcc35530c6 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -439,6 +439,13 @@ struct vc4_encoder { struct drm_encoder base; enum vc4_encoder_type type; u32 clock_select; + + void (*pre_crtc_configure)(struct drm_encoder *encoder); + void (*pre_crtc_enable)(struct drm_encoder *encoder); + void (*post_crtc_enable)(struct drm_encoder *encoder); + + void (*post_crtc_disable)(struct drm_encoder *encoder); + void (*post_crtc_powerdown)(struct drm_encoder *encoder); }; static inline struct vc4_encoder * -- GitLab From b7cb67a6b4fbb99a297bb0a57d906f56d81b29c9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:01 +0200 Subject: [PATCH 0878/1494] drm/vc4: crtc: Add a delay after disabling the PixelValve output In order to avoid pixels getting stuck in the (unflushable) FIFO between the HVS and the PV, we need to add some delay after disabling the PV output and before disabling the HDMI controller. 20ms seems to be good enough so let's use that. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/15cf215bd2ceebd203c4010c09c21a4019c650ed.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index d0b326e1df0af..4c23cf8aefb99 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -403,6 +403,24 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); + /* + * This delay is needed to avoid to get a pixel stuck in an + * unflushable FIFO between the pixelvalve and the HDMI + * controllers on the BCM2711. + * + * Timing is fairly sensitive here, so mdelay is the safest + * approach. + * + * If it was to be reworked, the stuck pixel happens on a + * BCM2711 when changing mode with a good probability, so a + * script that changes mode on a regular basis should trigger + * the bug after less than 10 attempts. It manifests itself with + * every pixels being shifted by one to the right, and thus the + * last pixel of a line actually being displayed as the first + * pixel on the next line. + */ + mdelay(20); + if (vc4_encoder->post_crtc_disable) vc4_encoder->post_crtc_disable(encoder); -- GitLab From 0d2b96af53c973942c8c5a2c6629915774bae187 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:02 +0200 Subject: [PATCH 0879/1494] drm/vc4: crtc: Clear the PixelValve FIFO on disable In order to avoid a stale pixel getting stuck on mode change or a disable / enable cycle, we need to make sure to flush the PV FIFO on disable. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/26fe48b09d77088679ed0c8cb8cf0db2f108195e.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 4c23cf8aefb99..73d918706f7e1 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -424,8 +424,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, if (vc4_encoder->post_crtc_disable) vc4_encoder->post_crtc_disable(encoder); - CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); - + vc4_crtc_pixelvalve_reset(crtc); vc4_hvs_atomic_disable(crtc, old_state); if (vc4_encoder->post_crtc_powerdown) -- GitLab From 9e30cfd0764e1018897b8f4830d1cffd59a3fe40 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:03 +0200 Subject: [PATCH 0880/1494] drm/vc4: crtc: Clear the PixelValve FIFO during configuration Even though it's not really clear why we need to flush the PV FIFO during the configuration even though we started by flushing it, experience shows that without it we get a stale pixel stuck in the FIFO between the HVS and the PV. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/ccd6269ba37b2f849ba6e62471c99bd93a4548a0.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 73d918706f7e1..00b2c2b011d16 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) if (is_dsi) CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); - CRTC_WRITE(PV_CONTROL, + CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | -- GitLab From 50e9d6cb5dbfec87b39f7d6f270841328f9ba555 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:04 +0200 Subject: [PATCH 0881/1494] drm/vc4: hvs: Make the stop_channel function public During the transition from the firmware to the KMS driver, we need to pay particular attention to how we deal with the pixelvalves that have already been enabled, otherwise either timeouts or stuck pixels can occur. We'll thus need to call the function to stop an HVS channel at boot. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/a9d5f0891c3bc1deb6b16d56ca6994ed912ec7c7.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 251fcc35530c6..554c2e29b23d3 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -907,6 +907,7 @@ void vc4_irq_reset(struct drm_device *dev); /* vc4_hvs.c */ extern struct platform_driver vc4_hvs_driver; +void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output); int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state); void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 0f56a7b579168..b5ee9556e8218 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -248,7 +248,7 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, return 0; } -static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) +void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan) { struct vc4_dev *vc4 = to_vc4_dev(dev); -- GitLab From 29bbb93080a964db806e18acde3540278581f68d Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:05 +0200 Subject: [PATCH 0882/1494] drm/vc4: hvs: Introduce a function to get the assigned FIFO At boot time, if we detect that a pixelvalve has been enabled, we need to be able to retrieve the HVS channel it has been assigned to so that we can disable that channel too. Let's create that function that returns the FIFO or an error from a given output. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/178192d90874559b8386139f2226e773347729fc.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_hvs.c | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 554c2e29b23d3..860be019d8e30 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -908,6 +908,7 @@ void vc4_irq_reset(struct drm_device *dev); /* vc4_hvs.c */ extern struct platform_driver vc4_hvs_driver; void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output); +int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output); int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state); void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state); diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index b5ee9556e8218..4d0a833366cee 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -19,6 +19,7 @@ * each CRTC. */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/platform_device.h> @@ -196,6 +197,59 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc) vc4_hvs_lut_load(crtc); } +int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + u32 reg; + int ret; + + if (!vc4->hvs->hvs5) + return output; + + switch (output) { + case 0: + return 0; + + case 1: + return 1; + + case 2: + reg = HVS_READ(SCALER_DISPECTRL); + ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg); + if (ret == 0) + return 2; + + return 0; + + case 3: + reg = HVS_READ(SCALER_DISPCTRL); + ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg); + if (ret == 3) + return -EPIPE; + + return ret; + + case 4: + reg = HVS_READ(SCALER_DISPEOLN); + ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg); + if (ret == 3) + return -EPIPE; + + return ret; + + case 5: + reg = HVS_READ(SCALER_DISPDITHER); + ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg); + if (ret == 3) + return -EPIPE; + + return ret; + + default: + return -EPIPE; + } +} + static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc, struct drm_display_mode *mode, bool oneshot) { -- GitLab From 2d14ffe2737cd224101405641cbd48973fa5991a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:06 +0200 Subject: [PATCH 0883/1494] drm/vc4: crtc: Move the CRTC disable out We'll need to reuse the part that disables the HVS and PixelValve during boot too, so let's create a separate function. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/5288fb72ed2da643085dce1bc7f6d6f656bf176e.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 00b2c2b011d16..4156c5f668770 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -384,20 +384,14 @@ static void require_hvs_enabled(struct drm_device *dev) SCALER_DISPCTRL_ENABLE); } -static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) +static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel) { - struct drm_device *dev = crtc->dev; - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + struct drm_device *dev = crtc->dev; int ret; - require_hvs_enabled(dev); - - /* Disable vblank irq handling before crtc is disabled. */ - drm_crtc_vblank_off(crtc); - CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN); ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); @@ -421,15 +415,31 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, */ mdelay(20); - if (vc4_encoder->post_crtc_disable) + if (vc4_encoder && vc4_encoder->post_crtc_disable) vc4_encoder->post_crtc_disable(encoder); vc4_crtc_pixelvalve_reset(crtc); - vc4_hvs_atomic_disable(crtc, old_state); + vc4_hvs_stop_channel(dev, channel); - if (vc4_encoder->post_crtc_powerdown) + if (vc4_encoder && vc4_encoder->post_crtc_powerdown) vc4_encoder->post_crtc_powerdown(encoder); + return 0; +} + +static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state); + struct drm_device *dev = crtc->dev; + + require_hvs_enabled(dev); + + /* Disable vblank irq handling before crtc is disabled. */ + drm_crtc_vblank_off(crtc); + + vc4_crtc_disable(crtc, old_vc4_state->assigned_channel); + /* * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. -- GitLab From 875a4d5368424d6cf57d4b7250b470f1a8ad2c14 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:07 +0200 Subject: [PATCH 0884/1494] drm/vc4: drv: Disable the CRTC at boot time In order to prevent issues during the firmware to KMS transition, we need to make sure the pixelvalve are disabled at boot time so that the DRM state matches the hardware state. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/ad57f1bdeae7a99631713b0fc193c86f223de042.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 25 +++++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.c | 4 ++++ drivers/gpu/drm/vc4/vc4_drv.h | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 4156c5f668770..dfac304fe2b00 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -427,6 +427,31 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel) return 0; } +int vc4_crtc_disable_at_boot(struct drm_crtc *crtc) +{ + struct drm_device *drm = crtc->dev; + struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); + int channel; + + if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node, + "brcm,bcm2711-pixelvalve2") || + of_device_is_compatible(vc4_crtc->pdev->dev.of_node, + "brcm,bcm2711-pixelvalve4"))) + return 0; + + if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN)) + return 0; + + if (!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN)) + return 0; + + channel = vc4_hvs_get_fifo_from_output(drm, vc4_crtc->data->hvs_output); + if (channel < 0) + return 0; + + return vc4_crtc_disable(crtc, channel); +} + static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 38343d2fb4fb4..9567d10192121 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -252,6 +252,7 @@ static int vc4_drm_bind(struct device *dev) struct drm_device *drm; struct vc4_dev *vc4; struct device_node *node; + struct drm_crtc *crtc; int ret = 0; dev->coherent_dma_mask = DMA_BIT_MASK(32); @@ -298,6 +299,9 @@ static int vc4_drm_bind(struct device *dev) if (ret < 0) goto unbind_all; + drm_for_each_crtc(crtc, drm) + vc4_crtc_disable_at_boot(crtc); + ret = drm_dev_register(drm, 0); if (ret < 0) goto unbind_all; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 860be019d8e30..1a97545b92440 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -813,6 +813,7 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo); /* vc4_crtc.c */ extern struct platform_driver vc4_crtc_driver; +int vc4_crtc_disable_at_boot(struct drm_crtc *crtc); int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, const struct drm_crtc_funcs *crtc_funcs, const struct drm_crtc_helper_funcs *crtc_helper_funcs); -- GitLab From 2ed1989727f3109bb1b594c6a57c0418d5e3c7ed Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:08 +0200 Subject: [PATCH 0885/1494] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves The BCM2711 comes with other pixelvalves that have different requirements and capabilities. Let's document their compatible. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Rob Herring <robh+dt@kernel.org> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/3a21824460d96245984d730e446863a4853f2ae5.1599120059.git-series.maxime@cerno.tech --- .../bindings/display/brcm,bcm2835-pixelvalve0.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml index e60791db1fa12..4e1ba03f6477f 100644 --- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml +++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml @@ -15,6 +15,11 @@ properties: - brcm,bcm2835-pixelvalve0 - brcm,bcm2835-pixelvalve1 - brcm,bcm2835-pixelvalve2 + - brcm,bcm2711-pixelvalve0 + - brcm,bcm2711-pixelvalve1 + - brcm,bcm2711-pixelvalve2 + - brcm,bcm2711-pixelvalve3 + - brcm,bcm2711-pixelvalve4 reg: maxItems: 1 -- GitLab From 658a731c50e5be8870f05902ca820cbad4ad1322 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:09 +0200 Subject: [PATCH 0886/1494] drm/vc4: crtc: Add BCM2711 pixelvalves The BCM2711 has 5 pixelvalves, so now that our driver is ready, let's add support for them. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/2553ec9ece0d8a0e5299ff74ed932a38703c5db9.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 95 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/vc4/vc4_regs.h | 7 +++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index dfac304fe2b00..a393f93390a2e 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -208,6 +208,7 @@ void vc4_crtc_destroy(struct drm_crtc *crtc) static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) { + const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); u32 fifo_len_bytes = pv_data->fifo_depth; @@ -230,6 +231,13 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) case PV_CONTROL_FORMAT_24: case PV_CONTROL_FORMAT_DSIV_24: default: + /* + * For some reason, the pixelvalve4 doesn't work with + * the usual formula and will only work with 32. + */ + if (crtc_data->hvs_output == 5) + return 32; + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; } } @@ -238,9 +246,13 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, u32 format) { u32 level = vc4_get_fifo_full_level(vc4_crtc, format); + u32 ret = 0; + + ret |= VC4_SET_FIELD((level >> 6), + PV5_CONTROL_FIFO_LEVEL_HIGH); - return VC4_SET_FIELD(level & 0x3f, - PV_CONTROL_FIFO_LEVEL); + return ret | VC4_SET_FIELD(level & 0x3f, + PV_CONTROL_FIFO_LEVEL); } /* @@ -278,6 +290,8 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc) static void vc4_crtc_config_pv(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); @@ -358,6 +372,11 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc) if (is_dsi) CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); + if (vc4->hvs->hvs5) + CRTC_WRITE(PV_MUX_CFG, + VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, + PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); + CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | @@ -907,10 +926,82 @@ static const struct vc4_pv_data bcm2835_pv2_data = { }, }; +static const struct vc4_pv_data bcm2711_pv0_data = { + .base = { + .hvs_available_channels = BIT(0), + .hvs_output = 0, + }, + .debugfs_name = "crtc0_regs", + .fifo_depth = 64, + .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_DSI0, + [1] = VC4_ENCODER_TYPE_DPI, + }, +}; + +static const struct vc4_pv_data bcm2711_pv1_data = { + .base = { + .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), + .hvs_output = 3, + }, + .debugfs_name = "crtc1_regs", + .fifo_depth = 64, + .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_DSI1, + [1] = VC4_ENCODER_TYPE_SMI, + }, +}; + +static const struct vc4_pv_data bcm2711_pv2_data = { + .base = { + .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), + .hvs_output = 4, + }, + .debugfs_name = "crtc2_regs", + .fifo_depth = 256, + .pixels_per_clock = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI0, + }, +}; + +static const struct vc4_pv_data bcm2711_pv3_data = { + .base = { + .hvs_available_channels = BIT(1), + .hvs_output = 1, + }, + .debugfs_name = "crtc3_regs", + .fifo_depth = 64, + .pixels_per_clock = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_VEC, + }, +}; + +static const struct vc4_pv_data bcm2711_pv4_data = { + .base = { + .hvs_available_channels = BIT(0) | BIT(1) | BIT(2), + .hvs_output = 5, + }, + .debugfs_name = "crtc4_regs", + .fifo_depth = 64, + .pixels_per_clock = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI1, + }, +}; + static const struct of_device_id vc4_crtc_dt_match[] = { { .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data }, { .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data }, { .compatible = "brcm,bcm2835-pixelvalve2", .data = &bcm2835_pv2_data }, + { .compatible = "brcm,bcm2711-pixelvalve0", .data = &bcm2711_pv0_data }, + { .compatible = "brcm,bcm2711-pixelvalve1", .data = &bcm2711_pv1_data }, + { .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data }, + { .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data }, + { .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data }, {} }; diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 7fbac68b6fe12..c0031ab19689e 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -129,6 +129,8 @@ #define V3D_ERRSTAT 0x00f20 #define PV_CONTROL 0x00 +# define PV5_CONTROL_FIFO_LEVEL_HIGH_MASK VC4_MASK(26, 25) +# define PV5_CONTROL_FIFO_LEVEL_HIGH_SHIFT 25 # define PV_CONTROL_FORMAT_MASK VC4_MASK(23, 21) # define PV_CONTROL_FORMAT_SHIFT 21 # define PV_CONTROL_FORMAT_24 0 @@ -208,6 +210,11 @@ #define PV_HACT_ACT 0x30 +#define PV_MUX_CFG 0x34 +# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_MASK VC4_MASK(5, 2) +# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT 2 +# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP 8 + #define SCALER_CHANNELS_COUNT 3 #define SCALER_DISPCTRL 0x00000000 -- GitLab From 3eda598241420d3469161010a157682162d83c52 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:10 +0200 Subject: [PATCH 0887/1494] drm/vc4: hdmi: Use debugfs private field We're calling vc4_debugfs_add_file with our struct vc4_hdmi pointer set in the private field, but we don't use that field and go through the main struct vc4_dev to get it. Let's use the private field directly, that will save us some trouble later on. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/24028dc06c379dbc71f98e027cce2839fdd446ce.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ec34c08b16df6..ae8c4d53e2391 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -183,9 +183,7 @@ static const struct debugfs_reg32 hd_regs[] = { static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; - struct drm_device *dev = node->minor->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *hdmi = node->info_ent->data; struct drm_printer p = drm_seq_file_printer(m); drm_print_regset32(&p, &hdmi->hdmi_regset); -- GitLab From f73100cce9ab0528808aaf818e2302ec4851de79 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:11 +0200 Subject: [PATCH 0888/1494] drm/vc4: hdmi: Move structure to header We will need to share the vc4_hdmi and related structures with multiple files, so let's create a header for it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/db3ff2babc914e38e86f794c4e49128697aed887.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 76 +----------------------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 75 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ae8c4d53e2391..5c4d2fee6b861 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -49,87 +49,13 @@ #include <sound/soc.h> #include "media/cec.h" #include "vc4_drv.h" +#include "vc4_hdmi.h" #include "vc4_regs.h" #define HSM_CLOCK_FREQ 163682864 #define CEC_CLOCK_FREQ 40000 #define CEC_CLOCK_DIV (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ) -/* HDMI audio information */ -struct vc4_hdmi_audio { - struct snd_soc_card card; - struct snd_soc_dai_link link; - struct snd_soc_dai_link_component cpu; - struct snd_soc_dai_link_component codec; - struct snd_soc_dai_link_component platform; - int samplerate; - int channels; - struct snd_dmaengine_dai_dma_data dma_data; - struct snd_pcm_substream *substream; -}; - -/* General HDMI hardware state. */ -struct vc4_hdmi { - struct platform_device *pdev; - - struct drm_encoder *encoder; - struct drm_connector *connector; - - struct vc4_hdmi_audio audio; - - struct i2c_adapter *ddc; - void __iomem *hdmicore_regs; - void __iomem *hd_regs; - int hpd_gpio; - bool hpd_active_low; - - struct cec_adapter *cec_adap; - struct cec_msg cec_rx_msg; - bool cec_tx_ok; - bool cec_irq_was_rx; - - struct clk *pixel_clock; - struct clk *hsm_clock; - - struct debugfs_regset32 hdmi_regset; - struct debugfs_regset32 hd_regset; -}; - -#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset) -#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset) -#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset) -#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset) - -/* VC4 HDMI encoder KMS struct */ -struct vc4_hdmi_encoder { - struct vc4_encoder base; - bool hdmi_monitor; - bool limited_rgb_range; -}; - -static inline struct vc4_hdmi_encoder * -to_vc4_hdmi_encoder(struct drm_encoder *encoder) -{ - return container_of(encoder, struct vc4_hdmi_encoder, base.base); -} - -/* VC4 HDMI connector KMS struct */ -struct vc4_hdmi_connector { - struct drm_connector base; - - /* Since the connector is attached to just the one encoder, - * this is the reference to it so we can do the best_encoder() - * hook. - */ - struct drm_encoder *encoder; -}; - -static inline struct vc4_hdmi_connector * -to_vc4_hdmi_connector(struct drm_connector *connector) -{ - return container_of(connector, struct vc4_hdmi_connector, base); -} - static const struct debugfs_reg32 hdmi_regs[] = { VC4_REG32(VC4_HDMI_CORE_REV), VC4_REG32(VC4_HDMI_SW_RESET_CONTROL), diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h new file mode 100644 index 0000000000000..5ec5d1f6b1e60 --- /dev/null +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -0,0 +1,86 @@ +#ifndef _VC4_HDMI_H_ +#define _VC4_HDMI_H_ + +#include <drm/drm_connector.h> +#include <media/cec.h> +#include <sound/dmaengine_pcm.h> +#include <sound/soc.h> + +#include "vc4_drv.h" + +/* HDMI audio information */ +struct vc4_hdmi_audio { + struct snd_soc_card card; + struct snd_soc_dai_link link; + struct snd_soc_dai_link_component cpu; + struct snd_soc_dai_link_component codec; + struct snd_soc_dai_link_component platform; + int samplerate; + int channels; + struct snd_dmaengine_dai_dma_data dma_data; + struct snd_pcm_substream *substream; +}; + +/* General HDMI hardware state. */ +struct vc4_hdmi { + struct platform_device *pdev; + + struct drm_encoder *encoder; + struct drm_connector *connector; + + struct vc4_hdmi_audio audio; + + struct i2c_adapter *ddc; + void __iomem *hdmicore_regs; + void __iomem *hd_regs; + int hpd_gpio; + bool hpd_active_low; + + struct cec_adapter *cec_adap; + struct cec_msg cec_rx_msg; + bool cec_tx_ok; + bool cec_irq_was_rx; + + struct clk *pixel_clock; + struct clk *hsm_clock; + + struct debugfs_regset32 hdmi_regset; + struct debugfs_regset32 hd_regset; +}; + +#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset) +#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset) +#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset) +#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset) + +/* VC4 HDMI encoder KMS struct */ +struct vc4_hdmi_encoder { + struct vc4_encoder base; + bool hdmi_monitor; + bool limited_rgb_range; +}; + +static inline struct vc4_hdmi_encoder * +to_vc4_hdmi_encoder(struct drm_encoder *encoder) +{ + return container_of(encoder, struct vc4_hdmi_encoder, base.base); +} + +/* VC4 HDMI connector KMS struct */ +struct vc4_hdmi_connector { + struct drm_connector base; + + /* Since the connector is attached to just the one encoder, + * this is the reference to it so we can do the best_encoder() + * hook. + */ + struct drm_encoder *encoder; +}; + +static inline struct vc4_hdmi_connector * +to_vc4_hdmi_connector(struct drm_connector *connector) +{ + return container_of(connector, struct vc4_hdmi_connector, base); +} + +#endif /* _VC4_HDMI_H_ */ -- GitLab From c98c85bb316cd5f4d85458f0aebb41073c8bad83 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:12 +0200 Subject: [PATCH 0889/1494] drm/vc4: hdmi: rework connectors and encoders the vc4_hdmi driver has some custom structures to hold the data it needs to associate with the drm_encoder and drm_connector structures. However, it allocates them separately from the vc4_hdmi structure which makes it more complicated than it needs to be. Move those structures to be contained by vc4_hdmi and update the code accordingly. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/93b418d63c876355af2b3d3afebe31a256268623.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++------------------ drivers/gpu/drm/vc4/vc4_hdmi.h | 64 ++++++++++++------------- 2 files changed, 72 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 5c4d2fee6b861..9a0612a87fb86 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = .get_modes = vc4_hdmi_connector_get_modes, }; -static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, - struct drm_encoder *encoder, - struct i2c_adapter *ddc) +static int vc4_hdmi_connector_init(struct drm_device *dev, + struct vc4_hdmi *vc4_hdmi, + struct i2c_adapter *ddc) { - struct drm_connector *connector; - struct vc4_hdmi_connector *hdmi_connector; + struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; + struct drm_connector *connector = &hdmi_connector->base; + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; int ret; - hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector), - GFP_KERNEL); - if (!hdmi_connector) - return ERR_PTR(-ENOMEM); - connector = &hdmi_connector->base; - hdmi_connector->encoder = encoder; drm_connector_init_with_ddc(dev, connector, @@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, /* Create and attach TV margin props to this connector. */ ret = drm_mode_create_tv_margin_properties(dev); if (ret) - return ERR_PTR(ret); + return ret; drm_connector_attach_tv_margin_properties(connector); @@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, drm_connector_attach_encoder(connector, encoder); - return connector; + return 0; } static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, @@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); struct vc4_dev *vc4 = encoder->dev->dev_private; struct vc4_hdmi *hdmi = vc4->hdmi; - struct drm_connector_state *cstate = hdmi->connector->state; + struct drm_connector *connector = &hdmi->connector.base; + struct drm_connector_state *cstate = connector->state; struct drm_crtc *crtc = encoder->crtc; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; union hdmi_infoframe frame; int ret; ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, - hdmi->connector, mode); + connector, mode); if (ret < 0) { DRM_ERROR("couldn't fill AVI infoframe\n"); return; } drm_hdmi_avi_infoframe_quant_range(&frame.avi, - hdmi->connector, mode, + connector, mode, vc4_encoder->limited_rgb_range ? HDMI_QUANTIZATION_RANGE_LIMITED : HDMI_QUANTIZATION_RANGE_FULL); @@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { /* HDMI audio codec callbacks */ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi) { - struct drm_device *drm = hdmi->encoder->dev; + struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); u32 hsm_clock = clk_get_rate(hdmi->hsm_clock); unsigned long n, m; @@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi) static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi) { - struct drm_encoder *encoder = hdmi->encoder; + struct drm_encoder *encoder = &hdmi->encoder.base.base; struct drm_crtc *crtc = encoder->crtc; struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); @@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = hdmi->encoder; + struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct drm_connector *connector = &hdmi->connector.base; struct vc4_dev *vc4 = to_vc4_dev(encoder->dev); int ret; @@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, VC4_HDMI_RAM_PACKET_ENABLE)) return -ENODEV; - ret = snd_pcm_hw_constraint_eld(substream->runtime, - hdmi->connector->eld); + ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld); if (ret) return ret; @@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi) { - struct drm_encoder *encoder = hdmi->encoder; + struct drm_encoder *encoder = &hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; struct device *dev = &hdmi->pdev->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); @@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = hdmi->encoder; + struct drm_encoder *encoder = &hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; struct device *dev = &hdmi->pdev->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); @@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = hdmi->encoder; + struct drm_encoder *encoder = &hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); @@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct vc4_hdmi *hdmi = snd_component_to_hdmi(component); + struct drm_connector *connector = &hdmi->connector.base; uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; - uinfo->count = sizeof(hdmi->connector->eld); + uinfo->count = sizeof(connector->eld); return 0; } @@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct vc4_hdmi *hdmi = snd_component_to_hdmi(component); + struct drm_connector *connector = &hdmi->connector.base; - memcpy(ucontrol->value.bytes.data, hdmi->connector->eld, - sizeof(hdmi->connector->eld)); + memcpy(ucontrol->value.bytes.data, connector->eld, + sizeof(connector->eld)); return 0; } @@ -1220,7 +1219,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = drm->dev_private; struct vc4_hdmi *hdmi; - struct vc4_hdmi_encoder *vc4_hdmi_encoder; + struct drm_encoder *encoder; struct device_node *ddc_node; u32 value; int ret; @@ -1229,14 +1228,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (!hdmi) return -ENOMEM; - vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder), - GFP_KERNEL); - if (!vc4_hdmi_encoder) - return -ENOMEM; - vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0; - hdmi->encoder = &vc4_hdmi_encoder->base.base; - + encoder = &hdmi->encoder.base.base; + hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; hdmi->pdev = pdev; + hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(hdmi->hdmicore_regs)) return PTR_ERR(hdmi->hdmicore_regs); @@ -1324,15 +1319,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) } pm_runtime_enable(dev); - drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS); - drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs); + drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); - hdmi->connector = - vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc); - if (IS_ERR(hdmi->connector)) { - ret = PTR_ERR(hdmi->connector); + ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc); + if (ret) goto err_destroy_encoder; - } + #ifdef CONFIG_DRM_VC4_HDMI_CEC hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, vc4, "vc4", @@ -1342,7 +1335,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret < 0) goto err_destroy_conn; - cec_fill_conn_info_from_drm(&conn_info, hdmi->connector); + cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base); cec_s_conn_info(hdmi->cec_adap, &conn_info); HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff); @@ -1379,10 +1372,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) err_delete_cec_adap: cec_delete_adapter(hdmi->cec_adap); err_destroy_conn: - vc4_hdmi_connector_destroy(hdmi->connector); + vc4_hdmi_connector_destroy(&hdmi->connector.base); #endif err_destroy_encoder: - drm_encoder_cleanup(hdmi->encoder); + drm_encoder_cleanup(encoder); err_unprepare_hsm: clk_disable_unprepare(hdmi->hsm_clock); pm_runtime_disable(dev); @@ -1400,8 +1393,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, struct vc4_hdmi *hdmi = vc4->hdmi; cec_unregister_adapter(hdmi->cec_adap); - vc4_hdmi_connector_destroy(hdmi->connector); - drm_encoder_cleanup(hdmi->encoder); + vc4_hdmi_connector_destroy(&hdmi->connector.base); + drm_encoder_cleanup(&hdmi->encoder.base.base); clk_disable_unprepare(hdmi->hsm_clock); pm_runtime_disable(dev); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 5ec5d1f6b1e60..17079a39f1b10 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -8,6 +8,36 @@ #include "vc4_drv.h" +/* VC4 HDMI encoder KMS struct */ +struct vc4_hdmi_encoder { + struct vc4_encoder base; + bool hdmi_monitor; + bool limited_rgb_range; +}; + +static inline struct vc4_hdmi_encoder * +to_vc4_hdmi_encoder(struct drm_encoder *encoder) +{ + return container_of(encoder, struct vc4_hdmi_encoder, base.base); +} + +/* VC4 HDMI connector KMS struct */ +struct vc4_hdmi_connector { + struct drm_connector base; + + /* Since the connector is attached to just the one encoder, + * this is the reference to it so we can do the best_encoder() + * hook. + */ + struct drm_encoder *encoder; +}; + +static inline struct vc4_hdmi_connector * +to_vc4_hdmi_connector(struct drm_connector *connector) +{ + return container_of(connector, struct vc4_hdmi_connector, base); +} + /* HDMI audio information */ struct vc4_hdmi_audio { struct snd_soc_card card; @@ -25,8 +55,8 @@ struct vc4_hdmi_audio { struct vc4_hdmi { struct platform_device *pdev; - struct drm_encoder *encoder; - struct drm_connector *connector; + struct vc4_hdmi_encoder encoder; + struct vc4_hdmi_connector connector; struct vc4_hdmi_audio audio; @@ -53,34 +83,4 @@ struct vc4_hdmi { #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset) #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset) -/* VC4 HDMI encoder KMS struct */ -struct vc4_hdmi_encoder { - struct vc4_encoder base; - bool hdmi_monitor; - bool limited_rgb_range; -}; - -static inline struct vc4_hdmi_encoder * -to_vc4_hdmi_encoder(struct drm_encoder *encoder) -{ - return container_of(encoder, struct vc4_hdmi_encoder, base.base); -} - -/* VC4 HDMI connector KMS struct */ -struct vc4_hdmi_connector { - struct drm_connector base; - - /* Since the connector is attached to just the one encoder, - * this is the reference to it so we can do the best_encoder() - * hook. - */ - struct drm_encoder *encoder; -}; - -static inline struct vc4_hdmi_connector * -to_vc4_hdmi_connector(struct drm_connector *connector) -{ - return container_of(connector, struct vc4_hdmi_connector, base); -} - #endif /* _VC4_HDMI_H_ */ -- GitLab From b052e70dd21c2a0eb0629c3300bf5596dc9abf2a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:13 +0200 Subject: [PATCH 0890/1494] drm/vc4: hdmi: Remove DDC argument to connector_init Now that we are passing the vc4_hdmi structure to the connector init function, we can simply use the pointer in that structure instead of having the pointer as an argument. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/4fe1b45fe45e4ba57d40154da010807d4e5db86c.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 9a0612a87fb86..1f350b068fcd4 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -192,8 +192,7 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = }; static int vc4_hdmi_connector_init(struct drm_device *dev, - struct vc4_hdmi *vc4_hdmi, - struct i2c_adapter *ddc) + struct vc4_hdmi *vc4_hdmi) { struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; struct drm_connector *connector = &hdmi_connector->base; @@ -205,7 +204,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, drm_connector_init_with_ddc(dev, connector, &vc4_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA, - ddc); + vc4_hdmi->ddc); drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); /* Create and attach TV margin props to this connector. */ @@ -1322,7 +1321,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); - ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc); + ret = vc4_hdmi_connector_init(drm, hdmi); if (ret) goto err_destroy_encoder; -- GitLab From 3408cc23c9311f45ca363112fa62e23846ffc499 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:14 +0200 Subject: [PATCH 0891/1494] drm/vc4: hdmi: Rename hdmi to vc4_hdmi The driver isn't consistent with the name given to the vc4_hdmi structure pointer in its functions. Make sure to use a consistent name. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/696be840dc427245afe94b43e0b829c728d948a7.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 283 +++++++++++++++++---------------- 1 file changed, 142 insertions(+), 141 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1f350b068fcd4..6733e4bc235b8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -109,11 +109,11 @@ static const struct debugfs_reg32 hd_regs[] = { static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; - struct vc4_hdmi *hdmi = node->info_ent->data; + struct vc4_hdmi *vc4_hdmi = node->info_ent->data; struct drm_printer p = drm_seq_file_printer(m); - drm_print_regset32(&p, &hdmi->hdmi_regset); - drm_print_regset32(&p, &hdmi->hd_regset); + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); return 0; } @@ -291,8 +291,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) { struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); struct vc4_dev *vc4 = encoder->dev->dev_private; - struct vc4_hdmi *hdmi = vc4->hdmi; - struct drm_connector *connector = &hdmi->connector.base; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_connector_state *cstate = connector->state; struct drm_crtc *crtc = encoder->crtc; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; @@ -337,7 +337,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) { struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; union hdmi_infoframe frame; int ret; @@ -346,7 +346,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; - frame.audio.channels = hdmi->audio.channels; + frame.audio.channels = vc4_hdmi->audio.channels; vc4_hdmi_write_infoframe(encoder, &frame); } @@ -361,7 +361,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; int ret; HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); @@ -370,9 +370,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) HD_WRITE(VC4_HD_VID_CTL, HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); - clk_disable_unprepare(hdmi->pixel_clock); + clk_disable_unprepare(vc4_hdmi->pixel_clock); - ret = pm_runtime_put(&hdmi->pdev->dev); + ret = pm_runtime_put(&vc4_hdmi->pdev->dev); if (ret < 0) DRM_ERROR("Failed to release power domain: %d\n", ret); } @@ -383,7 +383,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); struct drm_device *dev = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; bool debug_dump_regs = false; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; @@ -405,13 +405,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) u32 csc_ctl; int ret; - ret = pm_runtime_get_sync(&hdmi->pdev->dev); + ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); return; } - ret = clk_set_rate(hdmi->pixel_clock, + ret = clk_set_rate(vc4_hdmi->pixel_clock, mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1)); if (ret) { @@ -419,7 +419,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - ret = clk_prepare_enable(hdmi->pixel_clock); + ret = clk_prepare_enable(vc4_hdmi->pixel_clock); if (ret) { DRM_ERROR("Failed to turn on pixel clock: %d\n", ret); return; @@ -439,11 +439,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0); if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&hdmi->pdev->dev); + struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - dev_info(&hdmi->pdev->dev, "HDMI regs before:\n"); - drm_print_regset32(&p, &hdmi->hdmi_regset); - drm_print_regset32(&p, &hdmi->hd_regset); + dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n"); + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); } HD_WRITE(VC4_HD_VID_CTL, 0); @@ -518,11 +518,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&hdmi->pdev->dev); + struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - dev_info(&hdmi->pdev->dev, "HDMI regs after:\n"); - drm_print_regset32(&p, &hdmi->hdmi_regset); - drm_print_regset32(&p, &hdmi->hd_regset); + dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n"); + drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); + drm_print_regset32(&p, &vc4_hdmi->hd_regset); } HD_WRITE(VC4_HD_VID_CTL, @@ -621,15 +621,15 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { }; /* HDMI audio codec callbacks */ -static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi) +static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); - u32 hsm_clock = clk_get_rate(hdmi->hsm_clock); + u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock); unsigned long n, m; - rational_best_approximation(hsm_clock, hdmi->audio.samplerate, + rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate, VC4_HD_MAI_SMP_N_MASK >> VC4_HD_MAI_SMP_N_SHIFT, (VC4_HD_MAI_SMP_M_MASK >> @@ -641,14 +641,14 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi) VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); } -static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi) +static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_crtc *crtc = encoder->crtc; struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); const struct drm_display_mode *mode = &crtc->state->adjusted_mode; - u32 samplerate = hdmi->audio.samplerate; + u32 samplerate = vc4_hdmi->audio.samplerate; u32 n, cts; u64 tmp; @@ -680,16 +680,16 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = &hdmi->encoder.base.base; - struct drm_connector *connector = &hdmi->connector.base; + struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; + struct drm_connector *connector = &vc4_hdmi->connector.base; struct vc4_dev *vc4 = to_vc4_dev(encoder->dev); int ret; - if (hdmi->audio.substream && hdmi->audio.substream != substream) + if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream) return -EINVAL; - hdmi->audio.substream = substream; + vc4_hdmi->audio.substream = substream; /* * If the HDMI encoder hasn't probed, or the encoder is @@ -711,11 +711,11 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi) +static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; - struct device *dev = &hdmi->pdev->dev; + struct device *dev = &vc4_hdmi->pdev->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); int ret; @@ -731,14 +731,14 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi) static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct vc4_hdmi *hdmi = dai_to_hdmi(dai); + struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); - if (substream != hdmi->audio.substream) + if (substream != vc4_hdmi->audio.substream) return; - vc4_hdmi_audio_reset(hdmi); + vc4_hdmi_audio_reset(vc4_hdmi); - hdmi->audio.substream = NULL; + vc4_hdmi->audio.substream = NULL; } /* HDMI audio codec callbacks */ @@ -746,23 +746,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; - struct device *dev = &hdmi->pdev->dev; + struct device *dev = &vc4_hdmi->pdev->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); u32 audio_packet_config, channel_mask; u32 channel_map, i; - if (substream != hdmi->audio.substream) + if (substream != vc4_hdmi->audio.substream) return -EINVAL; dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__, params_rate(params), params_width(params), params_channels(params)); - hdmi->audio.channels = params_channels(params); - hdmi->audio.samplerate = params_rate(params); + vc4_hdmi->audio.channels = params_channels(params); + vc4_hdmi->audio.samplerate = params_rate(params); HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET | @@ -771,23 +771,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, VC4_HD_MAI_CTL_ERRORE | VC4_HD_MAI_CTL_ERRORF); - vc4_hdmi_audio_set_mai_clock(hdmi); + vc4_hdmi_audio_set_mai_clock(vc4_hdmi); audio_packet_config = VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT | VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS | VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER); - channel_mask = GENMASK(hdmi->audio.channels - 1, 0); + channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0); audio_packet_config |= VC4_SET_FIELD(channel_mask, VC4_HDMI_AUDIO_PACKET_CEA_MASK); /* Set the MAI threshold. This logic mimics the firmware's. */ - if (hdmi->audio.samplerate > 96000) { + if (vc4_hdmi->audio.samplerate > 96000) { HD_WRITE(VC4_HD_MAI_THR, VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) | VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); - } else if (hdmi->audio.samplerate > 48000) { + } else if (vc4_hdmi->audio.samplerate > 48000) { HD_WRITE(VC4_HD_MAI_THR, VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) | VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); @@ -811,7 +811,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map); HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); - vc4_hdmi_set_n_cts(hdmi); + vc4_hdmi_set_n_cts(vc4_hdmi); return 0; } @@ -819,8 +819,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct vc4_hdmi *hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = &hdmi->encoder.base.base; + struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); + struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_device *drm = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(drm); @@ -831,7 +831,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, HDMI_READ(VC4_HDMI_TX_PHY_CTL0) & ~VC4_HDMI_TX_PHY_RNG_PWRDN); HD_WRITE(VC4_HD_MAI_CTL, - VC4_SET_FIELD(hdmi->audio.channels, + VC4_SET_FIELD(vc4_hdmi->audio.channels, VC4_HD_MAI_CTL_CHNUM) | VC4_HD_MAI_CTL_ENABLE); break; @@ -863,8 +863,8 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct vc4_hdmi *hdmi = snd_component_to_hdmi(component); - struct drm_connector *connector = &hdmi->connector.base; + struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component); + struct drm_connector *connector = &vc4_hdmi->connector.base; uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = sizeof(connector->eld); @@ -876,8 +876,8 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct vc4_hdmi *hdmi = snd_component_to_hdmi(component); - struct drm_connector *connector = &hdmi->connector.base; + struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component); + struct drm_connector *connector = &vc4_hdmi->connector.base; memcpy(ucontrol->value.bytes.data, connector->eld, sizeof(connector->eld)); @@ -945,9 +945,9 @@ static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = { static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai) { - struct vc4_hdmi *hdmi = dai_to_hdmi(dai); + struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); - snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL); + snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL); return 0; } @@ -973,11 +973,11 @@ static const struct snd_dmaengine_pcm_config pcm_conf = { .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, }; -static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) +static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) { - struct snd_soc_dai_link *dai_link = &hdmi->audio.link; - struct snd_soc_card *card = &hdmi->audio.card; - struct device *dev = &hdmi->pdev->dev; + struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; + struct snd_soc_card *card = &vc4_hdmi->audio.card; + struct device *dev = &vc4_hdmi->pdev->dev; const __be32 *addr; int ret; @@ -995,9 +995,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) * This VC/MMU should probably be exposed to avoid this kind of hacks. */ addr = of_get_address(dev->of_node, 1, NULL, NULL); - hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA; - hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - hdmi->audio.dma_data.maxburst = 2; + vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA; + vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + vc4_hdmi->audio.dma_data.maxburst = 2; ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0); if (ret) { @@ -1020,9 +1020,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) return ret; } - dai_link->cpus = &hdmi->audio.cpu; - dai_link->codecs = &hdmi->audio.codec; - dai_link->platforms = &hdmi->audio.platform; + dai_link->cpus = &vc4_hdmi->audio.cpu; + dai_link->codecs = &vc4_hdmi->audio.codec; + dai_link->platforms = &vc4_hdmi->audio.platform; dai_link->num_cpus = 1; dai_link->num_codecs = 1; @@ -1047,7 +1047,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) * now stored in card->drvdata and should be retrieved with * snd_soc_card_get_drvdata() if needed. */ - snd_soc_card_set_drvdata(card, hdmi); + snd_soc_card_set_drvdata(card, vc4_hdmi); ret = devm_snd_soc_register_card(dev, card); if (ret) dev_err(dev, "Could not register sound card: %d\n", ret); @@ -1060,20 +1060,21 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi) static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) { struct vc4_dev *vc4 = priv; - struct vc4_hdmi *hdmi = vc4->hdmi; - - if (hdmi->cec_irq_was_rx) { - if (hdmi->cec_rx_msg.len) - cec_received_msg(hdmi->cec_adap, &hdmi->cec_rx_msg); - } else if (hdmi->cec_tx_ok) { - cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_OK, + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + + if (vc4_hdmi->cec_irq_was_rx) { + if (vc4_hdmi->cec_rx_msg.len) + cec_received_msg(vc4_hdmi->cec_adap, + &vc4_hdmi->cec_rx_msg); + } else if (vc4_hdmi->cec_tx_ok) { + cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); } else { /* * This CEC implementation makes 1 retry, so if we * get a NACK, then that means it made 2 attempts. */ - cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK, + cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, 0, 2, 0, 0); } return IRQ_HANDLED; @@ -1099,23 +1100,23 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1) static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) { struct vc4_dev *vc4 = priv; - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS); u32 cntrl1, cntrl5; if (!(stat & VC4_HDMI_CPU_CEC)) return IRQ_NONE; - hdmi->cec_rx_msg.len = 0; + vc4_hdmi->cec_rx_msg.len = 0; cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1); cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); - hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; - if (hdmi->cec_irq_was_rx) { + vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; + if (vc4_hdmi->cec_irq_was_rx) { vc4_cec_read_msg(vc4, cntrl1); cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1); cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; } else { - hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; + vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; } HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1); @@ -1217,46 +1218,46 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hdmi *hdmi; + struct vc4_hdmi *vc4_hdmi; struct drm_encoder *encoder; struct device_node *ddc_node; u32 value; int ret; - hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL); - if (!hdmi) + vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); + if (!vc4_hdmi) return -ENOMEM; - encoder = &hdmi->encoder.base.base; - hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; - hdmi->pdev = pdev; + encoder = &vc4_hdmi->encoder.base.base; + vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; + vc4_hdmi->pdev = pdev; - hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); - if (IS_ERR(hdmi->hdmicore_regs)) - return PTR_ERR(hdmi->hdmicore_regs); + vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); + if (IS_ERR(vc4_hdmi->hdmicore_regs)) + return PTR_ERR(vc4_hdmi->hdmicore_regs); - hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); - if (IS_ERR(hdmi->hd_regs)) - return PTR_ERR(hdmi->hd_regs); + vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1); + if (IS_ERR(vc4_hdmi->hd_regs)) + return PTR_ERR(vc4_hdmi->hd_regs); - hdmi->hdmi_regset.base = hdmi->hdmicore_regs; - hdmi->hdmi_regset.regs = hdmi_regs; - hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); - hdmi->hd_regset.base = hdmi->hd_regs; - hdmi->hd_regset.regs = hd_regs; - hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); + vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs; + vc4_hdmi->hdmi_regset.regs = hdmi_regs; + vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); + vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs; + vc4_hdmi->hd_regset.regs = hd_regs; + vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); - hdmi->pixel_clock = devm_clk_get(dev, "pixel"); - if (IS_ERR(hdmi->pixel_clock)) { - ret = PTR_ERR(hdmi->pixel_clock); + vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); + if (IS_ERR(vc4_hdmi->pixel_clock)) { + ret = PTR_ERR(vc4_hdmi->pixel_clock); if (ret != -EPROBE_DEFER) DRM_ERROR("Failed to get pixel clock\n"); return ret; } - hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); - if (IS_ERR(hdmi->hsm_clock)) { + vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); + if (IS_ERR(vc4_hdmi->hsm_clock)) { DRM_ERROR("Failed to get HDMI state machine clock\n"); - return PTR_ERR(hdmi->hsm_clock); + return PTR_ERR(vc4_hdmi->hsm_clock); } ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); @@ -1265,9 +1266,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return -ENODEV; } - hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); + vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node); of_node_put(ddc_node); - if (!hdmi->ddc) { + if (!vc4_hdmi->ddc) { DRM_DEBUG("Failed to get ddc i2c adapter by node\n"); return -EPROBE_DEFER; } @@ -1276,13 +1277,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) * needs to be a bit higher than the pixel clock rate * (generally 148.5Mhz). */ - ret = clk_set_rate(hdmi->hsm_clock, HSM_CLOCK_FREQ); + ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); goto err_put_i2c; } - ret = clk_prepare_enable(hdmi->hsm_clock); + ret = clk_prepare_enable(vc4_hdmi->hsm_clock); if (ret) { DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n", ret); @@ -1295,18 +1296,18 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (of_find_property(dev->of_node, "hpd-gpios", &value)) { enum of_gpio_flags hpd_gpio_flags; - hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node, - "hpd-gpios", 0, - &hpd_gpio_flags); - if (hdmi->hpd_gpio < 0) { - ret = hdmi->hpd_gpio; + vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node, + "hpd-gpios", 0, + &hpd_gpio_flags); + if (vc4_hdmi->hpd_gpio < 0) { + ret = vc4_hdmi->hpd_gpio; goto err_unprepare_hsm; } - hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; + vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - vc4->hdmi = hdmi; + vc4->hdmi = vc4_hdmi; /* HDMI core must be enabled. */ if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) { @@ -1321,21 +1322,21 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs); - ret = vc4_hdmi_connector_init(drm, hdmi); + ret = vc4_hdmi_connector_init(drm, vc4_hdmi); if (ret) goto err_destroy_encoder; #ifdef CONFIG_DRM_VC4_HDMI_CEC - hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, - vc4, "vc4", - CEC_CAP_DEFAULTS | - CEC_CAP_CONNECTOR_INFO, 1); - ret = PTR_ERR_OR_ZERO(hdmi->cec_adap); + vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, + vc4, "vc4", + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, 1); + ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); if (ret < 0) goto err_destroy_conn; - cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base); - cec_s_conn_info(hdmi->cec_adap, &conn_info); + cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base); + cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff); value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1); @@ -1354,32 +1355,32 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) "vc4 hdmi cec", vc4); if (ret) goto err_delete_cec_adap; - ret = cec_register_adapter(hdmi->cec_adap, dev); + ret = cec_register_adapter(vc4_hdmi->cec_adap, dev); if (ret < 0) goto err_delete_cec_adap; #endif - ret = vc4_hdmi_audio_init(hdmi); + ret = vc4_hdmi_audio_init(vc4_hdmi); if (ret) goto err_destroy_encoder; - vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, hdmi); + vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi); return 0; #ifdef CONFIG_DRM_VC4_HDMI_CEC err_delete_cec_adap: - cec_delete_adapter(hdmi->cec_adap); + cec_delete_adapter(vc4_hdmi->cec_adap); err_destroy_conn: - vc4_hdmi_connector_destroy(&hdmi->connector.base); + vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base); #endif err_destroy_encoder: drm_encoder_cleanup(encoder); err_unprepare_hsm: - clk_disable_unprepare(hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->hsm_clock); pm_runtime_disable(dev); err_put_i2c: - put_device(&hdmi->ddc->dev); + put_device(&vc4_hdmi->ddc->dev); return ret; } @@ -1389,16 +1390,16 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, { struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hdmi *hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; - cec_unregister_adapter(hdmi->cec_adap); - vc4_hdmi_connector_destroy(&hdmi->connector.base); - drm_encoder_cleanup(&hdmi->encoder.base.base); + cec_unregister_adapter(vc4_hdmi->cec_adap); + vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base); + drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); - clk_disable_unprepare(hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->hsm_clock); pm_runtime_disable(dev); - put_device(&hdmi->ddc->dev); + put_device(&vc4_hdmi->ddc->dev); vc4->hdmi = NULL; } -- GitLab From 13311457bebf5c1e66f2f7a53a4d30b0dddf158a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:15 +0200 Subject: [PATCH 0892/1494] drm/vc4: hdmi: Move accessors to vc4_hdmi The current driver only supports a single HDMI controller, and part of the issue is that the main vc4_dev structure holds a pointer to its (only) HDMI controller, and the HDMI registers accessors will use it to retrieve the mapped addresses. Let's modify those accessors to use directly the vc4_hdmi structure so that we can eventually get rid of that single global pointer. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/886b955586264ce078d7d35e9b8ef9ae51675c27.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++++-------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 8 ++++---- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 6733e4bc235b8..81c0f67cd0eb7 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -123,6 +123,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; if (vc4->hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ @@ -230,6 +231,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, { struct drm_device *dev = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; u32 packet_id = type - 0x80; HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, @@ -244,6 +246,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, { struct drm_device *dev = encoder->dev; struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; u32 packet_id = frame->any.type - 0x80; u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id); uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; @@ -623,9 +626,6 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { /* HDMI audio codec callbacks */ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) { - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_device *drm = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock); unsigned long n, m; @@ -645,8 +645,6 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) { struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_crtc *crtc = encoder->crtc; - struct drm_device *drm = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); const struct drm_display_mode *mode = &crtc->state->adjusted_mode; u32 samplerate = vc4_hdmi->audio.samplerate; u32 n, cts; @@ -683,7 +681,6 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; struct drm_connector *connector = &vc4_hdmi->connector.base; - struct vc4_dev *vc4 = to_vc4_dev(encoder->dev); int ret; if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream) @@ -714,9 +711,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) { struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_device *drm = encoder->dev; struct device *dev = &vc4_hdmi->pdev->dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); int ret; ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO); @@ -747,10 +742,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); - struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_device *drm = encoder->dev; struct device *dev = &vc4_hdmi->pdev->dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); u32 audio_packet_config, channel_mask; u32 channel_map, i; @@ -821,8 +813,6 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, { struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_device *drm = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(drm); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -1082,7 +1072,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1) { - struct cec_msg *msg = &vc4->hdmi->cec_rx_msg; + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; unsigned int i; msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> @@ -1128,6 +1119,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) { struct vc4_dev *vc4 = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); @@ -1171,6 +1163,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { struct vc4_dev *vc4 = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | @@ -1182,6 +1175,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { struct vc4_dev *vc4 = cec_get_drvdata(adap); + struct vc4_hdmi *vc4_hdmi = vc4->hdmi; u32 val; unsigned int i; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 17079a39f1b10..cdc9d90f62ac5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -78,9 +78,9 @@ struct vc4_hdmi { struct debugfs_regset32 hd_regset; }; -#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset) -#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset) -#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset) -#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset) +#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset) +#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset) +#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset) +#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset) #endif /* _VC4_HDMI_H_ */ -- GitLab From b10db9a4242bd5c89f0029e92ff13f2d7e9c53c8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:16 +0200 Subject: [PATCH 0893/1494] drm/vc4: hdmi: Use local vc4_hdmi directly The function vc4_hdmi_connector_detect access its vc4_hdmi struct by dereferencing the pointer in the structure vc4_dev. This will cause some issues when we will have multiple HDMI controllers, so let's just use the local variable for now instead of dereferencing that pointer all the time, and we'll fix the local variable later. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/ef92c5582d3b2894128b2272a8ada7cbc20be3d9.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 81c0f67cd0eb7..93865327a8d44 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -125,20 +125,20 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_hdmi *vc4_hdmi = vc4->hdmi; - if (vc4->hdmi->hpd_gpio) { - if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ - vc4->hdmi->hpd_active_low) + if (vc4_hdmi->hpd_gpio) { + if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ + vc4_hdmi->hpd_active_low) return connector_status_connected; - cec_phys_addr_invalidate(vc4->hdmi->cec_adap); + cec_phys_addr_invalidate(vc4_hdmi->cec_adap); return connector_status_disconnected; } - if (drm_probe_ddc(vc4->hdmi->ddc)) + if (drm_probe_ddc(vc4_hdmi->ddc)) return connector_status_connected; if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) return connector_status_connected; - cec_phys_addr_invalidate(vc4->hdmi->cec_adap); + cec_phys_addr_invalidate(vc4_hdmi->cec_adap); return connector_status_disconnected; } -- GitLab From 5dfbcae63f1098eae39d833f42b7879be5fd4ce2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:17 +0200 Subject: [PATCH 0894/1494] drm/vc4: hdmi: Add container_of macros for encoders and connectors Whenever the code needs to access the vc4_hdmi structure from a DRM connector or encoder, it first accesses the drm_device associated to the connector, then retrieve the drm_dev private data which gives it a pointer to our vc4_dev, and will finally follow the vc4_hdmi pointer in that structure. That will also give us some trouble when having multiple controllers, but now that we have our encoder and connector structures that are part of vc4_hdmi, we can simply call container_of on the DRM connector or encoder and retrieve the vc4_hdmi structure directly. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/536ecce5898ea75839fa3788b876009d69a5ccae.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 41 ++++++++++------------------------ drivers/gpu/drm/vc4/vc4_hdmi.h | 16 +++++++++++++ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 93865327a8d44..a2053da4e4436 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -121,9 +121,7 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { - struct drm_device *dev = connector->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); if (vc4_hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ @@ -150,17 +148,13 @@ static void vc4_hdmi_connector_destroy(struct drm_connector *connector) static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) { - struct vc4_hdmi_connector *vc4_connector = - to_vc4_hdmi_connector(connector); - struct drm_encoder *encoder = vc4_connector->encoder; - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_device *dev = connector->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); + struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); + struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; int ret = 0; struct edid *edid; - edid = drm_get_edid(connector, vc4->hdmi->ddc); - cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid); + edid = drm_get_edid(connector, vc4_hdmi->ddc); + cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid); if (!edid) return -ENODEV; @@ -229,9 +223,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, enum hdmi_infoframe_type type) { - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); u32 packet_id = type - 0x80; HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, @@ -244,9 +236,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, union hdmi_infoframe *frame) { - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); u32 packet_id = frame->any.type - 0x80; u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id); uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; @@ -292,9 +282,8 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct vc4_dev *vc4 = encoder->dev->dev_private; - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; struct drm_connector *connector = &vc4_hdmi->connector.base; struct drm_connector_state *cstate = connector->state; struct drm_crtc *crtc = encoder->crtc; @@ -338,9 +327,7 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) { - struct drm_device *drm = encoder->dev; - struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); union hdmi_infoframe frame; int ret; @@ -362,9 +349,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) { - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); int ret; HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); @@ -383,10 +368,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; bool debug_dump_regs = false; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index cdc9d90f62ac5..749a807cd1f3d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -78,6 +78,22 @@ struct vc4_hdmi { struct debugfs_regset32 hd_regset; }; +static inline struct vc4_hdmi * +connector_to_vc4_hdmi(struct drm_connector *connector) +{ + struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector); + + return container_of(_connector, struct vc4_hdmi, connector); +} + +static inline struct vc4_hdmi * +encoder_to_vc4_hdmi(struct drm_encoder *encoder) +{ + struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder); + + return container_of(_encoder, struct vc4_hdmi, encoder); +} + #define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset) #define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset) #define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset) -- GitLab From 66bf1c30e0e5bcc9d6965157a8581f36577c45a4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:18 +0200 Subject: [PATCH 0895/1494] drm/vc4: hdmi: Pass vc4_hdmi to CEC code Our CEC code also retrieves the associated vc4_hdmi by setting the vc4_dev pointer as its private data, and then dereferences its vc4_hdmi pointer. In order to eventually get rid of that pointer, we can simply pass the vc4_hdmi pointer directly. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/cb575cb9e13018bce131b8535e5b572dc1027877.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a2053da4e4436..44126ae55a194 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1032,8 +1032,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) #ifdef CONFIG_DRM_VC4_HDMI_CEC static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) { - struct vc4_dev *vc4 = priv; - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = priv; if (vc4_hdmi->cec_irq_was_rx) { if (vc4_hdmi->cec_rx_msg.len) @@ -1053,9 +1052,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) return IRQ_HANDLED; } -static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1) +static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) { - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; unsigned int i; @@ -1073,8 +1071,7 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1) static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) { - struct vc4_dev *vc4 = priv; - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = priv; u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS); u32 cntrl1, cntrl5; @@ -1085,7 +1082,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; if (vc4_hdmi->cec_irq_was_rx) { - vc4_cec_read_msg(vc4, cntrl1); + vc4_cec_read_msg(vc4_hdmi, cntrl1); cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1); cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; @@ -1101,8 +1098,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) { - struct vc4_dev *vc4 = cec_get_drvdata(adap); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); @@ -1145,8 +1141,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { - struct vc4_dev *vc4 = cec_get_drvdata(adap); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | @@ -1157,8 +1152,7 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { - struct vc4_dev *vc4 = cec_get_drvdata(adap); - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); u32 val; unsigned int i; @@ -1305,7 +1299,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) #ifdef CONFIG_DRM_VC4_HDMI_CEC vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, - vc4, "vc4", + vc4_hdmi, "vc4", CEC_CAP_DEFAULTS | CEC_CAP_CONNECTOR_INFO, 1); ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); @@ -1329,7 +1323,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), vc4_cec_irq_handler, vc4_cec_irq_handler_thread, 0, - "vc4 hdmi cec", vc4); + "vc4 hdmi cec", vc4_hdmi); if (ret) goto err_delete_cec_adap; ret = cec_register_adapter(vc4_hdmi->cec_adap, dev); -- GitLab From 47c167b757638e747717ab7e5d7e8803c446d943 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:19 +0200 Subject: [PATCH 0896/1494] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device The unbind function needs to retrieve a vc4_hdmi structure pointer through the struct device that we're given since we want to support multiple HDMI controllers. However, our optional ASoC support doesn't make that trivial since it will overwrite the device drvdata if we use it, but obviously won't if we don't use it. Let's make sure the fields are at the proper offset to be able to cast between the snd_soc_card structure and the vc4_hdmi structure transparently so we can support both cases. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/717082cba06b5c06280f26c56c08aee512365ed3.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++- drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 44126ae55a194..e0dc823c622a3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1199,6 +1199,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (!vc4_hdmi) return -ENOMEM; + dev_set_drvdata(dev, vc4_hdmi); encoder = &vc4_hdmi->encoder.base.base; vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; vc4_hdmi->pdev = pdev; @@ -1361,7 +1362,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, { struct drm_device *drm = dev_get_drvdata(master); struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hdmi *vc4_hdmi = vc4->hdmi; + struct vc4_hdmi *vc4_hdmi; + + /* + * ASoC makes it a bit hard to retrieve a pointer to the + * vc4_hdmi structure. Registering the card will overwrite our + * device drvdata with a pointer to the snd_soc_card structure, + * which can then be used to retrieve whatever drvdata we want + * to associate. + * + * However, that doesn't fly in the case where we wouldn't + * register an ASoC card (because of an old DT that is missing + * the dmas properties for example), then the card isn't + * registered and the device drvdata wouldn't be set. + * + * We can deal with both cases by making sure a snd_soc_card + * pointer and a vc4_hdmi structure are pointing to the same + * memory address, so we can treat them indistinctly without any + * issue. + */ + BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0); + BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); + vc4_hdmi = dev_get_drvdata(dev); cec_unregister_adapter(vc4_hdmi->cec_adap); vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 749a807cd1f3d..d434627894509 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -53,13 +53,13 @@ struct vc4_hdmi_audio { /* General HDMI hardware state. */ struct vc4_hdmi { + struct vc4_hdmi_audio audio; + struct platform_device *pdev; struct vc4_hdmi_encoder encoder; struct vc4_hdmi_connector connector; - struct vc4_hdmi_audio audio; - struct i2c_adapter *ddc; void __iomem *hdmicore_regs; void __iomem *hd_regs; -- GitLab From 283d347d6e3e25829663cc629e80eccea96c25de Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:20 +0200 Subject: [PATCH 0897/1494] drm/vc4: hdmi: Remove vc4_dev hdmi pointer Now that we don't have any users anymore, we can kill that pointer. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/d7ebf50319bbd902e4b7b7c39ae1612c3b38e6b2.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.h | 1 - drivers/gpu/drm/vc4/vc4_hdmi.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 1a97545b92440..501a48a714d3d 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -73,7 +73,6 @@ struct vc4_perfmon { struct vc4_dev { struct drm_device *dev; - struct vc4_hdmi *hdmi; struct vc4_hvs *hvs; struct vc4_v3d *v3d; struct vc4_dpi *dpi; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e0dc823c622a3..912560d584484 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1188,7 +1188,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) #endif struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = drm->dev_private; struct vc4_hdmi *vc4_hdmi; struct drm_encoder *encoder; struct device_node *ddc_node; @@ -1279,8 +1278,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - vc4->hdmi = vc4_hdmi; - /* HDMI core must be enabled. */ if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) { HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST); @@ -1360,8 +1357,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) static void vc4_hdmi_unbind(struct device *dev, struct device *master, void *data) { - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = drm->dev_private; struct vc4_hdmi *vc4_hdmi; /* @@ -1393,8 +1388,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, pm_runtime_disable(dev); put_device(&vc4_hdmi->ddc->dev); - - vc4->hdmi = NULL; } static const struct component_ops vc4_hdmi_ops = { -- GitLab From 0532e5e5e03996aa1eaa8e5a0bc5b93a6c3f1648 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:21 +0200 Subject: [PATCH 0898/1494] drm/vc4: hdmi: Remove vc4_hdmi_connector The vc4_hdmi_connector was only used to switch between drm_connector to drm_encoder. However, we can now use vc4_hdmi to do the switch, so that structure is redundant. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/aee5120728db350b19c074de4290eafaf01e6671.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 19 ++++++++----------- drivers/gpu/drm/vc4/vc4_hdmi.h | 23 ++--------------------- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 912560d584484..5c5684f91b69e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -189,13 +189,10 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs = static int vc4_hdmi_connector_init(struct drm_device *dev, struct vc4_hdmi *vc4_hdmi) { - struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector; - struct drm_connector *connector = &hdmi_connector->base; + struct drm_connector *connector = &vc4_hdmi->connector; struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; int ret; - hdmi_connector->encoder = encoder; - drm_connector_init_with_ddc(dev, connector, &vc4_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA, @@ -284,7 +281,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_connector *connector = &vc4_hdmi->connector; struct drm_connector_state *cstate = connector->state; struct drm_crtc *crtc = encoder->crtc; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; @@ -663,7 +660,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, { struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base; - struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_connector *connector = &vc4_hdmi->connector; int ret; if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream) @@ -837,7 +834,7 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component); - struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_connector *connector = &vc4_hdmi->connector; uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; uinfo->count = sizeof(connector->eld); @@ -850,7 +847,7 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol, { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component); - struct drm_connector *connector = &vc4_hdmi->connector.base; + struct drm_connector *connector = &vc4_hdmi->connector; memcpy(ucontrol->value.bytes.data, connector->eld, sizeof(connector->eld)); @@ -1304,7 +1301,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret < 0) goto err_destroy_conn; - cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base); + cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff); @@ -1341,7 +1338,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) err_delete_cec_adap: cec_delete_adapter(vc4_hdmi->cec_adap); err_destroy_conn: - vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base); + vc4_hdmi_connector_destroy(&vc4_hdmi->connector); #endif err_destroy_encoder: drm_encoder_cleanup(encoder); @@ -1381,7 +1378,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi = dev_get_drvdata(dev); cec_unregister_adapter(vc4_hdmi->cec_adap); - vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base); + vc4_hdmi_connector_destroy(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); clk_disable_unprepare(vc4_hdmi->hsm_clock); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index d434627894509..674541493909e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -21,23 +21,6 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_hdmi_encoder, base.base); } -/* VC4 HDMI connector KMS struct */ -struct vc4_hdmi_connector { - struct drm_connector base; - - /* Since the connector is attached to just the one encoder, - * this is the reference to it so we can do the best_encoder() - * hook. - */ - struct drm_encoder *encoder; -}; - -static inline struct vc4_hdmi_connector * -to_vc4_hdmi_connector(struct drm_connector *connector) -{ - return container_of(connector, struct vc4_hdmi_connector, base); -} - /* HDMI audio information */ struct vc4_hdmi_audio { struct snd_soc_card card; @@ -58,7 +41,7 @@ struct vc4_hdmi { struct platform_device *pdev; struct vc4_hdmi_encoder encoder; - struct vc4_hdmi_connector connector; + struct drm_connector connector; struct i2c_adapter *ddc; void __iomem *hdmicore_regs; @@ -81,9 +64,7 @@ struct vc4_hdmi { static inline struct vc4_hdmi * connector_to_vc4_hdmi(struct drm_connector *connector) { - struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector); - - return container_of(_connector, struct vc4_hdmi, connector); + return container_of(connector, struct vc4_hdmi, connector); } static inline struct vc4_hdmi * -- GitLab From 33c773eb62eaa1b4be3598eb91e7cd01b4ab4053 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:22 +0200 Subject: [PATCH 0899/1494] drm/vc4: hdmi: Introduce resource init and variant The HDMI controllers found in the BCM2711 has a pretty different clock and registers areas than found in the older BCM283x SoCs. Let's create a variant structure to store the various adjustments we'll need later on, and a function to get the resources needed for one particular version. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/71cfa3ce3d865bbab52a0e5651bc052dc4893f11.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++----------- drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++ 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 5c5684f91b69e..c40050b908b5a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1178,28 +1178,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { }; #endif -static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) { -#ifdef CONFIG_DRM_VC4_HDMI_CEC - struct cec_connector_info conn_info; -#endif - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_hdmi *vc4_hdmi; - struct drm_encoder *encoder; - struct device_node *ddc_node; - u32 value; + struct platform_device *pdev = vc4_hdmi->pdev; + struct device *dev = &pdev->dev; int ret; - vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); - if (!vc4_hdmi) - return -ENOMEM; - - dev_set_drvdata(dev, vc4_hdmi); - encoder = &vc4_hdmi->encoder.base.base; - vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; - vc4_hdmi->pdev = pdev; - vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0); if (IS_ERR(vc4_hdmi->hdmicore_regs)) return PTR_ERR(vc4_hdmi->hdmicore_regs); @@ -1211,6 +1195,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs; vc4_hdmi->hdmi_regset.regs = hdmi_regs; vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); + vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs; vc4_hdmi->hd_regset.regs = hd_regs; vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); @@ -1222,12 +1207,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) DRM_ERROR("Failed to get pixel clock\n"); return ret; } + vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); if (IS_ERR(vc4_hdmi->hsm_clock)) { DRM_ERROR("Failed to get HDMI state machine clock\n"); return PTR_ERR(vc4_hdmi->hsm_clock); } + return 0; +} + +static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) +{ +#ifdef CONFIG_DRM_VC4_HDMI_CEC + struct cec_connector_info conn_info; +#endif + const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); + struct vc4_hdmi *vc4_hdmi; + struct drm_encoder *encoder; + struct device_node *ddc_node; + u32 value; + int ret; + + vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL); + if (!vc4_hdmi) + return -ENOMEM; + + dev_set_drvdata(dev, vc4_hdmi); + encoder = &vc4_hdmi->encoder.base.base; + vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; + vc4_hdmi->pdev = pdev; + vc4_hdmi->variant = variant; + + ret = variant->init_resources(vc4_hdmi); + if (ret) + return ret; + ddc_node = of_parse_phandle(dev->of_node, "ddc", 0); if (!ddc_node) { DRM_ERROR("Failed to find ddc node in device tree\n"); @@ -1403,8 +1420,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) return 0; } +static const struct vc4_hdmi_variant bcm2835_variant = { + .init_resources = vc4_hdmi_init_resources, +}; + static const struct of_device_id vc4_hdmi_dt_match[] = { - { .compatible = "brcm,bcm2835-hdmi" }, + { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, {} }; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 674541493909e..0eaf979fe8112 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_hdmi_encoder, base.base); } +struct vc4_hdmi; + +struct vc4_hdmi_variant { + /* Callback to get the resources (memory region, interrupts, + * clocks, etc) for that variant. + */ + int (*init_resources)(struct vc4_hdmi *vc4_hdmi); +}; + /* HDMI audio information */ struct vc4_hdmi_audio { struct snd_soc_card card; @@ -39,6 +48,7 @@ struct vc4_hdmi { struct vc4_hdmi_audio audio; struct platform_device *pdev; + const struct vc4_hdmi_variant *variant; struct vc4_hdmi_encoder encoder; struct drm_connector connector; -- GitLab From 311e305fdb4e82c190cc44566dc01cc9fd9cb75c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:23 +0200 Subject: [PATCH 0900/1494] drm/vc4: hdmi: Implement a register layout abstraction The HDMI controllers found in the BCM2711 have most of the registers reorganized in multiple registers areas and at different offsets than previously found. The logic however remains pretty much the same, so it doesn't really make sense to create a whole new driver and we should share the code as much as possible. Let's implement some indirection to wrap around a register and depending on the variant will lookup the associated register on that particular variant. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/3070236daff920e7edd11c5a72ac31fd0f6a656b.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 427 ++++++++++++++-------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 12 +- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 92 ------ 4 files changed, 464 insertions(+), 308 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c40050b908b5a..adc7c06936507 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -50,62 +50,13 @@ #include "media/cec.h" #include "vc4_drv.h" #include "vc4_hdmi.h" +#include "vc4_hdmi_regs.h" #include "vc4_regs.h" #define HSM_CLOCK_FREQ 163682864 #define CEC_CLOCK_FREQ 40000 #define CEC_CLOCK_DIV (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ) -static const struct debugfs_reg32 hdmi_regs[] = { - VC4_REG32(VC4_HDMI_CORE_REV), - VC4_REG32(VC4_HDMI_SW_RESET_CONTROL), - VC4_REG32(VC4_HDMI_HOTPLUG_INT), - VC4_REG32(VC4_HDMI_HOTPLUG), - VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP), - VC4_REG32(VC4_HDMI_MAI_CONFIG), - VC4_REG32(VC4_HDMI_MAI_FORMAT), - VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG), - VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG), - VC4_REG32(VC4_HDMI_HORZA), - VC4_REG32(VC4_HDMI_HORZB), - VC4_REG32(VC4_HDMI_FIFO_CTL), - VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL), - VC4_REG32(VC4_HDMI_VERTA0), - VC4_REG32(VC4_HDMI_VERTA1), - VC4_REG32(VC4_HDMI_VERTB0), - VC4_REG32(VC4_HDMI_VERTB1), - VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL), - VC4_REG32(VC4_HDMI_TX_PHY_CTL0), - - VC4_REG32(VC4_HDMI_CEC_CNTRL_1), - VC4_REG32(VC4_HDMI_CEC_CNTRL_2), - VC4_REG32(VC4_HDMI_CEC_CNTRL_3), - VC4_REG32(VC4_HDMI_CEC_CNTRL_4), - VC4_REG32(VC4_HDMI_CEC_CNTRL_5), - VC4_REG32(VC4_HDMI_CPU_STATUS), - VC4_REG32(VC4_HDMI_CPU_MASK_STATUS), - - VC4_REG32(VC4_HDMI_CEC_RX_DATA_1), - VC4_REG32(VC4_HDMI_CEC_RX_DATA_2), - VC4_REG32(VC4_HDMI_CEC_RX_DATA_3), - VC4_REG32(VC4_HDMI_CEC_RX_DATA_4), - VC4_REG32(VC4_HDMI_CEC_TX_DATA_1), - VC4_REG32(VC4_HDMI_CEC_TX_DATA_2), - VC4_REG32(VC4_HDMI_CEC_TX_DATA_3), - VC4_REG32(VC4_HDMI_CEC_TX_DATA_4), -}; - -static const struct debugfs_reg32 hd_regs[] = { - VC4_REG32(VC4_HD_M_CTL), - VC4_REG32(VC4_HD_MAI_CTL), - VC4_REG32(VC4_HD_MAI_THR), - VC4_REG32(VC4_HD_MAI_FMT), - VC4_REG32(VC4_HD_MAI_SMP), - VC4_REG32(VC4_HD_VID_CTL), - VC4_REG32(VC4_HD_CSC_CTL), - VC4_REG32(VC4_HD_FRAME_COUNT), -}; - static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *)m->private; @@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) if (drm_probe_ddc(vc4_hdmi->ddc)) return connector_status_connected; - if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) + if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) return connector_status_connected; cec_phys_addr_invalidate(vc4_hdmi->cec_adap); return connector_status_disconnected; @@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); u32 packet_id = type - 0x80; - HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, - HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, + HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); - return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & + return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) & BIT(packet_id)), 100); } @@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); u32 packet_id = frame->any.type - 0x80; - u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id); + const struct vc4_hdmi_register *ram_packet_start = + &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START]; + u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id; + void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi, + ram_packet_start->reg); uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; ssize_t len, i; int ret; - WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & + WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE), "Packet RAM has to be on to store the packet."); @@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, } for (i = 0; i < len; i += 7) { - HDMI_WRITE(packet_reg, - buffer[i + 0] << 0 | - buffer[i + 1] << 8 | - buffer[i + 2] << 16); + writel(buffer[i + 0] << 0 | + buffer[i + 1] << 8 | + buffer[i + 2] << 16, + base + packet_reg); packet_reg += 4; - HDMI_WRITE(packet_reg, - buffer[i + 3] << 0 | - buffer[i + 4] << 8 | - buffer[i + 5] << 16 | - buffer[i + 6] << 24); + writel(buffer[i + 3] << 0 | + buffer[i + 4] << 8 | + buffer[i + 5] << 16 | + buffer[i + 6] << 24, + base + packet_reg); packet_reg += 4; } - HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, - HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); - ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, + HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); + ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) & BIT(packet_id)), 100); if (ret) DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); @@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); int ret; - HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); - HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); - HD_WRITE(VC4_HD_VID_CTL, - HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); clk_disable_unprepare(vc4_hdmi->pixel_clock); @@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, + HDMI_WRITE(HDMI_SW_RESET_CONTROL, VC4_HDMI_SW_RESET_HDMI | VC4_HDMI_SW_RESET_FORMAT_DETECT); - HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0); + HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); /* PHY should be in reset, like * vc4_hdmi_encoder_disable() does. */ - HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); - HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); if (debug_dump_regs) { struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); @@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) drm_print_regset32(&p, &vc4_hdmi->hd_regset); } - HD_WRITE(VC4_HD_VID_CTL, 0); + HDMI_WRITE(HDMI_VID_CTL, 0); - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | + HDMI_WRITE(HDMI_SCHEDULER_CONTROL, + HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS); - HDMI_WRITE(VC4_HDMI_HORZA, + HDMI_WRITE(HDMI_HORZA, (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | VC4_SET_FIELD(mode->hdisplay * pixel_rep, VC4_HDMI_HORZA_HAP)); - HDMI_WRITE(VC4_HDMI_HORZB, + HDMI_WRITE(HDMI_HORZB, VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep, VC4_HDMI_HORZB_HBP) | @@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) mode->hdisplay) * pixel_rep, VC4_HDMI_HORZB_HFP)); - HDMI_WRITE(VC4_HDMI_VERTA0, verta); - HDMI_WRITE(VC4_HDMI_VERTA1, verta); + HDMI_WRITE(HDMI_VERTA0, verta); + HDMI_WRITE(HDMI_VERTA1, verta); - HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even); - HDMI_WRITE(VC4_HDMI_VERTB1, vertb); + HDMI_WRITE(HDMI_VERTB0, vertb_even); + HDMI_WRITE(HDMI_VERTB1, vertb); - HD_WRITE(VC4_HD_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + HDMI_WRITE(HDMI_VID_CTL, + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, VC4_HD_CSC_CTL_ORDER); @@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, VC4_HD_CSC_CTL_MODE); - HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000); - HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0); - HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000); - HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); - HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); - HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0); + HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0); + HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000); vc4_encoder->limited_rgb_range = true; } else { vc4_encoder->limited_rgb_range = false; } /* The RGB order applies even when CSC is disabled. */ - HD_WRITE(VC4_HD_CSC_CTL, csc_ctl); + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); - HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); + HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); if (debug_dump_regs) { struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); @@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) drm_print_regset32(&p, &vc4_hdmi->hd_regset); } - HD_WRITE(VC4_HD_VID_CTL, - HD_READ(VC4_HD_VID_CTL) | - VC4_HD_VID_CTL_ENABLE | - VC4_HD_VID_CTL_UNDERFLOW_ENABLE | - VC4_HD_VID_CTL_FRAME_COUNTER_RESET); + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_ENABLE | + VC4_HD_VID_CTL_UNDERFLOW_ENABLE | + VC4_HD_VID_CTL_FRAME_COUNTER_RESET); if (vc4_encoder->hdmi_monitor) { - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | + HDMI_WRITE(HDMI_SCHEDULER_CONTROL, + HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & + ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); WARN_ONCE(ret, "Timeout waiting for " "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); } else { - HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, - HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, + HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~(VC4_HDMI_RAM_PACKET_ENABLE)); - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & + HDMI_WRITE(HDMI_SCHEDULER_CONTROL, + HDMI_READ(HDMI_SCHEDULER_CONTROL) & ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); - ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & + ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); WARN_ONCE(ret, "Timeout waiting for " "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); @@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_encoder->hdmi_monitor) { u32 drift; - WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & + WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); - HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, - HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | + HDMI_WRITE(HDMI_SCHEDULER_CONTROL, + HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT); - HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, + HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, VC4_HDMI_RAM_PACKET_ENABLE); vc4_hdmi_set_infoframes(encoder); - drift = HDMI_READ(VC4_HDMI_FIFO_CTL); + drift = HDMI_READ(HDMI_FIFO_CTL); drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - HDMI_WRITE(VC4_HDMI_FIFO_CTL, + HDMI_WRITE(HDMI_FIFO_CTL, drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(VC4_HDMI_FIFO_CTL, + HDMI_WRITE(HDMI_FIFO_CTL, drift | VC4_HDMI_FIFO_CTL_RECENTER); usleep_range(1000, 1100); - HDMI_WRITE(VC4_HDMI_FIFO_CTL, + HDMI_WRITE(HDMI_FIFO_CTL, drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(VC4_HDMI_FIFO_CTL, + HDMI_WRITE(HDMI_FIFO_CTL, drift | VC4_HDMI_FIFO_CTL_RECENTER); - ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) & + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); WARN_ONCE(ret, "Timeout waiting for " "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); @@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) VC4_HD_MAI_SMP_M_SHIFT) + 1, &n, &m); - HD_WRITE(VC4_HD_MAI_SMP, - VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) | - VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); + HDMI_WRITE(HDMI_MAI_SMP, + VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) | + VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M)); } static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) @@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) do_div(tmp, 128 * samplerate); cts = tmp; - HDMI_WRITE(VC4_HDMI_CRP_CFG, + HDMI_WRITE(HDMI_CRP_CFG, VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN | VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N)); @@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi) * providing a CTS_1 value. The two CTS values are alternated * between based on the period fields */ - HDMI_WRITE(VC4_HDMI_CTS_0, cts); - HDMI_WRITE(VC4_HDMI_CTS_1, cts); + HDMI_WRITE(HDMI_CTS_0, cts); + HDMI_WRITE(HDMI_CTS_1, cts); } static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai) @@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream, * If the HDMI encoder hasn't probed, or the encoder is * currently in DVI mode, treat the codec dai as missing. */ - if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & + if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) & VC4_HDMI_RAM_PACKET_ENABLE)) return -ENODEV; @@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) if (ret) dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); - HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET); - HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF); - HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH); + HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET); + HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF); + HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH); } static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream, @@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, vc4_hdmi->audio.channels = params_channels(params); vc4_hdmi->audio.samplerate = params_rate(params); - HD_WRITE(VC4_HD_MAI_CTL, - VC4_HD_MAI_CTL_RESET | - VC4_HD_MAI_CTL_FLUSH | - VC4_HD_MAI_CTL_DLATE | - VC4_HD_MAI_CTL_ERRORE | - VC4_HD_MAI_CTL_ERRORF); + HDMI_WRITE(HDMI_MAI_CTL, + VC4_HD_MAI_CTL_RESET | + VC4_HD_MAI_CTL_FLUSH | + VC4_HD_MAI_CTL_DLATE | + VC4_HD_MAI_CTL_ERRORE | + VC4_HD_MAI_CTL_ERRORF); vc4_hdmi_audio_set_mai_clock(vc4_hdmi); @@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, /* Set the MAI threshold. This logic mimics the firmware's. */ if (vc4_hdmi->audio.samplerate > 96000) { - HD_WRITE(VC4_HD_MAI_THR, - VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) | - VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) | + VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); } else if (vc4_hdmi->audio.samplerate > 48000) { - HD_WRITE(VC4_HD_MAI_THR, - VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) | - VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) | + VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW)); } else { - HD_WRITE(VC4_HD_MAI_THR, - VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | - VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | - VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) | - VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW)); + HDMI_WRITE(HDMI_MAI_THR, + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) | + VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW)); } - HDMI_WRITE(VC4_HDMI_MAI_CONFIG, + HDMI_WRITE(HDMI_MAI_CONFIG, VC4_HDMI_MAI_CONFIG_BIT_REVERSE | VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK)); @@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, channel_map |= i << (3 * i); } - HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map); - HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); + HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map); + HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); vc4_hdmi_set_n_cts(vc4_hdmi); return 0; @@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: vc4_hdmi_set_audio_infoframe(encoder); - HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0, - HDMI_READ(VC4_HDMI_TX_PHY_CTL0) & + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) & ~VC4_HDMI_TX_PHY_RNG_PWRDN); - HD_WRITE(VC4_HD_MAI_CTL, - VC4_SET_FIELD(vc4_hdmi->audio.channels, - VC4_HD_MAI_CTL_CHNUM) | - VC4_HD_MAI_CTL_ENABLE); + + HDMI_WRITE(HDMI_MAI_CTL, + VC4_SET_FIELD(vc4_hdmi->audio.channels, + VC4_HD_MAI_CTL_CHNUM) | + VC4_HD_MAI_CTL_ENABLE); break; case SNDRV_PCM_TRIGGER_STOP: - HD_WRITE(VC4_HD_MAI_CTL, - VC4_HD_MAI_CTL_DLATE | - VC4_HD_MAI_CTL_ERRORE | - VC4_HD_MAI_CTL_ERRORF); - HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0, - HDMI_READ(VC4_HDMI_TX_PHY_CTL0) | + HDMI_WRITE(HDMI_MAI_CTL, + VC4_HD_MAI_CTL_DLATE | + VC4_HD_MAI_CTL_ERRORE | + VC4_HD_MAI_CTL_ERRORF); + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) | VC4_HDMI_TX_PHY_RNG_PWRDN); break; default: @@ -945,6 +901,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = { static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) { + const struct vc4_hdmi_register *mai_data = + &vc4_hdmi->variant->registers[HDMI_MAI_DATA]; struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link; struct snd_soc_card *card = &vc4_hdmi->audio.card; struct device *dev = &vc4_hdmi->pdev->dev; @@ -957,6 +915,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) return 0; } + if (mai_data->reg != VC4_HD) { + WARN_ONCE(true, "MAI isn't in the HD block\n"); + return -EINVAL; + } + /* * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve * the bus address specified in the DT, because the physical address @@ -965,7 +928,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) * This VC/MMU should probably be exposed to avoid this kind of hacks. */ addr = of_get_address(dev->of_node, 1, NULL, NULL); - vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA; + vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; vc4_hdmi->audio.dma_data.maxburst = 2; @@ -1057,7 +1020,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); for (i = 0; i < msg->len; i += 4) { - u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i); + u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i); msg->msg[i] = val & 0xff; msg->msg[i + 1] = (val >> 8) & 0xff; @@ -1069,26 +1032,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) static irqreturn_t vc4_cec_irq_handler(int irq, void *priv) { struct vc4_hdmi *vc4_hdmi = priv; - u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS); + u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS); u32 cntrl1, cntrl5; if (!(stat & VC4_HDMI_CPU_CEC)) return IRQ_NONE; vc4_hdmi->cec_rx_msg.len = 0; - cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1); - cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); + cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1); + cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5); vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT; if (vc4_hdmi->cec_irq_was_rx) { vc4_cec_read_msg(vc4_hdmi, cntrl1); cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1); + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF; } else { vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD; cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; } - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1); - HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC); + HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1); + HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC); return IRQ_WAKE_THREAD; } @@ -1098,7 +1061,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); /* clock period in microseconds */ const u32 usecs = 1000000 / CEC_CLOCK_FREQ; - u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5); + u32 val = HDMI_READ(HDMI_CEC_CNTRL_5); val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET | VC4_HDMI_CEC_CNT_TO_4700_US_MASK | @@ -1107,30 +1070,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT); if (enable) { - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val | + HDMI_WRITE(HDMI_CEC_CNTRL_5, val | VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2, - ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) | - ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) | - ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) | - ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) | - ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT)); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3, - ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) | - ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) | - ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) | - ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT)); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4, - ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) | - ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) | - ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) | - ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT)); - - HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); + HDMI_WRITE(HDMI_CEC_CNTRL_5, val); + HDMI_WRITE(HDMI_CEC_CNTRL_2, + ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) | + ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) | + ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) | + ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) | + ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT)); + HDMI_WRITE(HDMI_CEC_CNTRL_3, + ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) | + ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) | + ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) | + ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT)); + HDMI_WRITE(HDMI_CEC_CNTRL_4, + ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) | + ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) | + ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) | + ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT)); + + HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC); } else { - HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val | + HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC); + HDMI_WRITE(HDMI_CEC_CNTRL_5, val | VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET); } return 0; @@ -1140,8 +1103,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, - (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | + HDMI_WRITE(HDMI_CEC_CNTRL_1, + (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) | (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT); return 0; } @@ -1154,20 +1117,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, unsigned int i; for (i = 0; i < msg->len; i += 4) - HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i, + HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i, (msg->msg[i]) | (msg->msg[i + 1] << 8) | (msg->msg[i + 2] << 16) | (msg->msg[i + 3] << 24)); - val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1); + val = HDMI_READ(HDMI_CEC_CNTRL_1); val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN; - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val); + HDMI_WRITE(HDMI_CEC_CNTRL_1, val); val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK; val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT; val |= VC4_HDMI_CEC_START_XMIT_BEGIN; - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val); + HDMI_WRITE(HDMI_CEC_CNTRL_1, val); return 0; } @@ -1178,6 +1141,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { }; #endif +static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, + struct debugfs_regset32 *regset, + enum vc4_hdmi_regs reg) +{ + const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; + struct debugfs_reg32 *regs, *new_regs; + unsigned int count = 0; + unsigned int i; + + regs = kcalloc(variant->num_registers, sizeof(*regs), + GFP_KERNEL); + if (!regs) + return -ENOMEM; + + for (i = 0; i < variant->num_registers; i++) { + const struct vc4_hdmi_register *field = &variant->registers[i]; + + if (field->reg != reg) + continue; + + regs[count].name = field->name; + regs[count].offset = field->offset; + count++; + } + + new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL); + if (!new_regs) + return -ENOMEM; + + regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg); + regset->regs = new_regs; + regset->nregs = count; + + return 0; +} + static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) { struct platform_device *pdev = vc4_hdmi->pdev; @@ -1192,13 +1191,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) if (IS_ERR(vc4_hdmi->hd_regs)) return PTR_ERR(vc4_hdmi->hd_regs); - vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs; - vc4_hdmi->hdmi_regset.regs = hdmi_regs; - vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs); + ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD); + if (ret) + return ret; - vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs; - vc4_hdmi->hd_regset.regs = hd_regs; - vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs); + ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI); + if (ret) + return ret; vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel"); if (IS_ERR(vc4_hdmi->pixel_clock)) { @@ -1293,12 +1292,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) } /* HDMI core must be enabled. */ - if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) { - HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST); + if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) { + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); udelay(1); - HD_WRITE(VC4_HD_M_CTL, 0); + HDMI_WRITE(HDMI_M_CTL, 0); - HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE); + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); } pm_runtime_enable(dev); @@ -1321,8 +1320,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); - HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff); - value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1); + HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); + value = HDMI_READ(HDMI_CEC_CNTRL_1); value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; /* * Set the logical address to Unregistered and set the clock @@ -1331,7 +1330,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) */ value |= VC4_HDMI_CEC_ADDR_MASK | (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); - HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value); + HDMI_WRITE(HDMI_CEC_CNTRL_1, value); ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), vc4_cec_irq_handler, vc4_cec_irq_handler_thread, 0, @@ -1394,6 +1393,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0); vc4_hdmi = dev_get_drvdata(dev); + kfree(vc4_hdmi->hdmi_regset.regs); + kfree(vc4_hdmi->hd_regset.regs); + cec_unregister_adapter(vc4_hdmi->cec_adap); vc4_hdmi_connector_destroy(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); @@ -1421,6 +1423,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) } static const struct vc4_hdmi_variant bcm2835_variant = { + .registers = vc4_hdmi_fields, + .num_registers = ARRAY_SIZE(vc4_hdmi_fields), + .init_resources = vc4_hdmi_init_resources, }; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 0eaf979fe8112..b36e0210671f2 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) } struct vc4_hdmi; +struct vc4_hdmi_register; struct vc4_hdmi_variant { + /* List of the registers available on that variant */ + const struct vc4_hdmi_register *registers; + + /* Number of registers on that variant */ + unsigned int num_registers; + /* Callback to get the resources (memory region, interrupts, * clocks, etc) for that variant. */ @@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) return container_of(_encoder, struct vc4_hdmi, encoder); } -#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset) -#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset) -#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset) -#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset) - #endif /* _VC4_HDMI_H_ */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h new file mode 100644 index 0000000000000..bc47cc9bc8834 --- /dev/null +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -0,0 +1,241 @@ +#ifndef _VC4_HDMI_REGS_H_ +#define _VC4_HDMI_REGS_H_ + +#include "vc4_hdmi.h" + +#define VC4_HDMI_PACKET_STRIDE 0x24 + +enum vc4_hdmi_regs { + VC4_INVALID = 0, + VC4_HDMI, + VC4_HD, +}; + +enum vc4_hdmi_field { + HDMI_AUDIO_PACKET_CONFIG, + HDMI_CEC_CNTRL_1, + HDMI_CEC_CNTRL_2, + HDMI_CEC_CNTRL_3, + HDMI_CEC_CNTRL_4, + HDMI_CEC_CNTRL_5, + HDMI_CEC_CPU_CLEAR, + HDMI_CEC_CPU_MASK_CLEAR, + HDMI_CEC_CPU_MASK_SET, + HDMI_CEC_CPU_MASK_STATUS, + HDMI_CEC_CPU_STATUS, + + /* + * Transmit data, first byte is low byte of the 32-bit reg. + * MSB of each byte transmitted first. + */ + HDMI_CEC_RX_DATA_1, + HDMI_CEC_RX_DATA_2, + HDMI_CEC_RX_DATA_3, + HDMI_CEC_RX_DATA_4, + HDMI_CEC_TX_DATA_1, + HDMI_CEC_TX_DATA_2, + HDMI_CEC_TX_DATA_3, + HDMI_CEC_TX_DATA_4, + HDMI_CORE_REV, + HDMI_CRP_CFG, + HDMI_CSC_12_11, + HDMI_CSC_14_13, + HDMI_CSC_22_21, + HDMI_CSC_24_23, + HDMI_CSC_32_31, + HDMI_CSC_34_33, + HDMI_CSC_CTL, + + /* + * 20-bit fields containing CTS values to be transmitted if + * !EXTERNAL_CTS_EN + */ + HDMI_CTS_0, + HDMI_CTS_1, + HDMI_FIFO_CTL, + HDMI_FRAME_COUNT, + HDMI_HORZA, + HDMI_HORZB, + HDMI_HOTPLUG, + HDMI_HOTPLUG_INT, + + /* + * 3 bits per field, where each field maps from that + * corresponding MAI bus channel to the given HDMI channel. + */ + HDMI_MAI_CHANNEL_MAP, + HDMI_MAI_CONFIG, + HDMI_MAI_CTL, + + /* + * Register for DMAing in audio data to be transported over + * the MAI bus to the Falcon core. + */ + HDMI_MAI_DATA, + + /* Format header to be placed on the MAI data. Unused. */ + HDMI_MAI_FMT, + + /* Last received format word on the MAI bus. */ + HDMI_MAI_FORMAT, + HDMI_MAI_SMP, + HDMI_MAI_THR, + HDMI_M_CTL, + HDMI_RAM_PACKET_CONFIG, + HDMI_RAM_PACKET_START, + HDMI_RAM_PACKET_STATUS, + HDMI_SCHEDULER_CONTROL, + HDMI_SW_RESET_CONTROL, + HDMI_TX_PHY_CTL_0, + HDMI_TX_PHY_RESET_CTL, + HDMI_VERTA0, + HDMI_VERTA1, + HDMI_VERTB0, + HDMI_VERTB1, + HDMI_VID_CTL, +}; + +struct vc4_hdmi_register { + char *name; + enum vc4_hdmi_regs reg; + unsigned int offset; +}; + +#define _VC4_REG(_base, _reg, _offset) \ + [_reg] = { \ + .name = #_reg, \ + .reg = _base, \ + .offset = _offset, \ + } + +#define VC4_HD_REG(reg, offset) _VC4_REG(VC4_HD, reg, offset) +#define VC4_HDMI_REG(reg, offset) _VC4_REG(VC4_HDMI, reg, offset) + +static const struct vc4_hdmi_register vc4_hdmi_fields[] = { + VC4_HD_REG(HDMI_M_CTL, 0x000c), + VC4_HD_REG(HDMI_MAI_CTL, 0x0014), + VC4_HD_REG(HDMI_MAI_THR, 0x0018), + VC4_HD_REG(HDMI_MAI_FMT, 0x001c), + VC4_HD_REG(HDMI_MAI_DATA, 0x0020), + VC4_HD_REG(HDMI_MAI_SMP, 0x002c), + VC4_HD_REG(HDMI_VID_CTL, 0x0038), + VC4_HD_REG(HDMI_CSC_CTL, 0x0040), + VC4_HD_REG(HDMI_CSC_12_11, 0x0044), + VC4_HD_REG(HDMI_CSC_14_13, 0x0048), + VC4_HD_REG(HDMI_CSC_22_21, 0x004c), + VC4_HD_REG(HDMI_CSC_24_23, 0x0050), + VC4_HD_REG(HDMI_CSC_32_31, 0x0054), + VC4_HD_REG(HDMI_CSC_34_33, 0x0058), + VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068), + + VC4_HDMI_REG(HDMI_CORE_REV, 0x0000), + VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004), + VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008), + VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c), + VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c), + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090), + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094), + VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098), + VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c), + VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0), + VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4), + VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8), + VC4_HDMI_REG(HDMI_CTS_0, 0x00ac), + VC4_HDMI_REG(HDMI_CTS_1, 0x00b0), + VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0), + VC4_HDMI_REG(HDMI_HORZA, 0x00c4), + VC4_HDMI_REG(HDMI_HORZB, 0x00c8), + VC4_HDMI_REG(HDMI_VERTA0, 0x00cc), + VC4_HDMI_REG(HDMI_VERTB0, 0x00d0), + VC4_HDMI_REG(HDMI_VERTA1, 0x00d4), + VC4_HDMI_REG(HDMI_VERTB1, 0x00d8), + VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8), + VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec), + VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0), + VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4), + VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8), + VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc), + VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100), + VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104), + VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108), + VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c), + VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110), + VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114), + VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118), + VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0), + VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4), + VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340), + VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348), + VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c), + VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c), + VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354), + VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400), +}; + +static inline +void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi, + enum vc4_hdmi_regs reg) +{ + switch (reg) { + case VC4_HD: + return hdmi->hd_regs; + + case VC4_HDMI: + return hdmi->hdmicore_regs; + + default: + return NULL; + } + + return NULL; +} + +static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, + enum vc4_hdmi_regs reg) +{ + const struct vc4_hdmi_register *field; + const struct vc4_hdmi_variant *variant = hdmi->variant; + void __iomem *base; + + if (reg > variant->num_registers) { + dev_warn(&hdmi->pdev->dev, + "Invalid register ID %u\n", reg); + return 0; + } + + field = &variant->registers[reg]; + base = __vc4_hdmi_get_field_base(hdmi, field->reg); + if (!base) { + dev_warn(&hdmi->pdev->dev, + "Unknown register ID %u\n", reg); + return 0; + } + + return readl(base + field->offset); +} +#define HDMI_READ(reg) vc4_hdmi_read(vc4_hdmi, reg) + +static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, + enum vc4_hdmi_regs reg, + u32 value) +{ + const struct vc4_hdmi_register *field; + const struct vc4_hdmi_variant *variant = hdmi->variant; + void __iomem *base; + + if (reg > variant->num_registers) { + dev_warn(&hdmi->pdev->dev, + "Invalid register ID %u\n", reg); + return; + } + + field = &variant->registers[reg]; + base = __vc4_hdmi_get_field_base(hdmi, field->reg); + if (!base) + return; + + writel(value, base + field->offset); +} +#define HDMI_WRITE(reg, val) vc4_hdmi_write(vc4_hdmi, reg, val) + +#endif /* _VC4_HDMI_REGS_H_ */ diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index c0031ab19689e..d1e8961edaa06 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -493,32 +493,16 @@ #define SCALER5_DLIST_START 0x00004000 -#define VC4_HDMI_CORE_REV 0x000 - -#define VC4_HDMI_SW_RESET_CONTROL 0x004 # define VC4_HDMI_SW_RESET_FORMAT_DETECT BIT(1) # define VC4_HDMI_SW_RESET_HDMI BIT(0) -#define VC4_HDMI_HOTPLUG_INT 0x008 - -#define VC4_HDMI_HOTPLUG 0x00c # define VC4_HDMI_HOTPLUG_CONNECTED BIT(0) -/* 3 bits per field, where each field maps from that corresponding MAI - * bus channel to the given HDMI channel. - */ -#define VC4_HDMI_MAI_CHANNEL_MAP 0x090 - -#define VC4_HDMI_MAI_CONFIG 0x094 # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE BIT(27) # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE BIT(26) # define VC4_HDMI_MAI_CHANNEL_MASK_MASK VC4_MASK(15, 0) # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT 0 -/* Last received format word on the MAI bus. */ -#define VC4_HDMI_MAI_FORMAT 0x098 - -#define VC4_HDMI_AUDIO_PACKET_CONFIG 0x09c # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT BIT(29) # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS BIT(24) # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT BIT(19) @@ -532,12 +516,8 @@ # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK VC4_MASK(7, 0) # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT 0 -#define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0 # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) -#define VC4_HDMI_RAM_PACKET_STATUS 0x0a4 - -#define VC4_HDMI_CRP_CFG 0x0a8 /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead * of pixel clock. */ @@ -551,23 +531,12 @@ # define VC4_HDMI_CRP_CFG_N_MASK VC4_MASK(19, 0) # define VC4_HDMI_CRP_CFG_N_SHIFT 0 -/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */ -#define VC4_HDMI_CTS_0 0x0ac -#define VC4_HDMI_CTS_1 0x0b0 -/* 20-bit fields containing number of clocks to send CTS0/1 before - * switching to the other one. - */ -#define VC4_HDMI_CTS_PERIOD_0 0x0b4 -#define VC4_HDMI_CTS_PERIOD_1 0x0b8 - -#define VC4_HDMI_HORZA 0x0c4 # define VC4_HDMI_HORZA_VPOS BIT(14) # define VC4_HDMI_HORZA_HPOS BIT(13) /* Horizontal active pixels (hdisplay). */ # define VC4_HDMI_HORZA_HAP_MASK VC4_MASK(12, 0) # define VC4_HDMI_HORZA_HAP_SHIFT 0 -#define VC4_HDMI_HORZB 0x0c8 /* Horizontal pack porch (htotal - hsync_end). */ # define VC4_HDMI_HORZB_HBP_MASK VC4_MASK(29, 20) # define VC4_HDMI_HORZB_HBP_SHIFT 20 @@ -578,7 +547,6 @@ # define VC4_HDMI_HORZB_HFP_MASK VC4_MASK(9, 0) # define VC4_HDMI_HORZB_HFP_SHIFT 0 -#define VC4_HDMI_FIFO_CTL 0x05c # define VC4_HDMI_FIFO_CTL_RECENTER_DONE BIT(14) # define VC4_HDMI_FIFO_CTL_USE_EMPTY BIT(13) # define VC4_HDMI_FIFO_CTL_ON_VB BIT(7) @@ -591,15 +559,12 @@ # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N BIT(0) # define VC4_HDMI_FIFO_VALID_WRITE_MASK 0xefff -#define VC4_HDMI_SCHEDULER_CONTROL 0x0c0 # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15) # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5) # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT BIT(3) # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE BIT(1) # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI BIT(0) -#define VC4_HDMI_VERTA0 0x0cc -#define VC4_HDMI_VERTA1 0x0d4 /* Vertical sync pulse (vsync_end - vsync_start). */ # define VC4_HDMI_VERTA_VSP_MASK VC4_MASK(24, 20) # define VC4_HDMI_VERTA_VSP_SHIFT 20 @@ -610,8 +575,6 @@ # define VC4_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0) # define VC4_HDMI_VERTA_VAL_SHIFT 0 -#define VC4_HDMI_VERTB0 0x0d0 -#define VC4_HDMI_VERTB1 0x0d8 /* Vertical sync pulse offset (for interlaced) */ # define VC4_HDMI_VERTB_VSPO_MASK VC4_MASK(21, 9) # define VC4_HDMI_VERTB_VSPO_SHIFT 9 @@ -619,7 +582,6 @@ # define VC4_HDMI_VERTB_VBP_MASK VC4_MASK(8, 0) # define VC4_HDMI_VERTB_VBP_SHIFT 0 -#define VC4_HDMI_CEC_CNTRL_1 0x0e8 /* Set when the transmission has ended. */ # define VC4_HDMI_CEC_TX_EOM BIT(31) /* If set, transmission was acked on the 1st or 2nd attempt (only one @@ -660,7 +622,6 @@ /* Set these fields to how many bit clock cycles get to that many * microseconds. */ -#define VC4_HDMI_CEC_CNTRL_2 0x0ec # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK VC4_MASK(30, 24) # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT 24 # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK VC4_MASK(23, 17) @@ -672,7 +633,6 @@ # define VC4_HDMI_CEC_CNT_TO_400_US_MASK VC4_MASK(4, 0) # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT 0 -#define VC4_HDMI_CEC_CNTRL_3 0x0f0 # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK VC4_MASK(31, 24) # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT 24 # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK VC4_MASK(23, 16) @@ -682,7 +642,6 @@ # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK VC4_MASK(7, 0) # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT 0 -#define VC4_HDMI_CEC_CNTRL_4 0x0f4 # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK VC4_MASK(31, 24) # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT 24 # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK VC4_MASK(23, 16) @@ -692,7 +651,6 @@ # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK VC4_MASK(7, 0) # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT 0 -#define VC4_HDMI_CEC_CNTRL_5 0x0f8 # define VC4_HDMI_CEC_TX_SW_RESET BIT(27) # define VC4_HDMI_CEC_RX_SW_RESET BIT(26) # define VC4_HDMI_CEC_PAD_SW_RESET BIT(25) @@ -705,39 +663,11 @@ # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK VC4_MASK(7, 0) # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT 0 -/* Transmit data, first byte is low byte of the 32-bit reg. MSB of - * each byte transmitted first. - */ -#define VC4_HDMI_CEC_TX_DATA_1 0x0fc -#define VC4_HDMI_CEC_TX_DATA_2 0x100 -#define VC4_HDMI_CEC_TX_DATA_3 0x104 -#define VC4_HDMI_CEC_TX_DATA_4 0x108 -#define VC4_HDMI_CEC_RX_DATA_1 0x10c -#define VC4_HDMI_CEC_RX_DATA_2 0x110 -#define VC4_HDMI_CEC_RX_DATA_3 0x114 -#define VC4_HDMI_CEC_RX_DATA_4 0x118 - -#define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 - -#define VC4_HDMI_TX_PHY_CTL0 0x2c4 # define VC4_HDMI_TX_PHY_RNG_PWRDN BIT(25) -/* Interrupt status bits */ -#define VC4_HDMI_CPU_STATUS 0x340 -#define VC4_HDMI_CPU_SET 0x344 -#define VC4_HDMI_CPU_CLEAR 0x348 # define VC4_HDMI_CPU_CEC BIT(6) # define VC4_HDMI_CPU_HOTPLUG BIT(0) -#define VC4_HDMI_CPU_MASK_STATUS 0x34c -#define VC4_HDMI_CPU_MASK_SET 0x350 -#define VC4_HDMI_CPU_MASK_CLEAR 0x354 - -#define VC4_HDMI_GCP(x) (0x400 + ((x) * 0x4)) -#define VC4_HDMI_RAM_PACKET(x) (0x400 + ((x) * 0x24)) -#define VC4_HDMI_PACKET_STRIDE 0x24 - -#define VC4_HD_M_CTL 0x00c /* Debug: Current receive value on the CEC pad. */ # define VC4_HD_CECRXD BIT(9) /* Debug: Override CEC output to 0. */ @@ -747,7 +677,6 @@ # define VC4_HD_M_SW_RST BIT(2) # define VC4_HD_M_ENABLE BIT(0) -#define VC4_HD_MAI_CTL 0x014 /* Set when audio stream is received at a slower rate than the * sampling period, so MAI fifo goes empty. Write 1 to clear. */ @@ -772,7 +701,6 @@ /* Single-shot reset bit. Read value is undefined. */ # define VC4_HD_MAI_CTL_RESET BIT(0) -#define VC4_HD_MAI_THR 0x018 # define VC4_HD_MAI_THR_PANICHIGH_MASK VC4_MASK(29, 24) # define VC4_HD_MAI_THR_PANICHIGH_SHIFT 24 # define VC4_HD_MAI_THR_PANICLOW_MASK VC4_MASK(21, 16) @@ -782,31 +710,20 @@ # define VC4_HD_MAI_THR_DREQLOW_MASK VC4_MASK(5, 0) # define VC4_HD_MAI_THR_DREQLOW_SHIFT 0 -/* Format header to be placed on the MAI data. Unused. */ -#define VC4_HD_MAI_FMT 0x01c - -/* Register for DMAing in audio data to be transported over the MAI - * bus to the Falcon core. - */ -#define VC4_HD_MAI_DATA 0x020 - /* Divider from HDMI HSM clock to MAI serial clock. Sampling period * converges to N / (M + 1) cycles. */ -#define VC4_HD_MAI_SMP 0x02c # define VC4_HD_MAI_SMP_N_MASK VC4_MASK(31, 8) # define VC4_HD_MAI_SMP_N_SHIFT 8 # define VC4_HD_MAI_SMP_M_MASK VC4_MASK(7, 0) # define VC4_HD_MAI_SMP_M_SHIFT 0 -#define VC4_HD_VID_CTL 0x038 # define VC4_HD_VID_CTL_ENABLE BIT(31) # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE BIT(30) # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29) # define VC4_HD_VID_CTL_VSYNC_LOW BIT(28) # define VC4_HD_VID_CTL_HSYNC_LOW BIT(27) -#define VC4_HD_CSC_CTL 0x040 # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 # define VC4_HD_CSC_CTL_ORDER_RGB 0 @@ -824,15 +741,6 @@ # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) # define VC4_HD_CSC_CTL_ENABLE BIT(0) -#define VC4_HD_CSC_12_11 0x044 -#define VC4_HD_CSC_14_13 0x048 -#define VC4_HD_CSC_22_21 0x04c -#define VC4_HD_CSC_24_23 0x050 -#define VC4_HD_CSC_32_31 0x054 -#define VC4_HD_CSC_34_33 0x058 - -#define VC4_HD_FRAME_COUNT 0x068 - /* HVS display list information. */ #define HVS_BOOTLOADER_DLIST_END 32 -- GitLab From 9045e91a476b7504b8bfb207466b7b12dd135381 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:24 +0200 Subject: [PATCH 0901/1494] drm/vc4: hdmi: Add reset callback The BCM2711 and BCM283x HDMI controllers use a slightly different reset sequence, so let's add a callback to reset the controller. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/a34bcb493da07eae58ed704f65e72ce0748e8952.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index adc7c06936507..77971be075ec9 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) return 0; } +static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HDMI_WRITE(HDMI_M_CTL, 0); + + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); + + HDMI_WRITE(HDMI_SW_RESET_CONTROL, + VC4_HDMI_SW_RESET_HDMI | + VC4_HDMI_SW_RESET_FORMAT_DETECT); + + HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); +} + static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { @@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - HDMI_WRITE(HDMI_SW_RESET_CONTROL, - VC4_HDMI_SW_RESET_HDMI | - VC4_HDMI_SW_RESET_FORMAT_DETECT); - - HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); + if (vc4_hdmi->variant->reset) + vc4_hdmi->variant->reset(vc4_hdmi); /* PHY should be in reset, like * vc4_hdmi_encoder_disable() does. @@ -1291,14 +1303,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - /* HDMI core must be enabled. */ - if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) { - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); - udelay(1); - HDMI_WRITE(HDMI_M_CTL, 0); - - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); - } pm_runtime_enable(dev); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); @@ -1427,6 +1431,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .num_registers = ARRAY_SIZE(vc4_hdmi_fields), .init_resources = vc4_hdmi_init_resources, + .reset = vc4_hdmi_reset, }; static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index b36e0210671f2..17a30589f39c5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -35,6 +35,9 @@ struct vc4_hdmi_variant { * clocks, etc) for that variant. */ int (*init_resources)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to reset the HDMI block */ + void (*reset)(struct vc4_hdmi *vc4_hdmi); }; /* HDMI audio information */ -- GitLab From c457b8aededd6c0b5a4ee6ba408f378791c9ebf8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:25 +0200 Subject: [PATCH 0902/1494] drm/vc4: hdmi: Add PHY init and disable function The HDMI PHY in the BCM2711 HDMI controller is significantly more complicated to setup than in the older BCM283x SoCs. Let's add hooks to enable and disable the PHY. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/7216826284dbc60a58bdacd662805d20699e5c80.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/Makefile | 1 + drivers/gpu/drm/vc4/vc4_hdmi.c | 14 +++++++------- drivers/gpu/drm/vc4/vc4_hdmi.h | 13 +++++++++++++ drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile index b303703bc7f37..d0163e18e9caa 100644 --- a/drivers/gpu/drm/vc4/Makefile +++ b/drivers/gpu/drm/vc4/Makefile @@ -12,6 +12,7 @@ vc4-y := \ vc4_kms.o \ vc4_gem.o \ vc4_hdmi.o \ + vc4_hdmi_phy.o \ vc4_vec.o \ vc4_hvs.o \ vc4_irq.o \ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 77971be075ec9..f3cc612f6a0b1 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); + if (vc4_hdmi->variant->phy_disable) + vc4_hdmi->variant->phy_disable(vc4_hdmi); + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); @@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->reset) vc4_hdmi->variant->reset(vc4_hdmi); - /* PHY should be in reset, like - * vc4_hdmi_encoder_disable() does. - */ - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); - - HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); + if (vc4_hdmi->variant->phy_init) + vc4_hdmi->variant->phy_init(vc4_hdmi, mode); if (debug_dump_regs) { struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); @@ -1432,6 +1430,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .init_resources = vc4_hdmi_init_resources, .reset = vc4_hdmi_reset, + .phy_init = vc4_hdmi_phy_init, + .phy_disable = vc4_hdmi_phy_disable, }; static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 17a30589f39c5..32c80161c786b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder) return container_of(encoder, struct vc4_hdmi_encoder, base.base); } +struct drm_display_mode; + struct vc4_hdmi; struct vc4_hdmi_register; @@ -38,6 +40,13 @@ struct vc4_hdmi_variant { /* Callback to reset the HDMI block */ void (*reset)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to initialize the PHY according to the mode */ + void (*phy_init)(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode); + + /* Callback to disable the PHY */ + void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); }; /* HDMI audio information */ @@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) return container_of(_encoder, struct vc4_hdmi, encoder); } +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode); +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); + #endif /* _VC4_HDMI_H_ */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c new file mode 100644 index 0000000000000..5a1746877bb59 --- /dev/null +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2015 Broadcom + * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2013 Red Hat + * Author: Rob Clark <robdclark@gmail.com> + */ + +#include "vc4_hdmi.h" +#include "vc4_hdmi_regs.h" + +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) +{ + /* PHY should be in reset, like + * vc4_hdmi_encoder_disable() does. + */ + + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0); +} + +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); +} -- GitLab From 647b9655061b9e260c296de0e23745ac04d7c96d Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:26 +0200 Subject: [PATCH 0903/1494] drm/vc4: hdmi: Add PHY RNG enable / disable function Let's continue the implementation of hooks for the parts that change in the BCM2711 SoC with the PHY RNG setup. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/216155f1c0b83e622ac60a2f7d00eb707de3acba.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 15 +++++++++------ drivers/gpu/drm/vc4/vc4_hdmi.h | 8 ++++++++ drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f3cc612f6a0b1..c29376c3fd8a8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: vc4_hdmi_set_audio_infoframe(encoder); - HDMI_WRITE(HDMI_TX_PHY_CTL_0, - HDMI_READ(HDMI_TX_PHY_CTL_0) & - ~VC4_HDMI_TX_PHY_RNG_PWRDN); + + if (vc4_hdmi->variant->phy_rng_enable) + vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); HDMI_WRITE(HDMI_MAI_CTL, VC4_SET_FIELD(vc4_hdmi->audio.channels, @@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, VC4_HD_MAI_CTL_DLATE | VC4_HD_MAI_CTL_ERRORE | VC4_HD_MAI_CTL_ERRORF); - HDMI_WRITE(HDMI_TX_PHY_CTL_0, - HDMI_READ(HDMI_TX_PHY_CTL_0) | - VC4_HDMI_TX_PHY_RNG_PWRDN); + + if (vc4_hdmi->variant->phy_rng_disable) + vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); + break; default: break; @@ -1432,6 +1433,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .reset = vc4_hdmi_reset, .phy_init = vc4_hdmi_phy_init, .phy_disable = vc4_hdmi_phy_disable, + .phy_rng_enable = vc4_hdmi_phy_rng_enable, + .phy_rng_disable = vc4_hdmi_phy_rng_disable, }; static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 32c80161c786b..950accbc44e4a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -47,6 +47,12 @@ struct vc4_hdmi_variant { /* Callback to disable the PHY */ void (*phy_disable)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to enable the RNG in the PHY */ + void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to disable the RNG in the PHY */ + void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi); }; /* HDMI audio information */ @@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode); void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); #endif /* _VC4_HDMI_H_ */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c index 5a1746877bb59..93287e24d7d1d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -7,6 +7,7 @@ */ #include "vc4_hdmi.h" +#include "vc4_regs.h" #include "vc4_hdmi_regs.h" void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) @@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) { HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16); } + +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) & + ~VC4_HDMI_TX_PHY_RNG_PWRDN); +} + +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + HDMI_READ(HDMI_TX_PHY_CTL_0) | + VC4_HDMI_TX_PHY_RNG_PWRDN); +} -- GitLab From 89f31a23fd1302eb8e717605ee87e39e222600d7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:27 +0200 Subject: [PATCH 0904/1494] drm/vc4: hdmi: Add a CSC setup callback Similarly to the previous patches, the CSC setup is slightly different in the BCM2711 than in the previous generations. Let's add a callback for it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/5c19bbf10153cb42ca0fb67e08606c8295c17236.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 70 ++++++++++++++++++++-------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 ++ 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c29376c3fd8a8..532618e023998 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -334,6 +334,41 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) DRM_ERROR("Failed to release power domain: %d\n", ret); } +static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) +{ + u32 csc_ctl; + + csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, + VC4_HD_CSC_CTL_ORDER); + + if (enable) { + /* CEA VICs other than #1 requre limited range RGB + * output unless overridden by an AVI infoframe. + * Apply a colorspace conversion to squash 0-255 down + * to 16-235. The matrix here is: + * + * [ 0 0 0.8594 16] + * [ 0 0.8594 0 16] + * [ 0.8594 0 0 16] + * [ 0 0 0 1] + */ + csc_ctl |= VC4_HD_CSC_CTL_ENABLE; + csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC; + csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, + VC4_HD_CSC_CTL_MODE); + + HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0); + HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000); + HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0); + HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000); + } + + /* The RGB order applies even when CSC is disabled. */ + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); +} + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; @@ -357,7 +392,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) mode->crtc_vsync_end - interlaced, VC4_HDMI_VERTB_VBP)); - u32 csc_ctl; int ret; ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); @@ -428,41 +462,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, - VC4_HD_CSC_CTL_ORDER); if (vc4_encoder->hdmi_monitor && - drm_default_rgb_quant_range(mode) == - HDMI_QUANTIZATION_RANGE_LIMITED) { - /* CEA VICs other than #1 requre limited range RGB - * output unless overridden by an AVI infoframe. - * Apply a colorspace conversion to squash 0-255 down - * to 16-235. The matrix here is: - * - * [ 0 0 0.8594 16] - * [ 0 0.8594 0 16] - * [ 0.8594 0 0 16] - * [ 0 0 0 1] - */ - csc_ctl |= VC4_HD_CSC_CTL_ENABLE; - csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC; - csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, - VC4_HD_CSC_CTL_MODE); + drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { + if (vc4_hdmi->variant->csc_setup) + vc4_hdmi->variant->csc_setup(vc4_hdmi, true); - HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000); - HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0); - HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000); - HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000); - HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0); - HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000); vc4_encoder->limited_rgb_range = true; } else { + if (vc4_hdmi->variant->csc_setup) + vc4_hdmi->variant->csc_setup(vc4_hdmi, false); + vc4_encoder->limited_rgb_range = false; } - /* The RGB order applies even when CSC is disabled. */ - HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); - HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); if (debug_dump_regs) { @@ -1430,6 +1443,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .num_registers = ARRAY_SIZE(vc4_hdmi_fields), .init_resources = vc4_hdmi_init_resources, + .csc_setup = vc4_hdmi_csc_setup, .reset = vc4_hdmi_reset, .phy_init = vc4_hdmi_phy_init, .phy_disable = vc4_hdmi_phy_disable, diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 950accbc44e4a..c8fd58548ea2b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -41,6 +41,9 @@ struct vc4_hdmi_variant { /* Callback to reset the HDMI block */ void (*reset)(struct vc4_hdmi *vc4_hdmi); + /* Callback to enable / disable the CSC */ + void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable); + /* Callback to initialize the PHY according to the mode */ void (*phy_init)(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode); -- GitLab From 904f668adcdeb71aa7bcf6a1aad731bb7b363b13 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:28 +0200 Subject: [PATCH 0905/1494] drm/vc4: hdmi: Add a set_timings callback Similarly to the previous patches, the timings setup in the HDMI controller of the BCM2711 is slightly different, mostly because it supports higher resolutions and thus needed more spaces for the various timings, resulting in the register layout changing. Let's add a callback for that as well. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/0cfcbb379212f90b4abc76c0ccf3b90d1d7c0268.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 72 +++++++++++++++++++--------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++ 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 532618e023998..9e2bc6cb690e7 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -369,12 +369,9 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); } -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode) { - struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; - struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder; - bool debug_dump_regs = false; bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -392,6 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) mode->crtc_vsync_end - interlaced, VC4_HDMI_VERTB_VBP)); + + HDMI_WRITE(HDMI_HORZA, + (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | + (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | + VC4_SET_FIELD(mode->hdisplay * pixel_rep, + VC4_HDMI_HORZA_HAP)); + + HDMI_WRITE(HDMI_HORZB, + VC4_SET_FIELD((mode->htotal - + mode->hsync_end) * pixel_rep, + VC4_HDMI_HORZB_HBP) | + VC4_SET_FIELD((mode->hsync_end - + mode->hsync_start) * pixel_rep, + VC4_HDMI_HORZB_HSP) | + VC4_SET_FIELD((mode->hsync_start - + mode->hdisplay) * pixel_rep, + VC4_HDMI_HORZB_HFP)); + + HDMI_WRITE(HDMI_VERTA0, verta); + HDMI_WRITE(HDMI_VERTA1, verta); + + HDMI_WRITE(HDMI_VERTB0, vertb_even); + HDMI_WRITE(HDMI_VERTB1, vertb); + + HDMI_WRITE(HDMI_VID_CTL, + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); +} + +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +{ + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + bool debug_dump_regs = false; int ret; ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); @@ -435,33 +467,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS); - HDMI_WRITE(HDMI_HORZA, - (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | - (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | - VC4_SET_FIELD(mode->hdisplay * pixel_rep, - VC4_HDMI_HORZA_HAP)); - - HDMI_WRITE(HDMI_HORZB, - VC4_SET_FIELD((mode->htotal - - mode->hsync_end) * pixel_rep, - VC4_HDMI_HORZB_HBP) | - VC4_SET_FIELD((mode->hsync_end - - mode->hsync_start) * pixel_rep, - VC4_HDMI_HORZB_HSP) | - VC4_SET_FIELD((mode->hsync_start - - mode->hdisplay) * pixel_rep, - VC4_HDMI_HORZB_HFP)); - - HDMI_WRITE(HDMI_VERTA0, verta); - HDMI_WRITE(HDMI_VERTA1, verta); - - HDMI_WRITE(HDMI_VERTB0, vertb_even); - HDMI_WRITE(HDMI_VERTB1, vertb); - - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - + if (vc4_hdmi->variant->set_timings) + vc4_hdmi->variant->set_timings(vc4_hdmi, mode); if (vc4_encoder->hdmi_monitor && drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { @@ -1445,6 +1452,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .init_resources = vc4_hdmi_init_resources, .csc_setup = vc4_hdmi_csc_setup, .reset = vc4_hdmi_reset, + .set_timings = vc4_hdmi_set_timings, .phy_init = vc4_hdmi_phy_init, .phy_disable = vc4_hdmi_phy_disable, .phy_rng_enable = vc4_hdmi_phy_rng_enable, diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index c8fd58548ea2b..0c32dc46d289a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -44,6 +44,10 @@ struct vc4_hdmi_variant { /* Callback to enable / disable the CSC */ void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable); + /* Callback to configure the video timings in the HDMI block */ + void (*set_timings)(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode); + /* Callback to initialize the PHY according to the mode */ void (*phy_init)(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode); -- GitLab From 7d73299dad3edd3e3caf7b9d2817c3db931a26d3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:29 +0200 Subject: [PATCH 0906/1494] drm/vc4: hdmi: Store the encoder type in the variant structure The vc4 CRTC will use the encoder type to control its output clock muxing. However, this will be different from HDMI0 to HDMI1, so let's store our type in the variant structure so that we can support multiple controllers later on. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/2736a86b498551ba9dbc5803c5bb910627a2550c.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 9e2bc6cb690e7..f6d18bdbd1bb3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1267,7 +1267,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, vc4_hdmi); encoder = &vc4_hdmi->encoder.base.base; - vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0; + vc4_hdmi->encoder.base.type = variant->encoder_type; vc4_hdmi->pdev = pdev; vc4_hdmi->variant = variant; @@ -1446,6 +1446,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) } static const struct vc4_hdmi_variant bcm2835_variant = { + .encoder_type = VC4_ENCODER_TYPE_HDMI0, .registers = vc4_hdmi_fields, .num_registers = ARRAY_SIZE(vc4_hdmi_fields), diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 0c32dc46d289a..0d529db4b3ab3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -27,6 +27,9 @@ struct vc4_hdmi; struct vc4_hdmi_register; struct vc4_hdmi_variant { + /* Encoder Type for that controller */ + enum vc4_encoder_type encoder_type; + /* List of the registers available on that variant */ const struct vc4_hdmi_register *registers; -- GitLab From b2405c98260ad5ce08c1b33b82198812ba3e004e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:30 +0200 Subject: [PATCH 0907/1494] drm/vc4: hdmi: Deal with multiple debugfs files The HDMI driver was registering a single debugfs file so far with the name hdmi_regs. Obviously, this is not going to work anymore when will have multiple HDMI controllers since we will end up trying to register two files with the same name. Let's use the variant to avoid that name conflict. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/9505c1eb40b3ef3709277bf9e8af77917b249c32.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f6d18bdbd1bb3..4d0b44a2ac619 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1369,7 +1369,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_destroy_encoder; - vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi); + vc4_debugfs_add_file(drm, variant->debugfs_name, + vc4_hdmi_debugfs_regs, + vc4_hdmi); return 0; @@ -1447,6 +1449,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) static const struct vc4_hdmi_variant bcm2835_variant = { .encoder_type = VC4_ENCODER_TYPE_HDMI0, + .debugfs_name = "hdmi_regs", .registers = vc4_hdmi_fields, .num_registers = ARRAY_SIZE(vc4_hdmi_fields), diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 0d529db4b3ab3..794216f3228de 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -30,6 +30,9 @@ struct vc4_hdmi_variant { /* Encoder Type for that controller */ enum vc4_encoder_type encoder_type; + /* Filename to expose the registers in debugfs */ + const char *debugfs_name; + /* List of the registers available on that variant */ const struct vc4_hdmi_register *registers; -- GitLab From c0791e08380117c2d52e63f0e03d73610ce07858 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:31 +0200 Subject: [PATCH 0908/1494] drm/vc4: hdmi: Move CEC init to its own function The CEC init code was put directly into the bind function, which was quite inconsistent with how the audio support was done, and would prevent us from further changes to skip that initialisation entirely. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/21f4717e076291522d0784a7fd3774d8e97eaf01.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 108 ++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 4d0b44a2ac619..bf537c6d413f4 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1170,6 +1170,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = { .adap_log_addr = vc4_hdmi_cec_adap_log_addr, .adap_transmit = vc4_hdmi_cec_adap_transmit, }; + +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +{ + struct cec_connector_info conn_info; + struct platform_device *pdev = vc4_hdmi->pdev; + u32 value; + int ret; + + vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, + vc4_hdmi, "vc4", + CEC_CAP_DEFAULTS | + CEC_CAP_CONNECTOR_INFO, 1); + ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); + if (ret < 0) + return ret; + + cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); + cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); + + HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); + value = HDMI_READ(HDMI_CEC_CNTRL_1); + value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; + /* + * Set the logical address to Unregistered and set the clock + * divider: the hsm_clock rate and this divider setting will + * give a 40 kHz CEC clock. + */ + value |= VC4_HDMI_CEC_ADDR_MASK | + (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); + HDMI_WRITE(HDMI_CEC_CNTRL_1, value); + ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0), + vc4_cec_irq_handler, + vc4_cec_irq_handler_thread, 0, + "vc4 hdmi cec", vc4_hdmi); + if (ret) + goto err_delete_cec_adap; + + ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev); + if (ret < 0) + goto err_delete_cec_adap; + + return 0; + +err_delete_cec_adap: + cec_delete_adapter(vc4_hdmi->cec_adap); + + return ret; +} + +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) +{ + cec_unregister_adapter(vc4_hdmi->cec_adap); +} +#else +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) +{ + return 0; +} + +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {}; + #endif static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi, @@ -1249,9 +1310,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) { -#ifdef CONFIG_DRM_VC4_HDMI_CEC - struct cec_connector_info conn_info; -#endif const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); @@ -1331,43 +1389,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (ret) goto err_destroy_encoder; -#ifdef CONFIG_DRM_VC4_HDMI_CEC - vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, - vc4_hdmi, "vc4", - CEC_CAP_DEFAULTS | - CEC_CAP_CONNECTOR_INFO, 1); - ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap); - if (ret < 0) - goto err_destroy_conn; - - cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector); - cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info); - - HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff); - value = HDMI_READ(HDMI_CEC_CNTRL_1); - value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK; - /* - * Set the logical address to Unregistered and set the clock - * divider: the hsm_clock rate and this divider setting will - * give a 40 kHz CEC clock. - */ - value |= VC4_HDMI_CEC_ADDR_MASK | - (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT); - HDMI_WRITE(HDMI_CEC_CNTRL_1, value); - ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), - vc4_cec_irq_handler, - vc4_cec_irq_handler_thread, 0, - "vc4 hdmi cec", vc4_hdmi); + ret = vc4_hdmi_cec_init(vc4_hdmi); if (ret) - goto err_delete_cec_adap; - ret = cec_register_adapter(vc4_hdmi->cec_adap, dev); - if (ret < 0) - goto err_delete_cec_adap; -#endif + goto err_destroy_conn; ret = vc4_hdmi_audio_init(vc4_hdmi); if (ret) - goto err_destroy_encoder; + goto err_free_cec; vc4_debugfs_add_file(drm, variant->debugfs_name, vc4_hdmi_debugfs_regs, @@ -1375,12 +1403,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return 0; -#ifdef CONFIG_DRM_VC4_HDMI_CEC -err_delete_cec_adap: - cec_delete_adapter(vc4_hdmi->cec_adap); +err_free_cec: + vc4_hdmi_cec_exit(vc4_hdmi); err_destroy_conn: vc4_hdmi_connector_destroy(&vc4_hdmi->connector); -#endif err_destroy_encoder: drm_encoder_cleanup(encoder); err_unprepare_hsm: @@ -1421,7 +1447,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, kfree(vc4_hdmi->hdmi_regset.regs); kfree(vc4_hdmi->hd_regset.regs); - cec_unregister_adapter(vc4_hdmi->cec_adap); + vc4_hdmi_cec_exit(vc4_hdmi); vc4_hdmi_connector_destroy(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); -- GitLab From 234f4212ecec4f7f5db7a8698392569770b395b2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:32 +0200 Subject: [PATCH 0909/1494] drm/vc4: hdmi: Add CEC support flag Similarly to the audio support, CEC support is not there yet for the BCM2711, so let's skip entirely the CEC initialization through a variant flag. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/bd0c4afa83b4e121692352cdc2dd1886162c7552.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++ drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index bf537c6d413f4..a26b6bd61f74c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1178,6 +1178,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi) u32 value; int ret; + if (!vc4_hdmi->variant->cec_available) + return 0; + vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops, vc4_hdmi, "vc4", CEC_CAP_DEFAULTS | @@ -1476,6 +1479,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) static const struct vc4_hdmi_variant bcm2835_variant = { .encoder_type = VC4_ENCODER_TYPE_HDMI0, .debugfs_name = "hdmi_regs", + .cec_available = true, .registers = vc4_hdmi_fields, .num_registers = ARRAY_SIZE(vc4_hdmi_fields), diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 794216f3228de..3f07aebe89f13 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -33,6 +33,9 @@ struct vc4_hdmi_variant { /* Filename to expose the registers in debugfs */ const char *debugfs_name; + /* Set to true when the CEC support is available */ + bool cec_available; + /* List of the registers available on that variant */ const struct vc4_hdmi_register *registers; -- GitLab From 4c55c2c40dc9a2914e668cd9152200653b99ff4a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:33 +0200 Subject: [PATCH 0910/1494] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/53805cc47e99a137e5f08c92fb781cc2e2134299.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a26b6bd61f74c..e39c6fcf4c124 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -55,7 +55,6 @@ #define HSM_CLOCK_FREQ 163682864 #define CEC_CLOCK_FREQ 40000 -#define CEC_CLOCK_DIV (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ) static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { -- GitLab From 11a1731eb6eac76a446d837dba115e67d24a6ee1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:34 +0200 Subject: [PATCH 0911/1494] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid The mode_valid hook on the encoder uses a pointer to a drm_encoder called crtc, which is pretty confusing. Let's rename it to encoder to make it clear what it is. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/7fbabab03992efe4a3a3640ac5ee2bb49b1c7338.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e39c6fcf4c124..1e6c0e26d1863 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } static enum drm_mode_status -vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc, +vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { /* -- GitLab From cd4cb49dc5bb5f8595ed7828e41329e9380fd0b1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:35 +0200 Subject: [PATCH 0912/1494] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate The HSM clock needs to be setup at around 101% of the pixel rate. This was done previously by setting the clock rate to 163.7MHz at probe time and only check in mode_valid whether the mode pixel clock was under the pixel clock +1% or not. However, with 4k we need to change that frequency to a higher frequency than 163.7MHz, and yet want to have the lowest clock as possible to have a decent power saving. Let's change that logic a bit by setting the clock rate of the HSM clock to the pixel rate at encoder_enable time. This would work for the BCM2711 that support 4k resolutions and has a clock that can provide it, but we still have to take care of a 4k panel plugged on a BCM283x SoCs that wouldn't be able to use those modes, so let's define the limit in the variant. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/7e692ddc231d33dd671e70ea04dd1dcf56c1ecb3.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++------------------ drivers/gpu/drm/vc4/vc4_hdmi.h | 3 ++ 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1e6c0e26d1863..84273fe650d6c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -53,7 +53,6 @@ #include "vc4_hdmi_regs.h" #include "vc4_regs.h" -#define HSM_CLOCK_FREQ 163682864 #define CEC_CLOCK_FREQ 40000 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); + clk_disable_unprepare(vc4_hdmi->hsm_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); ret = pm_runtime_put(&vc4_hdmi->pdev->dev); @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); bool debug_dump_regs = false; + unsigned long pixel_rate, hsm_rate; int ret; ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - ret = clk_set_rate(vc4_hdmi->pixel_clock, - mode->clock * 1000 * - ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1)); + pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1); + ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); if (ret) { DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); return; @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * pixel clock, but HSM ends up being the limiting factor. + */ + hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); + ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); + if (ret) { + DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); + return; + } + + ret = clk_prepare_enable(vc4_hdmi->hsm_clock); + if (ret) { + DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); + clk_disable_unprepare(vc4_hdmi->pixel_clock); + return; + } + if (vc4_hdmi->variant->reset) vc4_hdmi->variant->reset(vc4_hdmi); @@ -559,23 +589,9 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in - * simulation. Otherwise, exact value is unimportant for HDMI - * operation." This conflicts with bcm2835's vc4 documentation, which - * states HSM's clock has to be at least 108% of the pixel clock. - * - * Real life tests reveal that vc4's firmware statement holds up, and - * users are able to use pixel clocks closer to HSM's, namely for - * 1920x1200@60Hz. So it was decided to have leave a 1% margin between - * both clocks. Which, for RPi0-3 implies a maximum pixel clock of - * 162MHz. - * - * Additionally, the AXI clock needs to be at least 25% of - * pixel clock, but HSM ends up being the limiting factor. - */ - if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100)) + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + + if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) return MODE_CLOCK_HIGH; return MODE_OK; @@ -1348,23 +1364,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) return -EPROBE_DEFER; } - /* This is the rate that is set by the firmware. The number - * needs to be a bit higher than the pixel clock rate - * (generally 148.5Mhz). - */ - ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ); - if (ret) { - DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); - goto err_put_i2c; - } - - ret = clk_prepare_enable(vc4_hdmi->hsm_clock); - if (ret) { - DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n", - ret); - goto err_put_i2c; - } - /* Only use the GPIO HPD pin if present in the DT, otherwise * we'll use the HDMI core's register. */ @@ -1412,9 +1411,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) err_destroy_encoder: drm_encoder_cleanup(encoder); err_unprepare_hsm: - clk_disable_unprepare(vc4_hdmi->hsm_clock); pm_runtime_disable(dev); -err_put_i2c: put_device(&vc4_hdmi->ddc->dev); return ret; @@ -1453,7 +1450,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master, vc4_hdmi_connector_destroy(&vc4_hdmi->connector); drm_encoder_cleanup(&vc4_hdmi->encoder.base.base); - clk_disable_unprepare(vc4_hdmi->hsm_clock); pm_runtime_disable(dev); put_device(&vc4_hdmi->ddc->dev); @@ -1478,6 +1474,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) static const struct vc4_hdmi_variant bcm2835_variant = { .encoder_type = VC4_ENCODER_TYPE_HDMI0, .debugfs_name = "hdmi_regs", + .max_pixel_clock = 162000000, .cec_available = true, .registers = vc4_hdmi_fields, .num_registers = ARRAY_SIZE(vc4_hdmi_fields), diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 3f07aebe89f13..342f6e0227a2e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -36,6 +36,9 @@ struct vc4_hdmi_variant { /* Set to true when the CEC support is available */ bool cec_available; + /* Maximum pixel clock supported by the controller (in Hz) */ + unsigned long long max_pixel_clock; + /* List of the registers available on that variant */ const struct vc4_hdmi_register *registers; -- GitLab From d5d5ce885c00af156325bf463657651284e61d40 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:36 +0200 Subject: [PATCH 0913/1494] drm/vc4: hdmi: Use clk_set_min_rate instead The HSM clock needs to be running at 101% the pixel clock of the HDMI controller, however it's shared between the two HDMI controllers, which means that if the resolutions are different between the two HDMI controllers, and the lowest resolution is on the second (in enable order) controller, the first HDMI controller will end up with a smaller than expected clock rate. Since we don't really need an exact frequency there, we can simply change the minimum rate we expect instead. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/821992209cc0d7a83254bf26fe2bf507ef0994d2.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 84273fe650d6c..487c04de6b85c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) * pixel clock, but HSM ends up being the limiting factor. */ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); - ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); + ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); return; -- GitLab From 094864bd0054ea831b573f733cf2a5a0741f7cb5 Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:01:37 +0200 Subject: [PATCH 0914/1494] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers The register range used for audio setup in the previous generations of SoC were always the second range in the device tree. However, now that the BCM2711 has way more register ranges, it makes sense to retrieve it by names for it, while preserving the id-based lookup as a fallback. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/a1ba5605fe1006a1ead5262ef3d66ea5d0750381.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 487c04de6b85c..53c3b5ae1179c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -953,6 +953,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) struct snd_soc_card *card = &vc4_hdmi->audio.card; struct device *dev = &vc4_hdmi->pdev->dev; const __be32 *addr; + int index; int ret; if (!of_find_property(dev->of_node, "dmas", NULL)) { @@ -973,7 +974,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) * for DMA transfers. * This VC/MMU should probably be exposed to avoid this kind of hacks. */ - addr = of_get_address(dev->of_node, 1, NULL, NULL); + index = of_property_match_string(dev->of_node, "reg-names", "hd"); + /* Before BCM2711, we don't have a named register range */ + if (index < 0) + index = 1; + + addr = of_get_address(dev->of_node, index, NULL, NULL); + vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset; vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; vc4_hdmi->audio.dma_data.maxburst = 2; -- GitLab From 6ac1c7532217509379a8de5da9a4cc3a79aa99aa Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:01:38 +0200 Subject: [PATCH 0915/1494] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming If the encoder is disabled and re-enabled (eg mode change) all infoframes are reset, whilst the audio subsystem know nothing about this change. The driver therefore needs to reinstate the audio infoframe for itself. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/cd579ccc2c9b9d2fce0ebaf32f847cedb0e4a7a2.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++++++ drivers/gpu/drm/vc4/vc4_hdmi.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 53c3b5ae1179c..43e59466b1d81 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -308,8 +308,16 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder) static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) { + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + vc4_hdmi_set_avi_infoframe(encoder); vc4_hdmi_set_spd_infoframe(encoder); + /* + * If audio was streaming, then we need to reenabled the audio + * infoframe here during encoder_enable. + */ + if (vc4_hdmi->audio.streaming) + vc4_hdmi_set_audio_infoframe(encoder); } static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) @@ -694,6 +702,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi) struct device *dev = &vc4_hdmi->pdev->dev; int ret; + vc4_hdmi->audio.streaming = false; ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO); if (ret) dev_err(dev, "Failed to stop audio infoframe: %d\n", ret); @@ -797,6 +806,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: vc4_hdmi_set_audio_infoframe(encoder); + vc4_hdmi->audio.streaming = true; if (vc4_hdmi->variant->phy_rng_enable) vc4_hdmi->variant->phy_rng_enable(vc4_hdmi); @@ -815,6 +825,8 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, if (vc4_hdmi->variant->phy_rng_disable) vc4_hdmi->variant->phy_rng_disable(vc4_hdmi); + vc4_hdmi->audio.streaming = false; + break; default: break; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 342f6e0227a2e..77d47d1707cea 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -85,6 +85,8 @@ struct vc4_hdmi_audio { int channels; struct snd_dmaengine_dai_dma_data dma_data; struct snd_pcm_substream *substream; + + bool streaming; }; /* General HDMI hardware state. */ -- GitLab From b9b8bac60ab3917fb37de0eb8bd5ddfefa2d89f4 Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:01:39 +0200 Subject: [PATCH 0916/1494] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default. ALSA's iec958 plugin by default sets the block start preamble to 8, whilst this driver was programming the hardware to expect 0xF. Amend the hardware config to match ALSA. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/d0b126deb228baf1244c91e02ac0a8f7c9c60dc5.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 43e59466b1d81..d8137b838326b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -754,10 +754,11 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, vc4_hdmi_audio_set_mai_clock(vc4_hdmi); + /* The B frame identifier should match the value used by alsa-lib (8) */ audio_packet_config = VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT | VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS | - VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER); + VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER); channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0); audio_packet_config |= VC4_SET_FIELD(channel_mask, -- GitLab From 632ee3aa8786e41c3adfc1eb13223f1bbd20f46d Mon Sep 17 00:00:00 2001 From: Dave Stevenson <dave.stevenson@raspberrypi.com> Date: Thu, 3 Sep 2020 10:01:40 +0200 Subject: [PATCH 0917/1494] drm/vc4: hdmi: Add audio-related callbacks The audio configuration has changed for the BCM2711, with notably a different parent clock and a different channel configuration. Make that modular to be able to support the BCM2711. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Link: https://patchwork.freedesktop.org/patch/msgid/85a8ca721c2d800be758c55870cea98536749680.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++-------- drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d8137b838326b..20cfc85449ca9 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -611,10 +611,22 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { .enable = vc4_hdmi_encoder_enable, }; +static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) +{ + int i; + u32 channel_map = 0; + + for (i = 0; i < 8; i++) { + if (channel_mask & BIT(i)) + channel_map |= i << (3 * i); + } + return channel_map; +} + /* HDMI audio codec callbacks */ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) { - u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock); + u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock); unsigned long n, m; rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate, @@ -733,7 +745,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai); struct device *dev = &vc4_hdmi->pdev->dev; u32 audio_packet_config, channel_mask; - u32 channel_map, i; + u32 channel_map; if (substream != vc4_hdmi->audio.substream) return -EINVAL; @@ -785,12 +797,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream, VC4_HDMI_MAI_CONFIG_BIT_REVERSE | VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK)); - channel_map = 0; - for (i = 0; i < 8; i++) { - if (channel_mask & BIT(i)) - channel_map |= i << (3 * i); - } - + channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask); HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map); HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config); vc4_hdmi_set_n_cts(vc4_hdmi); @@ -1342,6 +1349,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) DRM_ERROR("Failed to get HDMI state machine clock\n"); return PTR_ERR(vc4_hdmi->hsm_clock); } + vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock; return 0; } @@ -1507,6 +1515,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .phy_disable = vc4_hdmi_phy_disable, .phy_rng_enable = vc4_hdmi_phy_rng_enable, .phy_rng_disable = vc4_hdmi_phy_rng_disable, + .channel_map = vc4_hdmi_channel_map, }; static const struct of_device_id vc4_hdmi_dt_match[] = { diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 77d47d1707cea..4aea5ee8a91db 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -72,6 +72,9 @@ struct vc4_hdmi_variant { /* Callback to disable the RNG in the PHY */ void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi); + + /* Callback to get channel map */ + u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask); }; /* HDMI audio information */ @@ -112,6 +115,7 @@ struct vc4_hdmi { struct clk *pixel_clock; struct clk *hsm_clock; + struct clk *audio_clock; struct debugfs_regset32 hdmi_regset; struct debugfs_regset32 hd_regset; -- GitLab From 9be43a5a6de5e89bbb7fa137a2348735e48d85f0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:41 +0200 Subject: [PATCH 0918/1494] drm/vc4: hdmi: Deal with multiple ALSA cards The HDMI driver was registering a single ALSA card so far with the name vc4-hdmi. Obviously, this is not going to work anymore when we will have multiple HDMI controllers since we will end up trying to register two files with the same name. Let's use the variant to avoid that name conflict. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/e60a37444e848a384a45707a21d6df8883115f86.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++- drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 20cfc85449ca9..5e479647559f4 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1043,7 +1043,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) card->dai_link = dai_link; card->num_links = 1; - card->name = "vc4-hdmi"; + card->name = vc4_hdmi->variant->card_name; card->dev = dev; /* @@ -1502,6 +1502,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev) static const struct vc4_hdmi_variant bcm2835_variant = { .encoder_type = VC4_ENCODER_TYPE_HDMI0, .debugfs_name = "hdmi_regs", + .card_name = "vc4-hdmi", .max_pixel_clock = 162000000, .cec_available = true, .registers = vc4_hdmi_fields, diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 4aea5ee8a91db..34138e0dd4a6f 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -30,6 +30,9 @@ struct vc4_hdmi_variant { /* Encoder Type for that controller */ enum vc4_encoder_type encoder_type; + /* ALSA card name */ + const char *card_name; + /* Filename to expose the registers in debugfs */ const char *debugfs_name; -- GitLab From 1bb0522e92ec8047037513a4ea9bdf76c42bce96 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:42 +0200 Subject: [PATCH 0919/1494] drm/vc4: hdmi: Remove register dumps in enable The current code has some logic, disabled by default, to dump the register setup in the HDMI controller. However, since we're going to split those functions in multiple, shorter, functions that only make sense where they are called in sequence, keeping the register dump makes little sense. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/c8c8d388f2d32fc3536336be36d003a862487eb7.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 5e479647559f4..3c7862a1dda8f 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - bool debug_dump_regs = false; unsigned long pixel_rate, hsm_rate; int ret; @@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, 0); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | -- GitLab From 691456f622a96b4e90e7798a671c7753d924375f Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:43 +0200 Subject: [PATCH 0920/1494] drm/vc4: hdmi: Always recenter the HDMI FIFO In order to avoid a pixel getting stuck in an unflushable FIFO, we need to recenter the FIFO every time we're doing a modeset and not only if we're connected to an HDMI monitor. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/b3faaf05ac6c4d3c364d28fa441571eb85903269.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 3c7862a1dda8f..c9eae5352b9ac 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); } +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) +{ + u32 drift; + int ret; + + drift = HDMI_READ(HDMI_FIFO_CTL); + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; + + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + usleep_range(1000, 1100); + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); + WARN_ONCE(ret, "Timeout waiting for " + "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); +} + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } if (vc4_encoder->hdmi_monitor) { - u32 drift; - WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) VC4_HDMI_RAM_PACKET_ENABLE); vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - usleep_range(1000, 1100); - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } + + vc4_hdmi_recenter_fifo(vc4_hdmi); } static enum drm_mode_status -- GitLab From 09c438139b8f5b832823db2e2a8a29f990647fc5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:44 +0200 Subject: [PATCH 0921/1494] drm/vc4: hdmi: Implement finer-grained hooks In order to prevent some pixels getting stuck in an unflushable FIFO on bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI controller (the encoder) in an intertwined way, and with tight delays. However, the atomic callbacks don't really provide a way to work with either constraints, so we need to roll our own callbacks so that we can provide those guarantees. Since those callbacks have been implemented and called in the CRTC code, we can just implement them in the HDMI driver now. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/2e9226d971117065f3b97e597f04f7fe2f0c134c.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 39 ++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c9eae5352b9ac..128d33c8c2c3b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) vc4_hdmi_set_audio_infoframe(encoder); } -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - int ret; HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); +} + +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + int ret; if (vc4_hdmi->variant->phy_disable) vc4_hdmi->variant->phy_disable(vc4_hdmi); @@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) DRM_ERROR("Failed to release power domain: %d\n", ret); } +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +{ +} + static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) { u32 csc_ctl; @@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); unsigned long pixel_rate, hsm_rate; int ret; @@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->set_timings) vc4_hdmi->variant->set_timings(vc4_hdmi, mode); +} + +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) +{ + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if (vc4_encoder->hdmi_monitor && drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { @@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); +} + +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + int ret; HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | @@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) vc4_hdmi_recenter_fifo(vc4_hdmi); } +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +{ +} + static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) @@ -1361,6 +1387,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) dev_set_drvdata(dev, vc4_hdmi); encoder = &vc4_hdmi->encoder.base.base; vc4_hdmi->encoder.base.type = variant->encoder_type; + vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; + vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; + vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; vc4_hdmi->pdev = pdev; vc4_hdmi->variant = variant; -- GitLab From 8b3f90e98e17644ee4899da953816d124fb1ac9f Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:45 +0200 Subject: [PATCH 0922/1494] drm/vc4: hdmi: Do the VID_CTL configuration at once The VID_CTL setup is done in several places in the driver even though it's not really required. Let's simplify it a bit to do the configuration in one go. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/08e7ebb605a560fcc149b69b4af52753a7870b2f.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 128d33c8c2c3b..8bf69cafdd7e7 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); } static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) @@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - HDMI_WRITE(HDMI_VID_CTL, 0); - HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | @@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) { + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; int ret; HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | VC4_HD_VID_CTL_UNDERFLOW_ENABLE | - VC4_HD_VID_CTL_FRAME_COUNTER_RESET); + VC4_HD_VID_CTL_FRAME_COUNTER_RESET | + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, -- GitLab From 81d830137bdb462ca0bef91ba1f187d7be5d0081 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:46 +0200 Subject: [PATCH 0923/1494] drm/vc4: hdmi: Switch to blank pixels when disabled In order to avoid pixels getting stuck in an unflushable FIFO, we need when we disable the HDMI controller to switch away from getting our pixels from the pixelvalve and instead use blank pixels, and switch back to the pixelvalve when we enable the HDMI controller. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/fde3efb1ad79f4476a73d310cbba3ec07dc6dabe.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 9 +++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 8bf69cafdd7e7..ab7abb409de2a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); + + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC); + + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); } static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) @@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX); + if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index d1e8961edaa06..30af52b406f1c 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -723,6 +723,9 @@ # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29) # define VC4_HD_VID_CTL_VSYNC_LOW BIT(28) # define VC4_HD_VID_CTL_HSYNC_LOW BIT(27) +# define VC4_HD_VID_CTL_CLRSYNC BIT(24) +# define VC4_HD_VID_CTL_CLRRGB BIT(23) +# define VC4_HD_VID_CTL_BLANKPIX BIT(18) # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 -- GitLab From 373874298cac99dc5b32f831f9aff5e64f75de85 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon <hoegeun.kwon@samsung.com> Date: Thu, 3 Sep 2020 10:01:47 +0200 Subject: [PATCH 0924/1494] drm/vc4: hdmi: Add pixel BVB clock control The BCM2711 has another clock that needs to be ramped up depending on the pixel rate: the pixel BVB clock. Add the code to adjust that clock when changing the mode. [Maxime: Changed the commit log, used clk_set_min_rate] Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://lore.kernel.org/r/20200901040759.29992-3-hoegeun.kwon@samsung.com Link: https://patchwork.freedesktop.org/patch/msgid/d757ddd6549da140f178563e5fd2bf1d129913fd.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_hdmi.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index ab7abb409de2a..c24510ba7f8f8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -54,6 +54,7 @@ #include "vc4_regs.h" #define CEC_CLOCK_FREQ 40000 +#define VC4_HSM_MID_CLOCK 149985000 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) { @@ -344,6 +345,7 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); + clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); clk_disable_unprepare(vc4_hdmi->hsm_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); @@ -516,6 +518,27 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) return; } + /* + * FIXME: When the pixel freq is 594MHz (4k60), this needs to be setup + * at 300MHz. + */ + ret = clk_set_min_rate(vc4_hdmi->pixel_bvb_clock, + (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000)); + if (ret) { + DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); + clk_disable_unprepare(vc4_hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->pixel_clock); + return; + } + + ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); + if (ret) { + DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); + clk_disable_unprepare(vc4_hdmi->hsm_clock); + clk_disable_unprepare(vc4_hdmi->pixel_clock); + return; + } + if (vc4_hdmi->variant->reset) vc4_hdmi->variant->reset(vc4_hdmi); diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 34138e0dd4a6f..59639b405b7f1 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -119,6 +119,7 @@ struct vc4_hdmi { struct clk *pixel_clock; struct clk *hsm_clock; struct clk *audio_clock; + struct clk *pixel_bvb_clock; struct debugfs_regset32 hdmi_regset; struct debugfs_regset32 hd_regset; -- GitLab From 8323989140f3e58e3e1da03a3b66ce5c8d65798a Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:48 +0200 Subject: [PATCH 0925/1494] drm/vc4: hdmi: Support the BCM2711 HDMI controllers Now that the driver is ready for it, let's bring in the HDMI controllers variants for the BCM2711. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/b540c7a9ebb7ad51da39271a8388b69c7e27e582.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 284 ++++++++++++++++ drivers/gpu/drm/vc4/vc4_hdmi.h | 36 +++ drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 481 ++++++++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 2 + 5 files changed, 1004 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c24510ba7f8f8..d0792915436c4 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -43,6 +43,7 @@ #include <linux/of_platform.h> #include <linux/pm_runtime.h> #include <linux/rational.h> +#include <linux/reset.h> #include <sound/dmaengine_pcm.h> #include <sound/pcm_drm_eld.h> #include <sound/pcm_params.h> @@ -53,6 +54,31 @@ #include "vc4_hdmi_regs.h" #include "vc4_regs.h" +#define VC5_HDMI_HORZA_HFP_SHIFT 16 +#define VC5_HDMI_HORZA_HFP_MASK VC4_MASK(28, 16) +#define VC5_HDMI_HORZA_VPOS BIT(15) +#define VC5_HDMI_HORZA_HPOS BIT(14) +#define VC5_HDMI_HORZA_HAP_SHIFT 0 +#define VC5_HDMI_HORZA_HAP_MASK VC4_MASK(13, 0) + +#define VC5_HDMI_HORZB_HBP_SHIFT 16 +#define VC5_HDMI_HORZB_HBP_MASK VC4_MASK(26, 16) +#define VC5_HDMI_HORZB_HSP_SHIFT 0 +#define VC5_HDMI_HORZB_HSP_MASK VC4_MASK(10, 0) + +#define VC5_HDMI_VERTA_VSP_SHIFT 24 +#define VC5_HDMI_VERTA_VSP_MASK VC4_MASK(28, 24) +#define VC5_HDMI_VERTA_VFP_SHIFT 16 +#define VC5_HDMI_VERTA_VFP_MASK VC4_MASK(22, 16) +#define VC5_HDMI_VERTA_VAL_SHIFT 0 +#define VC5_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0) + +#define VC5_HDMI_VERTB_VSPO_SHIFT 16 +#define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) + +# define VC4_HD_M_SW_RST BIT(2) +# define VC4_HD_M_ENABLE BIT(0) + #define CEC_CLOCK_FREQ 40000 #define VC4_HSM_MID_CLOCK 149985000 @@ -83,6 +109,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); } +static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) +{ + reset_control_reset(vc4_hdmi->reset); + + HDMI_WRITE(HDMI_DVP_CTL, 0); + + HDMI_WRITE(HDMI_CLOCK_STOP, + HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); +} + static enum drm_connector_status vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { @@ -393,6 +429,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); } +static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) +{ + u32 csc_ctl; + + csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */ + + if (enable) { + /* CEA VICs other than #1 requre limited range RGB + * output unless overridden by an AVI infoframe. + * Apply a colorspace conversion to squash 0-255 down + * to 16-235. The matrix here is: + * + * [ 0.8594 0 0 16] + * [ 0 0.8594 0 16] + * [ 0 0 0.8594 16] + * [ 0 0 0 1] + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ + HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80); + HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80); + } else { + /* Still use the matrix for full range, but make it unity. + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ + HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000); + HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); + HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000); + } + + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); +} + static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) { @@ -437,6 +512,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); } +static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode) +{ + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; + bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; + u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; + u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, + VC5_HDMI_VERTA_VSP) | + VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, + VC5_HDMI_VERTA_VFP) | + VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); + u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, + VC4_HDMI_VERTB_VBP)); + u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | + VC4_SET_FIELD(mode->crtc_vtotal - + mode->crtc_vsync_end - + interlaced, + VC4_HDMI_VERTB_VBP)); + + HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); + HDMI_WRITE(HDMI_HORZA, + (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) | + (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) | + VC4_SET_FIELD(mode->hdisplay * pixel_rep, + VC5_HDMI_HORZA_HAP) | + VC4_SET_FIELD((mode->hsync_start - + mode->hdisplay) * pixel_rep, + VC5_HDMI_HORZA_HFP)); + + HDMI_WRITE(HDMI_HORZB, + VC4_SET_FIELD((mode->htotal - + mode->hsync_end) * pixel_rep, + VC5_HDMI_HORZB_HBP) | + VC4_SET_FIELD((mode->hsync_end - + mode->hsync_start) * pixel_rep, + VC5_HDMI_HORZB_HSP)); + + HDMI_WRITE(HDMI_VERTA0, verta); + HDMI_WRITE(HDMI_VERTA1, verta); + + HDMI_WRITE(HDMI_VERTB0, vertb_even); + HDMI_WRITE(HDMI_VERTB1, vertb); + + HDMI_WRITE(HDMI_CLOCK_STOP, 0); +} static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) { @@ -668,6 +790,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) return channel_map; } +static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) +{ + int i; + u32 channel_map = 0; + + for (i = 0; i < 8; i++) { + if (channel_mask & BIT(i)) + channel_map |= i << (4 * i); + } + return channel_map; +} + /* HDMI audio codec callbacks */ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi) { @@ -1399,6 +1533,104 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return 0; } +static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) +{ + struct platform_device *pdev = vc4_hdmi->pdev; + struct device *dev = &pdev->dev; + struct resource *res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); + if (!res) + return -ENODEV; + + vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, + resource_size(res)); + if (IS_ERR(vc4_hdmi->hdmicore_regs)) + return PTR_ERR(vc4_hdmi->hdmicore_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd"); + if (!res) + return -ENODEV; + + vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->hd_regs)) + return PTR_ERR(vc4_hdmi->hd_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec"); + if (!res) + return -ENODEV; + + vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->cec_regs)) + return PTR_ERR(vc4_hdmi->cec_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc"); + if (!res) + return -ENODEV; + + vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->csc_regs)) + return PTR_ERR(vc4_hdmi->csc_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp"); + if (!res) + return -ENODEV; + + vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->dvp_regs)) + return PTR_ERR(vc4_hdmi->dvp_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); + if (!res) + return -ENODEV; + + vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->phy_regs)) + return PTR_ERR(vc4_hdmi->phy_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet"); + if (!res) + return -ENODEV; + + vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->ram_regs)) + return PTR_ERR(vc4_hdmi->ram_regs); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm"); + if (!res) + return -ENODEV; + + vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(vc4_hdmi->rm_regs)) + return PTR_ERR(vc4_hdmi->rm_regs); + + vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); + if (IS_ERR(vc4_hdmi->hsm_clock)) { + DRM_ERROR("Failed to get HDMI state machine clock\n"); + return PTR_ERR(vc4_hdmi->hsm_clock); + } + + vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); + if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { + DRM_ERROR("Failed to get pixel bvb clock\n"); + return PTR_ERR(vc4_hdmi->pixel_bvb_clock); + } + + vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); + if (IS_ERR(vc4_hdmi->audio_clock)) { + DRM_ERROR("Failed to get audio clock\n"); + return PTR_ERR(vc4_hdmi->audio_clock); + } + + vc4_hdmi->reset = devm_reset_control_get(dev, NULL); + if (IS_ERR(vc4_hdmi->reset)) { + DRM_ERROR("Failed to get HDMI reset line\n"); + return PTR_ERR(vc4_hdmi->reset); + } + + return 0; +} + static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) { const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); @@ -1569,8 +1801,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = { .channel_map = vc4_hdmi_channel_map, }; +static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { + .encoder_type = VC4_ENCODER_TYPE_HDMI0, + .debugfs_name = "hdmi0_regs", + .card_name = "vc4-hdmi-0", + .max_pixel_clock = 297000000, + .registers = vc5_hdmi_hdmi0_fields, + .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields), + .phy_lane_mapping = { + PHY_LANE_0, + PHY_LANE_1, + PHY_LANE_2, + PHY_LANE_CK, + }, + + .init_resources = vc5_hdmi_init_resources, + .csc_setup = vc5_hdmi_csc_setup, + .reset = vc5_hdmi_reset, + .set_timings = vc5_hdmi_set_timings, + .phy_init = vc5_hdmi_phy_init, + .phy_disable = vc5_hdmi_phy_disable, + .phy_rng_enable = vc5_hdmi_phy_rng_enable, + .phy_rng_disable = vc5_hdmi_phy_rng_disable, + .channel_map = vc5_hdmi_channel_map, +}; + +static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { + .encoder_type = VC4_ENCODER_TYPE_HDMI1, + .debugfs_name = "hdmi1_regs", + .card_name = "vc4-hdmi-1", + .max_pixel_clock = 297000000, + .registers = vc5_hdmi_hdmi1_fields, + .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields), + .phy_lane_mapping = { + PHY_LANE_1, + PHY_LANE_0, + PHY_LANE_CK, + PHY_LANE_2, + }, + + .init_resources = vc5_hdmi_init_resources, + .csc_setup = vc5_hdmi_csc_setup, + .reset = vc5_hdmi_reset, + .set_timings = vc5_hdmi_set_timings, + .phy_init = vc5_hdmi_phy_init, + .phy_disable = vc5_hdmi_phy_disable, + .phy_rng_enable = vc5_hdmi_phy_rng_enable, + .phy_rng_disable = vc5_hdmi_phy_rng_disable, + .channel_map = vc5_hdmi_channel_map, +}; + static const struct of_device_id vc4_hdmi_dt_match[] = { { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, + { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant }, + { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant }, {} }; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 59639b405b7f1..63c6f8bddf1de 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -26,6 +26,13 @@ struct drm_display_mode; struct vc4_hdmi; struct vc4_hdmi_register; +enum vc4_hdmi_phy_channel { + PHY_LANE_0 = 0, + PHY_LANE_1, + PHY_LANE_2, + PHY_LANE_CK, +}; + struct vc4_hdmi_variant { /* Encoder Type for that controller */ enum vc4_encoder_type encoder_type; @@ -48,6 +55,13 @@ struct vc4_hdmi_variant { /* Number of registers on that variant */ unsigned int num_registers; + /* BCM2711 Only. + * The variants don't map the lane in the same order in the + * PHY, so this is an array mapping the HDMI channel (index) + * to the PHY lane (value). + */ + enum vc4_hdmi_phy_channel phy_lane_mapping[4]; + /* Callback to get the resources (memory region, interrupts, * clocks, etc) for that variant. */ @@ -108,6 +122,20 @@ struct vc4_hdmi { struct i2c_adapter *ddc; void __iomem *hdmicore_regs; void __iomem *hd_regs; + + /* VC5 Only */ + void __iomem *cec_regs; + /* VC5 Only */ + void __iomem *csc_regs; + /* VC5 Only */ + void __iomem *dvp_regs; + /* VC5 Only */ + void __iomem *phy_regs; + /* VC5 Only */ + void __iomem *ram_regs; + /* VC5 Only */ + void __iomem *rm_regs; + int hpd_gpio; bool hpd_active_low; @@ -121,6 +149,8 @@ struct vc4_hdmi { struct clk *audio_clock; struct clk *pixel_bvb_clock; + struct reset_control *reset; + struct debugfs_regset32 hdmi_regset; struct debugfs_regset32 hd_regset; }; @@ -145,4 +175,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, + struct drm_display_mode *mode); +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); + #endif /* _VC4_HDMI_H_ */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c index 93287e24d7d1d..057796b54c51a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -10,6 +10,123 @@ #include "vc4_regs.h" #include "vc4_hdmi_regs.h" +#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB BIT(5) +#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB BIT(4) +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET BIT(3) +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET BIT(2) +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET BIT(1) +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET BIT(0) + +#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN BIT(4) + +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT 29 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK VC4_MASK(31, 29) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT 24 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK VC4_MASK(28, 24) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT 21 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK VC4_MASK(23, 21) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT 16 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK VC4_MASK(20, 16) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT 13 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK VC4_MASK(15, 13) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT 8 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK VC4_MASK(12, 8) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT 5 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK VC4_MASK(7, 5) +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT 0 +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK VC4_MASK(4, 0) + +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT 15 +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK VC4_MASK(19, 15) +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT 10 +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK VC4_MASK(14, 10) +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT 5 +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK VC4_MASK(9, 5) +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT 0 +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK VC4_MASK(4, 0) + +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT 16 +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK VC4_MASK(19, 16) +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT 12 +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK VC4_MASK(15, 12) +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT 8 +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK VC4_MASK(11, 8) +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT 4 +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK VC4_MASK(7, 4) +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT 0 +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK VC4_MASK(3, 0) + +#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT 17 +#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK VC4_MASK(19, 17) +#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT 12 +#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK VC4_MASK(16, 12) +#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT 10 +#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK VC4_MASK(11, 10) +#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT 8 +#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK VC4_MASK(9, 8) +#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT 6 +#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK VC4_MASK(7, 6) +#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT 0 +#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK VC4_MASK(5, 0) + +#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE BIT(13) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN BIT(12) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW BIT(11) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH BIT(10) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT 9 +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK VC4_MASK(9, 9) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2 BIT(8) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2 BIT(7) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN BIT(6) +#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK BIT(5) + +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT 16 +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK VC4_MASK(27, 16) +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT 14 +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK VC4_MASK(15, 14) +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE BIT(13) +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT 11 +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK VC4_MASK(12, 11) + +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT 8 +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK VC4_MASK(15, 8) + +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT 0 +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK VC4_MASK(3, 0) + +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12) +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT 12 +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK VC4_MASK(9, 8) +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8 +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK VC4_MASK(5, 4) +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4 +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK VC4_MASK(1, 0) +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0 + +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK VC4_MASK(27, 0) +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT 0 + +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK VC4_MASK(27, 0) +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT 0 + +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16) +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT 16 +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK VC4_MASK(15, 0) +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT 0 + +#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS BIT(19) +#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR BIT(17) +#define VC4_HDMI_RM_CONTROL_FREE_RUN BIT(4) + +#define VC4_HDMI_RM_OFFSET_ONLY BIT(31) +#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT 0 +#define VC4_HDMI_RM_OFFSET_OFFSET_MASK VC4_MASK(30, 0) + +#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT 24 +#define VC4_HDMI_RM_FORMAT_SHIFT_MASK VC4_MASK(25, 24) + +#define OSCILLATOR_FREQUENCY 54000000 + void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) { /* PHY should be in reset, like @@ -38,3 +155,367 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) HDMI_READ(HDMI_TX_PHY_CTL_0) | VC4_HDMI_TX_PHY_RNG_PWRDN); } + +static unsigned long long +phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div) +{ + unsigned long long vco_freq = clock; + unsigned int _vco_div = 0; + unsigned int _vco_sel = 0; + + while (vco_freq < 3000000000ULL) { + _vco_div++; + vco_freq = clock * _vco_div * 10; + } + + if (vco_freq > 4500000000ULL) + _vco_sel = 1; + + *vco_sel = _vco_sel; + *vco_div = _vco_div; + + return vco_freq; +} + +static u8 phy_get_cp_current(unsigned long vco_freq) +{ + if (vco_freq < 3700000000ULL) + return 0x1c; + + return 0x18; +} + +static u32 phy_get_rm_offset(unsigned long long vco_freq) +{ + unsigned long long fref = OSCILLATOR_FREQUENCY; + u64 offset = 0; + + /* RM offset is stored as 9.22 format */ + offset = vco_freq * 2; + offset = offset << 22; + do_div(offset, fref); + offset >>= 2; + + return offset; +} + +static u8 phy_get_vco_gain(unsigned long long vco_freq) +{ + if (vco_freq < 3350000000ULL) + return 0xf; + + if (vco_freq < 3700000000ULL) + return 0xc; + + if (vco_freq < 4050000000ULL) + return 0x6; + + if (vco_freq < 4800000000ULL) + return 0x5; + + if (vco_freq < 5200000000ULL) + return 0x7; + + return 0x2; +} + +struct phy_lane_settings { + struct { + u8 preemphasis; + u8 main_driver; + } amplitude; + + u8 res_sel_data; + u8 term_res_sel_data; +}; + +struct phy_settings { + unsigned long long min_rate; + unsigned long long max_rate; + struct phy_lane_settings channel[3]; + struct phy_lane_settings clock; +}; + +static const struct phy_settings vc5_hdmi_phy_settings[] = { + { + 0, 50000000, + { + {{0x0, 0x0A}, 0x12, 0x0}, + {{0x0, 0x0A}, 0x12, 0x0}, + {{0x0, 0x0A}, 0x12, 0x0} + }, + {{0x0, 0x0A}, 0x18, 0x0}, + }, + { + 50000001, 75000000, + { + {{0x0, 0x09}, 0x12, 0x0}, + {{0x0, 0x09}, 0x12, 0x0}, + {{0x0, 0x09}, 0x12, 0x0} + }, + {{0x0, 0x0C}, 0x18, 0x3}, + }, + { + 75000001, 165000000, + { + {{0x0, 0x09}, 0x12, 0x0}, + {{0x0, 0x09}, 0x12, 0x0}, + {{0x0, 0x09}, 0x12, 0x0} + }, + {{0x0, 0x0C}, 0x18, 0x3}, + }, + { + 165000001, 250000000, + { + {{0x0, 0x0F}, 0x12, 0x1}, + {{0x0, 0x0F}, 0x12, 0x1}, + {{0x0, 0x0F}, 0x12, 0x1} + }, + {{0x0, 0x0C}, 0x18, 0x3}, + }, + { + 250000001, 340000000, + { + {{0x2, 0x0D}, 0x12, 0x1}, + {{0x2, 0x0D}, 0x12, 0x1}, + {{0x2, 0x0D}, 0x12, 0x1} + }, + {{0x0, 0x0C}, 0x18, 0xF}, + }, + { + 340000001, 450000000, + { + {{0x0, 0x1B}, 0x12, 0xF}, + {{0x0, 0x1B}, 0x12, 0xF}, + {{0x0, 0x1B}, 0x12, 0xF} + }, + {{0x0, 0x0A}, 0x12, 0xF}, + }, + { + 450000001, 600000000, + { + {{0x0, 0x1C}, 0x12, 0xF}, + {{0x0, 0x1C}, 0x12, 0xF}, + {{0x0, 0x1C}, 0x12, 0xF} + }, + {{0x0, 0x0B}, 0x13, 0xF}, + }, +}; + +static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate) +{ + unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings); + unsigned int i; + + for (i = 0; i < count; i++) { + const struct phy_settings *s = &vc5_hdmi_phy_settings[i]; + + if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate) + return s; + } + + /* + * If the pixel clock exceeds our max setting, try the max + * setting anyway. + */ + return &vc5_hdmi_phy_settings[count - 1]; +} + +static const struct phy_lane_settings * +phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, + unsigned long long tmds_rate) +{ + const struct phy_settings *settings = phy_get_settings(tmds_rate); + + if (chan == PHY_LANE_CK) + return &settings->clock; + + return &settings->channel[chan]; +} + +static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f); + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10)); +} + +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) +{ + const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings; + const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; + unsigned long long pixel_freq = mode->clock * 1000; + unsigned long long vco_freq; + unsigned char word_sel; + u8 vco_sel, vco_div; + + vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div); + + vc5_hdmi_reset_phy(vc4_hdmi); + + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); + + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, + HDMI_READ(HDMI_TX_PHY_RESET_CTL) & + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET & + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET & + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET & + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET); + + HDMI_WRITE(HDMI_RM_CONTROL, + HDMI_READ(HDMI_RM_CONTROL) | + VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS | + VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR | + VC4_HDMI_RM_CONTROL_FREE_RUN); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, + (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) & + ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) | + VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT)); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, + (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) & + ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) | + VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT)); + + HDMI_WRITE(HDMI_RM_OFFSET, + VC4_SET_FIELD(phy_get_rm_offset(vco_freq), + VC4_HDMI_RM_OFFSET_OFFSET) | + VC4_HDMI_RM_OFFSET_ONLY); + + HDMI_WRITE(HDMI_TX_PHY_CLK_DIV, + VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO)); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, + VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) | + VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD)); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0, + VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK | + VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN | + VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE | + VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL)); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1, + HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) | + VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE | + VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) | + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) | + VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP)); + + HDMI_WRITE(HDMI_RM_FORMAT, + HDMI_READ(HDMI_RM_FORMAT) | + VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT)); + + HDMI_WRITE(HDMI_TX_PHY_PLL_CFG, + HDMI_READ(HDMI_TX_PHY_PLL_CFG) | + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV)); + + if (pixel_freq >= 340000000) + word_sel = 3; + else + word_sel = 0; + HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel); + + HDMI_WRITE(HDMI_TX_PHY_CTL_3, + VC4_SET_FIELD(phy_get_cp_current(vco_freq), + VC4_HDMI_TX_PHY_CTL_3_ICP) | + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) | + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) | + VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) | + VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) | + VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ)); + + chan0_settings = + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0], + pixel_freq); + chan1_settings = + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1], + pixel_freq); + chan2_settings = + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2], + pixel_freq); + clock_settings = + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK], + pixel_freq); + + HDMI_WRITE(HDMI_TX_PHY_CTL_0, + VC4_SET_FIELD(chan0_settings->amplitude.preemphasis, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) | + VC4_SET_FIELD(chan0_settings->amplitude.main_driver, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) | + VC4_SET_FIELD(chan1_settings->amplitude.preemphasis, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) | + VC4_SET_FIELD(chan1_settings->amplitude.main_driver, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) | + VC4_SET_FIELD(chan2_settings->amplitude.preemphasis, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) | + VC4_SET_FIELD(chan2_settings->amplitude.main_driver, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) | + VC4_SET_FIELD(clock_settings->amplitude.preemphasis, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) | + VC4_SET_FIELD(clock_settings->amplitude.main_driver, + VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV)); + + HDMI_WRITE(HDMI_TX_PHY_CTL_1, + HDMI_READ(HDMI_TX_PHY_CTL_1) | + VC4_SET_FIELD(chan0_settings->res_sel_data, + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) | + VC4_SET_FIELD(chan1_settings->res_sel_data, + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) | + VC4_SET_FIELD(chan2_settings->res_sel_data, + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) | + VC4_SET_FIELD(clock_settings->res_sel_data, + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK)); + + HDMI_WRITE(HDMI_TX_PHY_CTL_2, + VC4_SET_FIELD(chan0_settings->term_res_sel_data, + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) | + VC4_SET_FIELD(chan1_settings->term_res_sel_data, + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) | + VC4_SET_FIELD(chan2_settings->term_res_sel_data, + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) | + VC4_SET_FIELD(clock_settings->term_res_sel_data, + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) | + VC4_SET_FIELD(phy_get_vco_gain(vco_freq), + VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN)); + + HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP, + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0], + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) | + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1], + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) | + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2], + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) | + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK], + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL)); + + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, + HDMI_READ(HDMI_TX_PHY_RESET_CTL) & + ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | + VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB)); + + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, + HDMI_READ(HDMI_TX_PHY_RESET_CTL) | + VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | + VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB); +} + +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) +{ + vc5_hdmi_reset_phy(vc4_hdmi); +} + +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) & + ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); +} + +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) +{ + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) | + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); +} diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index bc47cc9bc8834..a5f1354e3e067 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -9,6 +9,12 @@ enum vc4_hdmi_regs { VC4_INVALID = 0, VC4_HDMI, VC4_HD, + VC5_CEC, + VC5_CSC, + VC5_DVP, + VC5_PHY, + VC5_RAM, + VC5_RM, }; enum vc4_hdmi_field { @@ -36,6 +42,7 @@ enum vc4_hdmi_field { HDMI_CEC_TX_DATA_2, HDMI_CEC_TX_DATA_3, HDMI_CEC_TX_DATA_4, + HDMI_CLOCK_STOP, HDMI_CORE_REV, HDMI_CRP_CFG, HDMI_CSC_12_11, @@ -52,6 +59,7 @@ enum vc4_hdmi_field { */ HDMI_CTS_0, HDMI_CTS_1, + HDMI_DVP_CTL, HDMI_FIFO_CTL, HDMI_FRAME_COUNT, HDMI_HORZA, @@ -84,10 +92,27 @@ enum vc4_hdmi_field { HDMI_RAM_PACKET_CONFIG, HDMI_RAM_PACKET_START, HDMI_RAM_PACKET_STATUS, + HDMI_RM_CONTROL, + HDMI_RM_FORMAT, + HDMI_RM_OFFSET, HDMI_SCHEDULER_CONTROL, HDMI_SW_RESET_CONTROL, + HDMI_TX_PHY_CHANNEL_SWAP, + HDMI_TX_PHY_CLK_DIV, HDMI_TX_PHY_CTL_0, + HDMI_TX_PHY_CTL_1, + HDMI_TX_PHY_CTL_2, + HDMI_TX_PHY_CTL_3, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, + HDMI_TX_PHY_PLL_CFG, + HDMI_TX_PHY_PLL_CTL_0, + HDMI_TX_PHY_PLL_CTL_1, + HDMI_TX_PHY_POWERDOWN_CTL, HDMI_TX_PHY_RESET_CTL, + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, + HDMI_VEC_INTERFACE_XBAR, HDMI_VERTA0, HDMI_VERTA1, HDMI_VERTB0, @@ -110,6 +135,12 @@ struct vc4_hdmi_register { #define VC4_HD_REG(reg, offset) _VC4_REG(VC4_HD, reg, offset) #define VC4_HDMI_REG(reg, offset) _VC4_REG(VC4_HDMI, reg, offset) +#define VC5_CEC_REG(reg, offset) _VC4_REG(VC5_CEC, reg, offset) +#define VC5_CSC_REG(reg, offset) _VC4_REG(VC5_CSC, reg, offset) +#define VC5_DVP_REG(reg, offset) _VC4_REG(VC5_DVP, reg, offset) +#define VC5_PHY_REG(reg, offset) _VC4_REG(VC5_PHY, reg, offset) +#define VC5_RAM_REG(reg, offset) _VC4_REG(VC5_RAM, reg, offset) +#define VC5_RM_REG(reg, offset) _VC4_REG(VC5_RM, reg, offset) static const struct vc4_hdmi_register vc4_hdmi_fields[] = { VC4_HD_REG(HDMI_M_CTL, 0x000c), @@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = { VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400), }; +static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { + VC4_HD_REG(HDMI_DVP_CTL, 0x0000), + VC4_HD_REG(HDMI_MAI_CTL, 0x0010), + VC4_HD_REG(HDMI_MAI_THR, 0x0014), + VC4_HD_REG(HDMI_MAI_FMT, 0x0018), + VC4_HD_REG(HDMI_MAI_DATA, 0x001c), + VC4_HD_REG(HDMI_MAI_SMP, 0x0020), + VC4_HD_REG(HDMI_VID_CTL, 0x0044), + VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060), + + VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074), + VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8), + VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc), + VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4), + VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8), + VC4_HDMI_REG(HDMI_CTS_0, 0x0cc), + VC4_HDMI_REG(HDMI_CTS_1, 0x0d0), + VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0), + VC4_HDMI_REG(HDMI_HORZA, 0x0e4), + VC4_HDMI_REG(HDMI_HORZB, 0x0e8), + VC4_HDMI_REG(HDMI_VERTA0, 0x0ec), + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), + VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004), + VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), + VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), + VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), + VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020), + VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034), + VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044), + VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c), + + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), + + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), + + VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), + VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), + VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), + VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), + VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), + VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), + VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), + VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), + VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), + VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), + VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), + VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), + VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), + + VC5_CSC_REG(HDMI_CSC_CTL, 0x000), + VC5_CSC_REG(HDMI_CSC_12_11, 0x004), + VC5_CSC_REG(HDMI_CSC_14_13, 0x008), + VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), +}; + +static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { + VC4_HD_REG(HDMI_DVP_CTL, 0x0000), + VC4_HD_REG(HDMI_MAI_CTL, 0x0030), + VC4_HD_REG(HDMI_MAI_THR, 0x0034), + VC4_HD_REG(HDMI_MAI_FMT, 0x0038), + VC4_HD_REG(HDMI_MAI_DATA, 0x003c), + VC4_HD_REG(HDMI_MAI_SMP, 0x0040), + VC4_HD_REG(HDMI_VID_CTL, 0x0048), + VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064), + + VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074), + VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8), + VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc), + VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4), + VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8), + VC4_HDMI_REG(HDMI_CTS_0, 0x0cc), + VC4_HDMI_REG(HDMI_CTS_1, 0x0d0), + VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0), + VC4_HDMI_REG(HDMI_HORZA, 0x0e4), + VC4_HDMI_REG(HDMI_HORZB, 0x0e8), + VC4_HDMI_REG(HDMI_VERTA0, 0x0ec), + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), + + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), + + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), + VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004), + VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), + VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), + VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), + VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020), + VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034), + VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c), + VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054), + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c), + + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), + + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), + + VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), + VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), + VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), + VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), + VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), + VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), + VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), + VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), + VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), + VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), + VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), + VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), + VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), + + VC5_CSC_REG(HDMI_CSC_CTL, 0x000), + VC5_CSC_REG(HDMI_CSC_12_11, 0x004), + VC5_CSC_REG(HDMI_CSC_14_13, 0x008), + VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), +}; + static inline void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi, enum vc4_hdmi_regs reg) @@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi, case VC4_HDMI: return hdmi->hdmicore_regs; + case VC5_CSC: + return hdmi->csc_regs; + + case VC5_CEC: + return hdmi->cec_regs; + + case VC5_DVP: + return hdmi->dvp_regs; + + case VC5_PHY: + return hdmi->phy_regs; + + case VC5_RAM: + return hdmi->ram_regs; + + case VC5_RM: + return hdmi->rm_regs; + default: return NULL; } diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 30af52b406f1c..be2c32a519b31 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -744,6 +744,8 @@ # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) # define VC4_HD_CSC_CTL_ENABLE BIT(0) +# define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1) + /* HVS display list information. */ #define HVS_BOOTLOADER_DLIST_END 32 -- GitLab From 2e3725b05b785e73482a194b99bff3d5a1c85140 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:49 +0200 Subject: [PATCH 0926/1494] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings The HDMI controllers found in the BCM2711 SoC need some adjustments to the bindings, especially since the registers have been shuffled around in more register ranges. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Rob Herring <robh@kernel.org> Reviewed-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/ecd686e9b2335275bfb1ccfe1878305367b34bf3.1599120059.git-series.maxime@cerno.tech --- .../bindings/display/brcm,bcm2711-hdmi.yaml | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml new file mode 100644 index 0000000000000..03a76729d26cf --- /dev/null +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml @@ -0,0 +1,117 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/brcm,bcm2711-hdmi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings + +maintainers: + - Eric Anholt <eric@anholt.net> + +properties: + compatible: + enum: + - brcm,bcm2711-hdmi0 + - brcm,bcm2711-hdmi1 + + reg: + items: + - description: HDMI controller register range + - description: DVP register range + - description: HDMI PHY register range + - description: Rate Manager register range + - description: Packet RAM register range + - description: Metadata RAM register range + - description: CSC register range + - description: CEC register range + - description: HD register range + + reg-names: + items: + - const: hdmi + - const: dvp + - const: phy + - const: rm + - const: packet + - const: metadata + - const: csc + - const: cec + - const: hd + + clocks: + items: + - description: The HDMI state machine clock + - description: The Pixel BVB clock + - description: The HDMI Audio parent clock + - description: The HDMI CEC parent clock + + clock-names: + items: + - const: hdmi + - const: bvb + - const: audio + - const: cec + + ddc: + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + description: > + Phandle of the I2C controller used for DDC EDID probing + + hpd-gpios: + description: > + The GPIO pin for the HDMI hotplug detect (if it doesn't appear + as an interrupt/status bit in the HDMI controller itself) + + dmas: + maxItems: 1 + description: > + Should contain one entry pointing to the DMA channel used to + transfer audio data. + + dma-names: + const: audio-rx + + resets: + maxItems: 1 + +required: + - compatible + - reg + - reg-names + - clocks + - resets + - ddc + +additionalProperties: false + +examples: + - | + hdmi0: hdmi@7ef00700 { + compatible = "brcm,bcm2711-hdmi0"; + reg = <0x7ef00700 0x300>, + <0x7ef00300 0x200>, + <0x7ef00f00 0x80>, + <0x7ef00f80 0x80>, + <0x7ef01b00 0x200>, + <0x7ef01f00 0x400>, + <0x7ef00200 0x80>, + <0x7ef04300 0x100>, + <0x7ef20000 0x100>; + reg-names = "hdmi", + "dvp", + "phy", + "rm", + "packet", + "metadata", + "csc", + "cec", + "hd"; + clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; + clock-names = "hdmi", "bvb", "audio", "cec"; + resets = <&dvp 0>; + ddc = <&ddc0>; + }; + +... -- GitLab From b5d1443aa3264f6d035a5b6fc46d6ea232a0dfc7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:50 +0200 Subject: [PATCH 0927/1494] dt-bindings: display: vc4: Document BCM2711 VC5 The BCM2711 comes with a new VideoCore. Add a compatible for it. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Rob Herring <robh+dt@kernel.org> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/1075091c50b378505a9a89f760af11f0e1e26e5b.1599120059.git-series.maxime@cerno.tech --- Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml index 0dcf0c3973759..49a5e041aa493 100644 --- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml +++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml @@ -17,6 +17,7 @@ description: > properties: compatible: enum: + - brcm,bcm2711-vc5 - brcm,bcm2835-vc4 - brcm,cygnus-vc4 -- GitLab From f437bc1ec731d3c8e45daecec7d89fc82bb76d12 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 3 Sep 2020 10:01:51 +0200 Subject: [PATCH 0928/1494] drm/vc4: drv: Support BCM2711 The BCM2711 has a reworked display pipeline, and the load tracker needs some adjustment to operate properly. Let's add a compatible for BCM2711 and disable the load tracker until properly supported. Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Chanwoo Choi <cw00.choi@samsung.com> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/beac4f9ef0261bca731a0402c8354e9af740519c.1599120059.git-series.maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_drv.c | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 3 +++ drivers/gpu/drm/vc4/vc4_kms.c | 44 +++++++++++++++++++++++---------- drivers/gpu/drm/vc4/vc4_plane.c | 5 ++++ 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 9567d10192121..f1a5fd5dab6f5 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev) } static const struct of_device_id vc4_of_match[] = { + { .compatible = "brcm,bcm2711-vc5", }, { .compatible = "brcm,bcm2835-vc4", }, { .compatible = "brcm,cygnus-vc4", }, {}, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 501a48a714d3d..8c8d96b6289f4 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -200,6 +200,9 @@ struct vc4_dev { int power_refcount; + /* Set to true when the load tracker is supported. */ + bool load_tracker_available; + /* Set to true when the load tracker is active. */ bool load_tracker_enabled; diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index bfc7ddd49ac58..16e233e1406e9 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -536,6 +536,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state) struct drm_plane *plane; int i; + if (!vc4->load_tracker_available) + return 0; + priv_state = drm_atomic_get_private_obj_state(state, &vc4->load_tracker); if (IS_ERR(priv_state)) @@ -683,12 +686,18 @@ int vc4_kms_load(struct drm_device *dev) struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_ctm_state *ctm_state; struct vc4_load_tracker_state *load_state; + bool is_vc5 = of_device_is_compatible(dev->dev->of_node, + "brcm,bcm2711-vc5"); int ret; - /* Start with the load tracker enabled. Can be disabled through the - * debugfs load_tracker file. - */ - vc4->load_tracker_enabled = true; + if (!is_vc5) { + vc4->load_tracker_available = true; + + /* Start with the load tracker enabled. Can be + * disabled through the debugfs load_tracker file. + */ + vc4->load_tracker_enabled = true; + } sema_init(&vc4->async_modeset, 1); @@ -702,8 +711,14 @@ int vc4_kms_load(struct drm_device *dev) return ret; } - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; + if (is_vc5) { + dev->mode_config.max_width = 7680; + dev->mode_config.max_height = 7680; + } else { + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + } + dev->mode_config.funcs = &vc4_mode_funcs; dev->mode_config.preferred_depth = 24; dev->mode_config.async_page_flip = true; @@ -718,14 +733,17 @@ int vc4_kms_load(struct drm_device *dev) drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base, &vc4_ctm_state_funcs); - load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); - if (!load_state) { - drm_atomic_private_obj_fini(&vc4->ctm_manager); - return -ENOMEM; - } + if (vc4->load_tracker_available) { + load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); + if (!load_state) { + drm_atomic_private_obj_fini(&vc4->ctm_manager); + return -ENOMEM; + } - drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base, - &vc4_load_tracker_state_funcs); + drm_atomic_private_obj_init(dev, &vc4->load_tracker, + &load_state->base, + &vc4_load_tracker_state_funcs); + } drm_mode_config_reset(dev); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 1e38e603f83b9..24d7e6db6fdd2 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state) struct vc4_plane_state *vc4_state; struct drm_crtc_state *crtc_state; unsigned int vscale_factor; + struct vc4_dev *vc4; + + vc4 = to_vc4_dev(state->plane->dev); + if (!vc4->load_tracker_available) + return; vc4_state = to_vc4_plane_state(state); crtc_state = drm_atomic_get_existing_crtc_state(state->state, -- GitLab From 0a667b500703db80eb30759bb67df671641dbc5b Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 25 Aug 2020 09:46:00 +1000 Subject: [PATCH 0929/1494] drm/ttm: remove bdev from ttm_tt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I want to split this structure up and use it differently, step one remove bdev pointer from it and pass it explicitly. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200826014428.828392-4-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 40 +++++++++++-------- drivers/gpu/drm/drm_gem_vram_helper.c | 2 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 16 ++++---- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 8 ++-- drivers/gpu/drm/qxl/qxl_ttm.c | 9 +++-- drivers/gpu/drm/radeon/radeon_ttm.c | 40 ++++++++++--------- drivers/gpu/drm/ttm/ttm_agp_backend.c | 17 +++++--- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++-- drivers/gpu/drm/ttm/ttm_bo_util.c | 14 +++---- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +- drivers/gpu/drm/ttm/ttm_tt.c | 45 ++++++++++++---------- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 16 +++++--- include/drm/ttm/ttm_bo_driver.h | 7 ++-- include/drm/ttm/ttm_tt.h | 25 ++++++------ 15 files changed, 139 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 46d6208174828..ca568e25c41c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -565,7 +565,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, } /* Bind the memory to the GTT space */ - r = ttm_tt_bind(bo->ttm, &tmp_mem, ctx); + r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, ctx); if (unlikely(r)) { goto out_cleanup; } @@ -991,9 +991,10 @@ void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) * * Called by amdgpu_ttm_backend_bind() **/ -static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) +static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; int r; @@ -1027,9 +1028,10 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) /** * amdgpu_ttm_tt_unpin_userptr - Unpin and unmap userptr pages */ -static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) +static void amdgpu_ttm_tt_unpin_userptr(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); @@ -1110,16 +1112,17 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, * Called by ttm_tt_bind() on behalf of ttm_bo_handle_move_mem(). * This handles binding GTT memory to the device address space. */ -static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, +static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void*)ttm; uint64_t flags; int r = 0; if (gtt->userptr) { - r = amdgpu_ttm_tt_pin_userptr(ttm); + r = amdgpu_ttm_tt_pin_userptr(bdev, ttm); if (r) { DRM_ERROR("failed to pin userptr\n"); return r; @@ -1237,15 +1240,16 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) * Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and * ttm_tt_destroy(). */ -static void amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) +static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; int r; /* if the pages have userptr pinning then clear that first */ if (gtt->userptr) - amdgpu_ttm_tt_unpin_userptr(ttm); + amdgpu_ttm_tt_unpin_userptr(bdev, ttm); if (gtt->offset == AMDGPU_BO_INVALID_OFFSET) return; @@ -1257,7 +1261,8 @@ static void amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) gtt->ttm.ttm.num_pages, gtt->offset); } -static void amdgpu_ttm_backend_destroy(struct ttm_tt *ttm) +static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct amdgpu_ttm_tt *gtt = (void *)ttm; @@ -1307,10 +1312,11 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, * Map the pages of a ttm_tt object to an address space visible * to the underlying device. */ -static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, - struct ttm_operation_ctx *ctx) +static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx) { - struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ @@ -1361,7 +1367,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, * Unmaps pages of a ttm_tt object from the device address space and * unpopulates the page array backing it. */ -static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) +static void amdgpu_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct amdgpu_ttm_tt *gtt = (void *)ttm; struct amdgpu_device *adev; @@ -1385,7 +1391,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) if (ttm->page_flags & TTM_PAGE_FLAG_SG) return; - adev = amdgpu_ttm_adev(ttm->bdev); + adev = amdgpu_ttm_adev(bdev); #ifdef CONFIG_SWIOTLB if (adev->need_swiotlb && swiotlb_nr_tbl()) { diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 545a877406f45..788557bc5c010 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -967,7 +967,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { * TTM TT */ -static void backend_func_destroy(struct ttm_tt *tt) +static void backend_func_destroy(struct ttm_bo_device *bdev, struct ttm_tt *tt) { ttm_tt_fini(tt); kfree(tt); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index f74988771ed84..41aa7ac31bd53 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -848,7 +848,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) return ret; - ret = ttm_tt_bind(bo->ttm, &tmp_reg, &ctx); + ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg, &ctx); if (ret) goto out; @@ -1219,7 +1219,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) } static int -nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) +nouveau_ttm_tt_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; @@ -1237,12 +1238,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) return 0; } - drm = nouveau_bdev(ttm->bdev); + drm = nouveau_bdev(bdev); dev = drm->dev->dev; #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { - return ttm_agp_tt_populate(ttm, ctx); + return ttm_agp_tt_populate(bdev, ttm, ctx); } #endif @@ -1255,7 +1256,8 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) } static void -nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) +nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; @@ -1265,12 +1267,12 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) if (slave) return; - drm = nouveau_bdev(ttm->bdev); + drm = nouveau_bdev(bdev); dev = drm->dev->dev; #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { - ttm_agp_tt_unpopulate(ttm); + ttm_agp_tt_unpopulate(bdev, ttm); return; } #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index eef75c53a1971..6000c650b1058 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -15,7 +15,7 @@ struct nouveau_sgdma_be { }; static void -nouveau_sgdma_destroy(struct ttm_tt *ttm) +nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; @@ -26,7 +26,7 @@ nouveau_sgdma_destroy(struct ttm_tt *ttm) } static int -nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_resource *reg) +nv04_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct nouveau_mem *mem = nouveau_mem(reg); @@ -47,7 +47,7 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_resource *reg) } static void -nv04_sgdma_unbind(struct ttm_tt *ttm) +nv04_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; nouveau_mem_fini(nvbe->mem); @@ -60,7 +60,7 @@ static struct ttm_backend_func nv04_sgdma_backend = { }; static int -nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_resource *reg) +nv50_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct nouveau_mem *mem = nouveau_mem(reg); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 7aae0a96f043e..3ab4603391453 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -104,7 +104,8 @@ struct qxl_ttm_tt { u64 offset; }; -static int qxl_ttm_backend_bind(struct ttm_tt *ttm, +static int qxl_ttm_backend_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct qxl_ttm_tt *gtt = (void *)ttm; @@ -118,12 +119,14 @@ static int qxl_ttm_backend_bind(struct ttm_tt *ttm, return -1; } -static void qxl_ttm_backend_unbind(struct ttm_tt *ttm) +static void qxl_ttm_backend_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { /* Not implemented */ } -static void qxl_ttm_backend_destroy(struct ttm_tt *ttm) +static void qxl_ttm_backend_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct qxl_ttm_tt *gtt = (void *)ttm; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 74ad50c7491c1..a8d6ca88c6e3b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -244,7 +244,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, goto out_cleanup; } - r = ttm_tt_bind(bo->ttm, &tmp_mem, &ctx); + r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, &ctx); if (unlikely(r)) { goto out_cleanup; } @@ -430,9 +430,9 @@ struct radeon_ttm_tt { }; /* prepare the sg table with the user pages */ -static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm) +static int radeon_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); + struct radeon_device *rdev = radeon_get_rdev(bdev); struct radeon_ttm_tt *gtt = (void *)ttm; unsigned pinned = 0; int r; @@ -491,9 +491,9 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm) return r; } -static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm) +static void radeon_ttm_tt_unpin_userptr(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); + struct radeon_device *rdev = radeon_get_rdev(bdev); struct radeon_ttm_tt *gtt = (void *)ttm; struct sg_page_iter sg_iter; @@ -520,17 +520,18 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_tt *ttm) sg_free_table(ttm->sg); } -static int radeon_ttm_backend_bind(struct ttm_tt *ttm, +static int radeon_ttm_backend_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct radeon_ttm_tt *gtt = (void*)ttm; - struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); + struct radeon_device *rdev = radeon_get_rdev(bdev); uint32_t flags = RADEON_GART_PAGE_VALID | RADEON_GART_PAGE_READ | RADEON_GART_PAGE_WRITE; int r; if (gtt->userptr) { - radeon_ttm_tt_pin_userptr(ttm); + radeon_ttm_tt_pin_userptr(bdev, ttm); flags &= ~RADEON_GART_PAGE_WRITE; } @@ -551,18 +552,18 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm, return 0; } -static void radeon_ttm_backend_unbind(struct ttm_tt *ttm) +static void radeon_ttm_backend_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct radeon_ttm_tt *gtt = (void *)ttm; - struct radeon_device *rdev = radeon_get_rdev(ttm->bdev); + struct radeon_device *rdev = radeon_get_rdev(bdev); radeon_gart_unbind(rdev, gtt->offset, ttm->num_pages); if (gtt->userptr) - radeon_ttm_tt_unpin_userptr(ttm); + radeon_ttm_tt_unpin_userptr(bdev, ttm); } -static void radeon_ttm_backend_destroy(struct ttm_tt *ttm) +static void radeon_ttm_backend_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct radeon_ttm_tt *gtt = (void *)ttm; @@ -609,8 +610,9 @@ static struct radeon_ttm_tt *radeon_ttm_tt_to_gtt(struct ttm_tt *ttm) return (struct radeon_ttm_tt *)ttm; } -static int radeon_ttm_tt_populate(struct ttm_tt *ttm, - struct ttm_operation_ctx *ctx) +static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx) { struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); struct radeon_device *rdev; @@ -633,10 +635,10 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm, return 0; } - rdev = radeon_get_rdev(ttm->bdev); + rdev = radeon_get_rdev(bdev); #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { - return ttm_agp_tt_populate(ttm, ctx); + return ttm_agp_tt_populate(bdev, ttm, ctx); } #endif @@ -649,7 +651,7 @@ static int radeon_ttm_tt_populate(struct ttm_tt *ttm, return ttm_populate_and_map_pages(rdev->dev, >t->ttm, ctx); } -static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) +static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct radeon_device *rdev; struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); @@ -664,10 +666,10 @@ static void radeon_ttm_tt_unpopulate(struct ttm_tt *ttm) if (slave) return; - rdev = radeon_get_rdev(ttm->bdev); + rdev = radeon_get_rdev(bdev); #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { - ttm_agp_tt_unpopulate(ttm); + ttm_agp_tt_unpopulate(bdev, ttm); return; } #endif diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 09fe80e215c58..934a694915478 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -48,7 +48,8 @@ struct ttm_agp_backend { struct agp_bridge_data *bridge; }; -static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) +static int ttm_agp_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); struct page *dummy_read_page = ttm_bo_glob.dummy_read_page; @@ -82,7 +83,8 @@ static int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) return ret; } -static void ttm_agp_unbind(struct ttm_tt *ttm) +static void ttm_agp_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); @@ -96,12 +98,13 @@ static void ttm_agp_unbind(struct ttm_tt *ttm) } } -static void ttm_agp_destroy(struct ttm_tt *ttm) +static void ttm_agp_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); if (agp_be->mem) - ttm_agp_unbind(ttm); + ttm_agp_unbind(bdev, ttm); ttm_tt_fini(ttm); kfree(agp_be); } @@ -135,7 +138,8 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_agp_tt_create); -int ttm_agp_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) +int ttm_agp_tt_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { if (ttm->state != tt_unpopulated) return 0; @@ -144,7 +148,8 @@ int ttm_agp_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) } EXPORT_SYMBOL(ttm_agp_tt_populate); -void ttm_agp_tt_unpopulate(struct ttm_tt *ttm) +void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { ttm_pool_unpopulate(ttm); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 89d8ab6edd40f..55f995bca661e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -282,7 +282,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err; if (mem->mem_type != TTM_PL_SYSTEM) { - ret = ttm_tt_bind(bo->ttm, mem, ctx); + ret = ttm_tt_bind(bdev, bo->ttm, mem, ctx); if (ret) goto out_err; } @@ -324,7 +324,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, out_err: new_man = ttm_manager_type(bdev, bo->mem.mem_type); if (!new_man->use_tt) { - ttm_tt_destroy(bo->ttm); + ttm_tt_destroy(bdev, bo->ttm); bo->ttm = NULL; } @@ -344,7 +344,7 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) if (bo->bdev->driver->move_notify) bo->bdev->driver->move_notify(bo, false, NULL); - ttm_tt_destroy(bo->ttm); + ttm_tt_destroy(bo->bdev, bo->ttm); bo->ttm = NULL; ttm_resource_free(bo, &bo->mem); } @@ -1656,7 +1656,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) if (bo->bdev->driver->swap_notify) bo->bdev->driver->swap_notify(bo); - ret = ttm_tt_swapout(bo->ttm, bo->persistent_swap_storage); + ret = ttm_tt_swapout(bo->bdev, bo->ttm, bo->persistent_swap_storage); out: /** diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 2c967607d4853..6f527d71576ae 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -67,7 +67,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, return ret; } - ttm_tt_unbind(ttm); + ttm_tt_unbind(bo->bdev, ttm); ttm_bo_free_old_node(bo); ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM, TTM_PL_MASK_MEM); @@ -79,7 +79,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, return ret; if (new_mem->mem_type != TTM_PL_SYSTEM) { - ret = ttm_tt_bind(ttm, new_mem, ctx); + ret = ttm_tt_bind(bo->bdev, ttm, new_mem, ctx); if (unlikely(ret != 0)) return ret; } @@ -264,7 +264,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, * TTM might be null for moves within the same region. */ if (ttm) { - ret = ttm_tt_populate(ttm, ctx); + ret = ttm_tt_populate(bdev, ttm, ctx); if (ret) goto out1; } @@ -303,7 +303,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, new_mem->mm_node = NULL; if (!man->use_tt) { - ttm_tt_destroy(ttm); + ttm_tt_destroy(bdev, ttm); bo->ttm = NULL; } @@ -454,7 +454,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, BUG_ON(!ttm); - ret = ttm_tt_populate(ttm, &ctx); + ret = ttm_tt_populate(bo->bdev, ttm, &ctx); if (ret) return ret; @@ -550,7 +550,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, return ret; if (!man->use_tt) { - ttm_tt_destroy(bo->ttm); + ttm_tt_destroy(bdev, bo->ttm); bo->ttm = NULL; } ttm_bo_free_old_node(bo); @@ -673,7 +673,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, return ret; if (!to->use_tt) { - ttm_tt_destroy(bo->ttm); + ttm_tt_destroy(bdev, bo->ttm); bo->ttm = NULL; } ttm_bo_free_old_node(bo); diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index d3dc0682425c4..bb96f819f6078 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -341,7 +341,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, }; ttm = bo->ttm; - if (ttm_tt_populate(bo->ttm, &ctx)) + if (ttm_tt_populate(bdev, bo->ttm, &ctx)) return VM_FAULT_OOM; } else { /* Iomem should not be marked encrypted */ diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 1ccf1ef050d6c..50a8991040220 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -207,29 +207,28 @@ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement) } EXPORT_SYMBOL(ttm_tt_set_placement_caching); -void ttm_tt_destroy(struct ttm_tt *ttm) +void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { if (ttm == NULL) return; - ttm_tt_unbind(ttm); + ttm_tt_unbind(bdev, ttm); if (ttm->state == tt_unbound) - ttm_tt_unpopulate(ttm); + ttm_tt_unpopulate(bdev, ttm); if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && ttm->swap_storage) fput(ttm->swap_storage); ttm->swap_storage = NULL; - ttm->func->destroy(ttm); + ttm->func->destroy(bdev, ttm); } static void ttm_tt_init_fields(struct ttm_tt *ttm, struct ttm_buffer_object *bo, uint32_t page_flags) { - ttm->bdev = bo->bdev; ttm->num_pages = bo->num_pages; ttm->caching_state = tt_cached; ttm->page_flags = page_flags; @@ -308,15 +307,16 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma) } EXPORT_SYMBOL(ttm_dma_tt_fini); -void ttm_tt_unbind(struct ttm_tt *ttm) +void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { if (ttm->state == tt_bound) { - ttm->func->unbind(ttm); + ttm->func->unbind(bdev, ttm); ttm->state = tt_unbound; } } -int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, +int ttm_tt_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem, struct ttm_operation_ctx *ctx) { int ret = 0; @@ -327,11 +327,11 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, if (ttm->state == tt_bound) return 0; - ret = ttm_tt_populate(ttm, ctx); + ret = ttm_tt_populate(bdev, ttm, ctx); if (ret) return ret; - ret = ttm->func->bind(ttm, bo_mem); + ret = ttm->func->bind(bdev, ttm, bo_mem); if (unlikely(ret != 0)) return ret; @@ -383,7 +383,8 @@ int ttm_tt_swapin(struct ttm_tt *ttm) return ret; } -int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) +int ttm_tt_swapout(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct file *persistent_swap_storage) { struct address_space *swap_space; struct file *swap_storage; @@ -429,7 +430,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) put_page(to_page); } - ttm_tt_unpopulate(ttm); + ttm_tt_unpopulate(bdev, ttm); ttm->swap_storage = swap_storage; ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; if (persistent_swap_storage) @@ -443,7 +444,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) return ret; } -static void ttm_tt_add_mapping(struct ttm_tt *ttm) +static void ttm_tt_add_mapping(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { pgoff_t i; @@ -451,22 +452,23 @@ static void ttm_tt_add_mapping(struct ttm_tt *ttm) return; for (i = 0; i < ttm->num_pages; ++i) - ttm->pages[i]->mapping = ttm->bdev->dev_mapping; + ttm->pages[i]->mapping = bdev->dev_mapping; } -int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) +int ttm_tt_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { int ret; if (ttm->state != tt_unpopulated) return 0; - if (ttm->bdev->driver->ttm_tt_populate) - ret = ttm->bdev->driver->ttm_tt_populate(ttm, ctx); + if (bdev->driver->ttm_tt_populate) + ret = bdev->driver->ttm_tt_populate(bdev, ttm, ctx); else ret = ttm_pool_populate(ttm, ctx); if (!ret) - ttm_tt_add_mapping(ttm); + ttm_tt_add_mapping(bdev, ttm); return ret; } @@ -484,14 +486,15 @@ static void ttm_tt_clear_mapping(struct ttm_tt *ttm) } } -void ttm_tt_unpopulate(struct ttm_tt *ttm) +void ttm_tt_unpopulate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { if (ttm->state == tt_unpopulated) return; ttm_tt_clear_mapping(ttm); - if (ttm->bdev->driver->ttm_tt_unpopulate) - ttm->bdev->driver->ttm_tt_unpopulate(ttm); + if (bdev->driver->ttm_tt_unpopulate) + bdev->driver->ttm_tt_unpopulate(bdev, ttm); else ttm_pool_unpopulate(ttm); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index 1629427d5734a..0cd21590ded9e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -465,13 +465,13 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, dma_resv_assert_held(src->base.resv); if (dst->ttm->state == tt_unpopulated) { - ret = dst->ttm->bdev->driver->ttm_tt_populate(dst->ttm, &ctx); + ret = dst->bdev->driver->ttm_tt_populate(dst->bdev, dst->ttm, &ctx); if (ret) return ret; } if (src->ttm->state == tt_unpopulated) { - ret = src->ttm->bdev->driver->ttm_tt_populate(src->ttm, &ctx); + ret = src->bdev->driver->ttm_tt_populate(src->bdev, src->ttm, &ctx); if (ret) return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index c7f10b2c93d22..a76a7f542dd8c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -539,7 +539,8 @@ const struct vmw_sg_table *vmw_bo_sg_table(struct ttm_buffer_object *bo) } -static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) +static int vmw_ttm_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -573,7 +574,8 @@ static int vmw_ttm_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) return 0; } -static void vmw_ttm_unbind(struct ttm_tt *ttm) +static void vmw_ttm_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -594,7 +596,7 @@ static void vmw_ttm_unbind(struct ttm_tt *ttm) } -static void vmw_ttm_destroy(struct ttm_tt *ttm) +static void vmw_ttm_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -612,7 +614,8 @@ static void vmw_ttm_destroy(struct ttm_tt *ttm) } -static int vmw_ttm_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) +static int vmw_ttm_populate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -640,7 +643,8 @@ static int vmw_ttm_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) return ret; } -static void vmw_ttm_unpopulate(struct ttm_tt *ttm) +static void vmw_ttm_unpopulate(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); @@ -796,7 +800,7 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv, ret = ttm_bo_reserve(bo, false, true, NULL); BUG_ON(ret != 0); - ret = vmw_ttm_populate(bo->ttm, &ctx); + ret = vmw_ttm_populate(bo->bdev, bo->ttm, &ctx); if (likely(ret == 0)) { struct vmw_ttm_tt *vmw_tt = container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm.ttm); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 9744ed9d677ec..a694388f7b13c 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -77,8 +77,9 @@ struct ttm_bo_driver { * Returns: * -ENOMEM: Out of memory. */ - int (*ttm_tt_populate)(struct ttm_tt *ttm, - struct ttm_operation_ctx *ctx); + int (*ttm_tt_populate)(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_operation_ctx *ctx); /** * ttm_tt_unpopulate @@ -87,7 +88,7 @@ struct ttm_bo_driver { * * Free all backing page */ - void (*ttm_tt_unpopulate)(struct ttm_tt *ttm); + void (*ttm_tt_unpopulate)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * struct ttm_bo_driver member eviction_valuable diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 241cc40839ed8..6bda88f8da46a 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -60,7 +60,7 @@ struct ttm_backend_func { * indicated by @bo_mem. This function should be able to handle * differences between aperture and system page sizes. */ - int (*bind) (struct ttm_tt *ttm, struct ttm_resource *bo_mem); + int (*bind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); /** * struct ttm_backend_func member unbind @@ -70,7 +70,7 @@ struct ttm_backend_func { * Unbind previously bound backend pages. This function should be * able to handle differences between aperture and system page sizes. */ - void (*unbind) (struct ttm_tt *ttm); + void (*unbind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * struct ttm_backend_func member destroy @@ -80,13 +80,12 @@ struct ttm_backend_func { * Destroy the backend. This will be call back from ttm_tt_destroy so * don't call ttm_tt_destroy from the callback or infinite loop. */ - void (*destroy) (struct ttm_tt *ttm); + void (*destroy) (struct ttm_bo_device *bdev, struct ttm_tt *ttm); }; /** * struct ttm_tt * - * @bdev: Pointer to a struct ttm_bo_device. * @func: Pointer to a struct ttm_backend_func that describes * the backend methods. * pointer. @@ -103,7 +102,6 @@ struct ttm_backend_func { * memory. */ struct ttm_tt { - struct ttm_bo_device *bdev; struct ttm_backend_func *func; struct page **pages; uint32_t page_flags; @@ -183,7 +181,8 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); * * Bind the pages of @ttm to an aperture location identified by @bo_mem */ -int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, +int ttm_tt_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem, struct ttm_operation_ctx *ctx); /** @@ -193,7 +192,7 @@ int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem, * * Unbind, unpopulate and destroy common struct ttm_tt. */ -void ttm_tt_destroy(struct ttm_tt *ttm); +void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * ttm_ttm_unbind: @@ -202,7 +201,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm); * * Unbind a struct ttm_tt. */ -void ttm_tt_unbind(struct ttm_tt *ttm); +void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm); /** * ttm_tt_swapin: @@ -227,7 +226,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm); * and cache flushes and potential page splitting / combining. */ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement); -int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage); +int ttm_tt_swapout(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct file *persistent_swap_storage); /** * ttm_tt_populate - allocate pages for a ttm @@ -236,7 +235,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage); * * Calls the driver method to allocate pages for a ttm */ -int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); +int ttm_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); /** * ttm_tt_unpopulate - free pages from a ttm @@ -245,7 +244,7 @@ int ttm_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); * * Calls the driver method to free all pages from a ttm */ -void ttm_tt_unpopulate(struct ttm_tt *ttm); +void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); #if IS_ENABLED(CONFIG_AGP) #include <linux/agp_backend.h> @@ -265,8 +264,8 @@ void ttm_tt_unpopulate(struct ttm_tt *ttm); struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, struct agp_bridge_data *bridge, uint32_t page_flags); -int ttm_agp_tt_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); -void ttm_agp_tt_unpopulate(struct ttm_tt *ttm); +int ttm_agp_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); +void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); #endif #endif -- GitLab From 953025763d1421605939479b2e9c070f03e428c1 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Date: Sun, 30 Aug 2020 10:19:58 -0400 Subject: [PATCH 0930/1494] drm/vkms: Decouple crc operations from composer In the vkms_composer.c, some of the functions related to CRC and compose have interdependence between each other. This patch reworks some functions inside vkms_composer to make crc and composer computation decoupled. This patch is preparation work for making vkms able to support new features. Tested-by: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Reviewed-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-2-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 49 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index eaecc5a6c5dba..f67d1baf1942c 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -131,35 +131,31 @@ static void compose_cursor(struct vkms_composer *cursor_composer, primary_composer, cursor_composer); } -static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer, - struct vkms_composer *cursor_composer) +static int compose_planes(void **vaddr_out, + struct vkms_composer *primary_composer, + struct vkms_composer *cursor_composer) { struct drm_framebuffer *fb = &primary_composer->fb; struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj); - void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL); - u32 crc = 0; - if (!vaddr_out) { - DRM_ERROR("Failed to allocate memory for output frame."); - return 0; + if (!*vaddr_out) { + *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL); + if (!*vaddr_out) { + DRM_ERROR("Cannot allocate memory for output frame."); + return -ENOMEM; + } } - if (WARN_ON(!vkms_obj->vaddr)) { - kfree(vaddr_out); - return crc; - } + if (WARN_ON(!vkms_obj->vaddr)) + return -EINVAL; - memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size); + memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size); if (cursor_composer) - compose_cursor(cursor_composer, primary_composer, vaddr_out); + compose_cursor(cursor_composer, primary_composer, *vaddr_out); - crc = compute_crc(vaddr_out, primary_composer); - - kfree(vaddr_out); - - return crc; + return 0; } /** @@ -180,9 +176,11 @@ void vkms_composer_worker(struct work_struct *work) struct vkms_output *out = drm_crtc_to_vkms_output(crtc); struct vkms_composer *primary_composer = NULL; struct vkms_composer *cursor_composer = NULL; + void *vaddr_out = NULL; u32 crc32 = 0; u64 frame_start, frame_end; bool crc_pending; + int ret; spin_lock_irq(&out->composer_lock); frame_start = crtc_state->frame_start; @@ -206,14 +204,25 @@ void vkms_composer_worker(struct work_struct *work) if (crtc_state->num_active_planes == 2) cursor_composer = crtc_state->active_planes[1]->composer; - if (primary_composer) - crc32 = _vkms_get_crc(primary_composer, cursor_composer); + if (!primary_composer) + return; + + ret = compose_planes(&vaddr_out, primary_composer, cursor_composer); + if (ret) { + if (ret == -EINVAL) + kfree(vaddr_out); + return; + } + + crc32 = compute_crc(vaddr_out, primary_composer); /* * The worker can fall behind the vblank hrtimer, make sure we catch up. */ while (frame_start <= frame_end) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); + + kfree(vaddr_out); } static const char * const pipe_crc_sources[] = {"auto"}; -- GitLab From 60cc20214cedaa5128005a6ccf38c4f37242cf5b Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Date: Sun, 30 Aug 2020 10:19:59 -0400 Subject: [PATCH 0931/1494] drm/vkms: Compute CRC without change input data This commit decouples pixel manipulation from compute_crc() for avoiding any pixel change during the CRC calculation. This commits represents a preparation work for making VKMS able to support the writeback feature. Change in V5 (Melissa): - Rebase and drop bitmap for alpha Change in V4 (Emil): - Move bitmap_clear operation and comments to get_pixel function Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Reviewed-by: Melissa Wen <melissa.srw@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-3-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/vkms_composer.c | 34 ++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index f67d1baf1942c..c5b32fe5870fa 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -9,31 +9,41 @@ #include "vkms_drv.h" +static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer, + const struct vkms_composer *composer) +{ + u32 pixel; + int src_offset = composer->offset + (y * composer->pitch) + + (x * composer->cpp); + + pixel = *(u32 *)&buffer[src_offset]; + + return pixel; +} + /** * compute_crc - Compute CRC value on output frame * - * @vaddr_out: address to final framebuffer + * @vaddr: address to final framebuffer * @composer: framebuffer's metadata * * returns CRC value computed using crc32 on the visible portion of * the final framebuffer at vaddr_out */ -static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) +static uint32_t compute_crc(const u8 *vaddr, + const struct vkms_composer *composer) { - int i, j, src_offset; + int x, y; + u32 crc = 0, pixel = 0; int x_src = composer->src.x1 >> 16; int y_src = composer->src.y1 >> 16; int h_src = drm_rect_height(&composer->src) >> 16; int w_src = drm_rect_width(&composer->src) >> 16; - u32 crc = 0; - - for (i = y_src; i < y_src + h_src; ++i) { - for (j = x_src; j < x_src + w_src; ++j) { - src_offset = composer->offset - + (i * composer->pitch) - + (j * composer->cpp); - crc = crc32_le(crc, vaddr_out + src_offset, - sizeof(u32)); + + for (y = y_src; y < y_src + h_src; ++y) { + for (x = x_src; x < x_src + w_src; ++x) { + pixel = get_pixel_from_buffer(x, y, vaddr, composer); + crc = crc32_le(crc, (void *)&pixel, sizeof(u32)); } } -- GitLab From dbd9d80c1b2e033d5ec2d00add89a4f18f6899eb Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Date: Sun, 30 Aug 2020 10:20:00 -0400 Subject: [PATCH 0932/1494] drm/vkms: Add support for writeback This patch implements the necessary functions to add writeback support for vkms. This feature is useful for testing compositors if you don't have hardware with writeback support. Change in V4 (Emil and Melissa): - Move signal completion above drm_crtc_add_crc_entry() - Make writeback always available - Use appropriate namespace - Drop fb check in vkms_wb_atomic_commit - Make vkms_set_composer visible for writeback code - Enable composer operation on prepare_job and disable it on cleanup_job - Drop extra space at the end of the file - Rebase Change in V3 (Daniel): - If writeback is enabled, compose everything into the writeback buffer instead of CRC private buffer - Guarantees that the CRC will match exactly what we have in the writeback buffer. Change in V2: - Rework signal completion (Brian) - Integrates writeback with active_planes (Daniel) - Compose cursor (Daniel) Signed-off-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200830142000.146706-4-rodrigosiqueiramelo@gmail.com --- drivers/gpu/drm/vkms/Makefile | 9 +- drivers/gpu/drm/vkms/vkms_composer.c | 21 +++- drivers/gpu/drm/vkms/vkms_drv.h | 10 +- drivers/gpu/drm/vkms/vkms_output.c | 4 + drivers/gpu/drm/vkms/vkms_writeback.c | 142 ++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 0b767d7efa24b..333d3cead0e38 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,4 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only -vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_composer.o +vkms-y := \ + vkms_drv.o \ + vkms_plane.o \ + vkms_output.o \ + vkms_crtc.o \ + vkms_gem.o \ + vkms_composer.o \ + vkms_writeback.o obj-$(CONFIG_DRM_VKMS) += vkms.o diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index c5b32fe5870fa..33c031f27c2c1 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -186,16 +186,17 @@ void vkms_composer_worker(struct work_struct *work) struct vkms_output *out = drm_crtc_to_vkms_output(crtc); struct vkms_composer *primary_composer = NULL; struct vkms_composer *cursor_composer = NULL; + bool crc_pending, wb_pending; void *vaddr_out = NULL; u32 crc32 = 0; u64 frame_start, frame_end; - bool crc_pending; int ret; spin_lock_irq(&out->composer_lock); frame_start = crtc_state->frame_start; frame_end = crtc_state->frame_end; crc_pending = crtc_state->crc_pending; + wb_pending = crtc_state->wb_pending; crtc_state->frame_start = 0; crtc_state->frame_end = 0; crtc_state->crc_pending = false; @@ -217,22 +218,32 @@ void vkms_composer_worker(struct work_struct *work) if (!primary_composer) return; + if (wb_pending) + vaddr_out = crtc_state->active_writeback; + ret = compose_planes(&vaddr_out, primary_composer, cursor_composer); if (ret) { - if (ret == -EINVAL) + if (ret == -EINVAL && !wb_pending) kfree(vaddr_out); return; } crc32 = compute_crc(vaddr_out, primary_composer); + if (wb_pending) { + drm_writeback_signal_completion(&out->wb_connector, 0); + spin_lock_irq(&out->composer_lock); + crtc_state->wb_pending = false; + spin_unlock_irq(&out->composer_lock); + } else { + kfree(vaddr_out); + } + /* * The worker can fall behind the vblank hrtimer, make sure we catch up. */ while (frame_start <= frame_end) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); - - kfree(vaddr_out); } static const char * const pipe_crc_sources[] = {"auto"}; @@ -275,7 +286,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *src_name, return 0; } -static void vkms_set_composer(struct vkms_output *out, bool enabled) +void vkms_set_composer(struct vkms_output *out, bool enabled) { bool old_enabled; diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index f4036bb0b9a89..380a8f27e1560 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -8,6 +8,7 @@ #include <drm/drm.h> #include <drm/drm_gem.h> #include <drm/drm_encoder.h> +#include <drm/drm_writeback.h> #define XRES_MIN 20 #define YRES_MIN 20 @@ -52,9 +53,11 @@ struct vkms_crtc_state { int num_active_planes; /* stack of active planes for crc computation, should be in z order */ struct vkms_plane_state **active_planes; + void *active_writeback; - /* below three are protected by vkms_output.composer_lock */ + /* below four are protected by vkms_output.composer_lock */ bool crc_pending; + bool wb_pending; u64 frame_start; u64 frame_end; }; @@ -63,6 +66,7 @@ struct vkms_output { struct drm_crtc crtc; struct drm_encoder encoder; struct drm_connector connector; + struct drm_writeback_connector wb_connector; struct hrtimer vblank_hrtimer; ktime_t period_ns; struct drm_pending_vblank_event *event; @@ -143,5 +147,9 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, /* Composer Support */ void vkms_composer_worker(struct work_struct *work); +void vkms_set_composer(struct vkms_output *out, bool enabled); + +/* Writeback */ +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev); #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 85afb77e97f0e..4a1848b0318fb 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -80,6 +80,10 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index) goto err_attach; } + ret = vkms_enable_writeback_connector(vkmsdev); + if (ret) + DRM_ERROR("Failed to init writeback connector\n"); + drm_mode_config_reset(dev); return 0; diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c new file mode 100644 index 0000000000000..094fa4aa061d0 --- /dev/null +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "vkms_drv.h" +#include <drm/drm_fourcc.h> +#include <drm/drm_writeback.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> + +static const u32 vkms_wb_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const struct drm_connector_funcs vkms_wb_connector_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .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 int vkms_wb_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct drm_framebuffer *fb; + const struct drm_display_mode *mode = &crtc_state->mode; + + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) + return 0; + + fb = conn_state->writeback_job->fb; + if (fb->width != mode->hdisplay || fb->height != mode->vdisplay) { + DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n", + fb->width, fb->height); + return -EINVAL; + } + + if (fb->format->format != vkms_wb_formats[0]) { + struct drm_format_name_buf format_name; + + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(fb->format->format, + &format_name)); + return -EINVAL; + } + + return 0; +} + +static const struct drm_encoder_helper_funcs vkms_wb_encoder_helper_funcs = { + .atomic_check = vkms_wb_encoder_atomic_check, +}; + +static int vkms_wb_connector_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + + return drm_add_modes_noedid(connector, dev->mode_config.max_width, + dev->mode_config.max_height); +} + +static int vkms_wb_prepare_job(struct drm_writeback_connector *wb_connector, + struct drm_writeback_job *job) +{ + struct vkms_gem_object *vkms_obj; + struct drm_gem_object *gem_obj; + int ret; + + if (!job->fb) + return 0; + + gem_obj = drm_gem_fb_get_obj(job->fb, 0); + ret = vkms_gem_vmap(gem_obj); + if (ret) { + DRM_ERROR("vmap failed: %d\n", ret); + return ret; + } + + vkms_obj = drm_gem_to_vkms_gem(gem_obj); + job->priv = vkms_obj->vaddr; + + return 0; +} + +static void vkms_wb_cleanup_job(struct drm_writeback_connector *connector, + struct drm_writeback_job *job) +{ + struct drm_gem_object *gem_obj; + struct vkms_device *vkmsdev; + + if (!job->fb) + return; + + gem_obj = drm_gem_fb_get_obj(job->fb, 0); + vkms_gem_vunmap(gem_obj); + + vkmsdev = drm_device_to_vkms_device(gem_obj->dev); + vkms_set_composer(&vkmsdev->output, false); +} + +static void vkms_wb_atomic_commit(struct drm_connector *conn, + struct drm_connector_state *state) +{ + struct vkms_device *vkmsdev = drm_device_to_vkms_device(conn->dev); + struct vkms_output *output = &vkmsdev->output; + struct drm_writeback_connector *wb_conn = &output->wb_connector; + struct drm_connector_state *conn_state = wb_conn->base.state; + struct vkms_crtc_state *crtc_state = output->composer_state; + + if (!conn_state) + return; + + vkms_set_composer(&vkmsdev->output, true); + + spin_lock_irq(&output->composer_lock); + crtc_state->active_writeback = conn_state->writeback_job->priv; + crtc_state->wb_pending = true; + spin_unlock_irq(&output->composer_lock); + drm_writeback_queue_job(wb_conn, state); +} + +static const struct drm_connector_helper_funcs vkms_wb_conn_helper_funcs = { + .get_modes = vkms_wb_connector_get_modes, + .prepare_writeback_job = vkms_wb_prepare_job, + .cleanup_writeback_job = vkms_wb_cleanup_job, + .atomic_commit = vkms_wb_atomic_commit, +}; + +int vkms_enable_writeback_connector(struct vkms_device *vkmsdev) +{ + struct drm_writeback_connector *wb = &vkmsdev->output.wb_connector; + + vkmsdev->output.wb_connector.encoder.possible_crtcs = 1; + drm_connector_helper_add(&wb->base, &vkms_wb_conn_helper_funcs); + + return drm_writeback_connector_init(&vkmsdev->drm, wb, + &vkms_wb_connector_funcs, + &vkms_wb_encoder_helper_funcs, + vkms_wb_formats, + ARRAY_SIZE(vkms_wb_formats)); +} -- GitLab From 25c4bcf9858e3e8752985fa0cda64a212ea328b7 Mon Sep 17 00:00:00 2001 From: Neil Armstrong <narmstrong@baylibre.com> Date: Mon, 7 Sep 2020 12:27:11 +0200 Subject: [PATCH 0933/1494] drm/bridge: dw-mipi-dsi: fix dw_mipi_dsi_debugfs_show/write warnings This fixes the following warnings while building in W=1 : dw-mipi-dsi.c:1002:5: warning: no previous prototype for 'dw_mipi_dsi_debugfs_write' [-Wmissing-prototypes] dw-mipi-dsi.c:1027:5: warning: no previous prototype for 'dw_mipi_dsi_debugfs_show' [-Wmissing-prototypes] Fixes: e2435d69204c ("drm/bridge: dw-mipi-dsi.c: Add VPG runtime config through debugfs") Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Angelo Ribeiro <angelo.ribeiro@synopsys.com> Cc: Maxime Ripard <maxime@cerno.tech> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200907102711.23748-1-narmstrong@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 0b3825a4fbdb5..52f5c5a2ed647 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -999,7 +999,7 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = { #ifdef CONFIG_DEBUG_FS -int dw_mipi_dsi_debugfs_write(void *data, u64 val) +static int dw_mipi_dsi_debugfs_write(void *data, u64 val) { struct debugfs_entries *vpg = data; struct dw_mipi_dsi *dsi; @@ -1024,7 +1024,7 @@ int dw_mipi_dsi_debugfs_write(void *data, u64 val) return 0; } -int dw_mipi_dsi_debugfs_show(void *data, u64 *val) +static int dw_mipi_dsi_debugfs_show(void *data, u64 *val) { struct debugfs_entries *vpg = data; -- GitLab From 1ff67ce49875f289d63e426b63c6561aa63fa888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 7 Sep 2020 10:45:52 +0200 Subject: [PATCH 0934/1494] drm/qxl: don't touch mem.bus.offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is internal to TTM and should not be used by drivers directly. Drop the call to qxl_ttm_io_mem_reserve() and use mem->start instead. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389456/ --- drivers/gpu/drm/qxl/qxl_object.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index f838b6d689aad..b2a1fa61920be 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -167,6 +167,7 @@ int qxl_bo_kmap(struct qxl_bo *bo, void **ptr) void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, struct qxl_bo *bo, int page_offset) { + unsigned long offset; void *rptr; int ret; struct io_mapping *map; @@ -178,9 +179,8 @@ void *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, else goto fallback; - ret = qxl_ttm_io_mem_reserve(bo->tbo.bdev, &bo->tbo.mem); - - return io_mapping_map_atomic_wc(map, bo->tbo.mem.bus.offset + page_offset); + offset = bo->tbo.mem.start << PAGE_SHIFT; + return io_mapping_map_atomic_wc(map, offset + page_offset); fallback: if (bo->kptr) { rptr = bo->kptr + (page_offset * PAGE_SIZE); -- GitLab From 54d04ea8cdbd143496e4f5cc9c0a9f86c0e55a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 7 Sep 2020 13:44:36 +0200 Subject: [PATCH 0935/1494] drm/ttm: merge offset and base in ttm_bus_placement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used by TTM to communicate the physical address which should be used with ioremap(), ioremap_wc(). We don't need to separate the base and offset in any way here. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389457/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 7 ++++--- drivers/gpu/drm/drm_gem_ttm_helper.c | 5 +---- drivers/gpu/drm/drm_gem_vram_helper.c | 3 +-- drivers/gpu/drm/nouveau/nouveau_bo.c | 9 ++++----- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 3 +-- drivers/gpu/drm/qxl/qxl_ttm.c | 7 +++---- drivers/gpu/drm/radeon/radeon_ttm.c | 14 ++++++-------- drivers/gpu/drm/ttm/ttm_bo.c | 3 --- drivers/gpu/drm/ttm/ttm_bo_util.c | 17 ++++++----------- drivers/gpu/drm/ttm/ttm_bo_vm.c | 3 +-- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 4 ++-- include/drm/ttm/ttm_resource.h | 6 ++---- 12 files changed, 31 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ca568e25c41c5..c6f4d9ede0e0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -773,7 +773,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso mem->bus.addr = (u8 *)adev->mman.aper_base_kaddr + mem->bus.offset; - mem->bus.base = adev->gmc.aper_base; + mem->bus.offset += adev->gmc.aper_base; mem->bus.is_iomem = true; break; default: @@ -785,12 +785,13 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo, unsigned long page_offset) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); uint64_t offset = (page_offset << PAGE_SHIFT); struct drm_mm_node *mm; mm = amdgpu_find_mm_node(&bo->mem, &offset); - return (bo->mem.bus.base >> PAGE_SHIFT) + mm->start + - (offset >> PAGE_SHIFT); + offset += adev->gmc.aper_base; + return mm->start + (offset >> PAGE_SHIFT); } /** diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c index 892b2288a104b..0e4fb9ba43adb 100644 --- a/drivers/gpu/drm/drm_gem_ttm_helper.c +++ b/drivers/gpu/drm/drm_gem_ttm_helper.c @@ -43,12 +43,9 @@ void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent, drm_print_bits(p, bo->mem.placement, plname, ARRAY_SIZE(plname)); drm_printf(p, "\n"); - if (bo->mem.bus.is_iomem) { - drm_printf_indent(p, indent, "bus.base=%lx\n", - (unsigned long)bo->mem.bus.base); + if (bo->mem.bus.is_iomem) drm_printf_indent(p, indent, "bus.offset=%lx\n", (unsigned long)bo->mem.bus.offset); - } } EXPORT_SYMBOL(drm_gem_ttm_print_info); diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 788557bc5c010..6a7e0788d8f04 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1042,8 +1042,7 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, case TTM_PL_SYSTEM: /* nothing to do */ break; case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = vmm->vram_base; + mem->bus.offset = (mem->start << PAGE_SHIFT) + vmm->vram_base; mem->bus.is_iomem = true; break; default: diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 41aa7ac31bd53..83fdd169a27a5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1081,8 +1081,8 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) case TTM_PL_TT: #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { - reg->bus.offset = reg->start << PAGE_SHIFT; - reg->bus.base = drm->agp.base; + reg->bus.offset = (reg->start << PAGE_SHIFT) + + drm->agp.base; reg->bus.is_iomem = !drm->agp.cma; } #endif @@ -1094,8 +1094,8 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) } fallthrough; /* tiled memory */ case TTM_PL_VRAM: - reg->bus.offset = reg->start << PAGE_SHIFT; - reg->bus.base = device->func->resource_addr(device, 1); + reg->bus.offset = (reg->start << PAGE_SHIFT) + + device->func->resource_addr(device, 1); reg->bus.is_iomem = true; if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) { union { @@ -1133,7 +1133,6 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resource *reg) goto out; } - reg->bus.base = 0; reg->bus.offset = handle; ret = 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index fad8030ec1f81..3159a2172db57 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -378,8 +378,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; info->fbops = &nouveau_fbcon_sw_ops; - info->fix.smem_start = nvbo->bo.mem.bus.base + - nvbo->bo.mem.bus.offset; + info->fix.smem_start = nvbo->bo.mem.bus.offset; info->fix.smem_len = nvbo->bo.mem.num_pages << PAGE_SHIFT; info->screen_base = nvbo_kmap_obj_iovirtual(nvbo); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 3ab4603391453..19b18ea38c340 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -81,13 +81,12 @@ int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev, return 0; case TTM_PL_VRAM: mem->bus.is_iomem = true; - mem->bus.base = qdev->vram_base; - mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.offset = (mem->start << PAGE_SHIFT) + qdev->vram_base; break; case TTM_PL_PRIV: mem->bus.is_iomem = true; - mem->bus.base = qdev->surfaceram_base; - mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.offset = (mem->start << PAGE_SHIFT) + + qdev->surfaceram_base; break; default: return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index a8d6ca88c6e3b..375ffd4a56abf 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -372,8 +372,8 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { /* RADEON_IS_AGP is set only if AGP is active */ - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = rdev->mc.agp_base; + mem->bus.offset = (mem->start << PAGE_SHIFT) + + rdev->mc.agp_base; mem->bus.is_iomem = !rdev->ddev->agp->cant_use_aperture; } #endif @@ -383,7 +383,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso /* check if it's visible */ if ((mem->bus.offset + bus_size) > rdev->mc.visible_vram_size) return -EINVAL; - mem->bus.base = rdev->mc.aper_base; + mem->bus.offset += rdev->mc.aper_base; mem->bus.is_iomem = true; #ifdef __alpha__ /* @@ -392,12 +392,10 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso */ if (mem->placement & TTM_PL_FLAG_WC) mem->bus.addr = - ioremap_wc(mem->bus.base + mem->bus.offset, - bus_size); + ioremap_wc(mem->bus.offset, bus_size); else mem->bus.addr = - ioremap(mem->bus.base + mem->bus.offset, - bus_size); + ioremap(mem->bus.offset, bus_size); if (!mem->bus.addr) return -ENOMEM; @@ -407,7 +405,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso * It then can be used to build PTEs for VRAM * access, as done in ttm_bo_vm_fault(). */ - mem->bus.base = (mem->bus.base & 0x0ffffffffUL) + + mem->bus.offset = (mem->bus.offset & 0x0ffffffffUL) + rdev->ddev->hose->dense_mem_base; #endif break; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 55f995bca661e..c93de7fab7395 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -641,7 +641,6 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, evict_mem = bo->mem; evict_mem.mm_node = NULL; - evict_mem.bus.base = 0; evict_mem.bus.offset = 0; evict_mem.bus.addr = NULL; @@ -1076,7 +1075,6 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; mem.page_alignment = bo->mem.page_alignment; - mem.bus.base = 0; mem.bus.offset = 0; mem.bus.addr = NULL; mem.mm_node = NULL; @@ -1235,7 +1233,6 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->mem.num_pages = bo->num_pages; bo->mem.mm_node = NULL; bo->mem.page_alignment = page_alignment; - bo->mem.bus.base = 0; bo->mem.bus.offset = 0; bo->mem.bus.addr = NULL; bo->moving = NULL; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 6f527d71576ae..5ac8da43238be 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -94,7 +94,7 @@ EXPORT_SYMBOL(ttm_bo_move_ttm); int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_resource *mem) { - if (mem->bus.base || mem->bus.offset || mem->bus.addr) + if (mem->bus.offset || mem->bus.addr) return 0; mem->bus.is_iomem = false; @@ -107,13 +107,12 @@ int ttm_mem_io_reserve(struct ttm_bo_device *bdev, void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_resource *mem) { - if (!mem->bus.base && !mem->bus.offset && !mem->bus.addr) + if (!mem->bus.offset && !mem->bus.addr) return; if (bdev->driver->io_mem_free) bdev->driver->io_mem_free(bdev, mem); - mem->bus.base = 0; mem->bus.offset = 0; mem->bus.addr = NULL; } @@ -136,11 +135,9 @@ static int ttm_resource_ioremap(struct ttm_bo_device *bdev, size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; if (mem->placement & TTM_PL_FLAG_WC) - addr = ioremap_wc(mem->bus.base + mem->bus.offset, - bus_size); + addr = ioremap_wc(mem->bus.offset, bus_size); else - addr = ioremap(mem->bus.base + mem->bus.offset, - bus_size); + addr = ioremap(mem->bus.offset, bus_size); if (!addr) { ttm_mem_io_free(bdev, mem); return -ENOMEM; @@ -427,12 +424,10 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo, } else { map->bo_kmap_type = ttm_bo_map_iomap; if (mem->placement & TTM_PL_FLAG_WC) - map->virtual = ioremap_wc(bo->mem.bus.base + - bo->mem.bus.offset + offset, + map->virtual = ioremap_wc(bo->mem.bus.offset + offset, size); else - map->virtual = ioremap(bo->mem.bus.base + - bo->mem.bus.offset + offset, + map->virtual = ioremap(bo->mem.bus.offset + offset, size); } return (!map->virtual) ? -ENOMEM : 0; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index bb96f819f6078..0e5497d806863 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -101,8 +101,7 @@ static unsigned long ttm_bo_io_mem_pfn(struct ttm_buffer_object *bo, if (bdev->driver->io_mem_pfn) return bdev->driver->io_mem_pfn(bo, page_offset); - return ((bo->mem.bus.base + bo->mem.bus.offset) >> PAGE_SHIFT) - + page_offset; + return (bo->mem.bus.offset >> PAGE_SHIFT) + page_offset; } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index a76a7f542dd8c..fdd2a5985616c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -725,8 +725,8 @@ static int vmw_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_resourc case VMW_PL_MOB: return 0; case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; - mem->bus.base = dev_priv->vram_start; + mem->bus.offset = (mem->start << PAGE_SHIFT) + + dev_priv->vram_start; mem->bus.is_iomem = true; break; default: diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 406baa8f0068e..7b8a3157fbb32 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -148,16 +148,14 @@ struct ttm_resource_manager { * struct ttm_bus_placement * * @addr: mapped virtual address - * @base: bus base address + * @offset: physical addr * @is_iomem: is this io memory ? - * @offset: offset from the base address * * Structure indicating the bus placement of an object. */ struct ttm_bus_placement { void *addr; - phys_addr_t base; - unsigned long offset; + phys_addr_t offset; bool is_iomem; }; -- GitLab From a49145acfb975d921464b84fe00279f99827d816 Mon Sep 17 00:00:00 2001 From: George Kennedy <george.kennedy@oracle.com> Date: Tue, 7 Jul 2020 15:26:03 -0400 Subject: [PATCH 0936/1494] fbmem: add margin check to fb_check_caps() A fb_ioctl() FBIOPUT_VSCREENINFO call with invalid xres setting or yres setting in struct fb_var_screeninfo will result in a KASAN: vmalloc-out-of-bounds failure in bitfill_aligned() as the margins are being cleared. The margins are cleared in chunks and if the xres setting or yres setting is a value of zero upto the chunk size, the failure will occur. Add a margin check to validate xres and yres settings. Signed-off-by: George Kennedy <george.kennedy@oracle.com> Reported-by: syzbot+e5fd3e65515b48c02a30@syzkaller.appspotmail.com Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com> Cc: Dhaval Giani <dhaval.giani@oracle.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/1594149963-13801-1-git-send-email-george.kennedy@oracle.com --- drivers/video/fbdev/core/fbmem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index cc69649dce95e..8268bbee8cae1 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1006,6 +1006,10 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) return 0; } + /* bitfill_aligned() assumes that it's at least 8x8 */ + if (var->xres < 8 || var->yres < 8) + return -EINVAL; + ret = info->fbops->fb_check_var(var, info); if (ret) -- GitLab From bcee1609ba9623f35597f06a2ad118ac4ade2974 Mon Sep 17 00:00:00 2001 From: Evgeny Novikov <novikov@ispras.ru> Date: Mon, 13 Jul 2020 11:05:32 +0300 Subject: [PATCH 0937/1494] fbdev: sm712fb: handle ioremap() errors in probe smtcfb_pci_probe() does not handle ioremap() errors for case 0x720. The patch fixes that exactly like for case 0x710/2. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Evgeny Novikov <novikov@ispras.ru> Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Cc: Teddy Wang <teddy.wang@siliconmotion.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200713080532.15504-1-novikov@ispras.ru --- drivers/video/fbdev/sm712fb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c index bdbe9c68e2740..0dbc6bf8268ac 100644 --- a/drivers/video/fbdev/sm712fb.c +++ b/drivers/video/fbdev/sm712fb.c @@ -1604,6 +1604,14 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, sfb->fb->fix.mmio_start = mmio_base; sfb->fb->fix.mmio_len = 0x00200000; sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size); + if (!sfb->dp_regs) { + dev_err(&pdev->dev, + "%s: unable to map memory mapped IO!\n", + sfb->fb->fix.id); + err = -ENOMEM; + goto failed_fb; + } + sfb->lfb = sfb->dp_regs + 0x00200000; sfb->mmio = (smtc_regbaseaddress = sfb->dp_regs + 0x000c0000); -- GitLab From c72fab81ceaa54408b827a2f0486d9a0f4be34cf Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Thu, 23 Jul 2020 18:02:27 +0100 Subject: [PATCH 0938/1494] video: fbdev: vga16fb: fix setting of pixclock because a pass-by-value error The pixclock is being set locally because it is being passed as a pass-by-value argument rather than pass-by-reference, so the computed pixclock is never being set in var->pixclock. Fix this by passing by reference. [This dates back to 2002, I found the offending commit from the git history git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git ] Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King <colin.king@canonical.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jani Nikula <jani.nikula@intel.com> [b.zolnierkie: minor patch summary fixup] [b.zolnierkie: removed "Fixes:" tag (not in upstream tree)] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200723170227.996229-1-colin.king@canonical.com --- drivers/video/fbdev/vga16fb.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index a20eeb8308ffd..52f273af6caee 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -243,7 +243,7 @@ static void vga16fb_update_fix(struct fb_info *info) } static void vga16fb_clock_chip(struct vga16fb_par *par, - unsigned int pixclock, + unsigned int *pixclock, const struct fb_info *info, int mul, int div) { @@ -259,14 +259,14 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, { 0 /* bad */, 0x00, 0x00}}; int err; - pixclock = (pixclock * mul) / div; + *pixclock = (*pixclock * mul) / div; best = vgaclocks; - err = pixclock - best->pixclock; + err = *pixclock - best->pixclock; if (err < 0) err = -err; for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) { int tmp; - tmp = pixclock - ptr->pixclock; + tmp = *pixclock - ptr->pixclock; if (tmp < 0) tmp = -tmp; if (tmp < err) { err = tmp; @@ -275,7 +275,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par, } par->misc |= best->misc; par->clkdiv = best->seq_clock_mode; - pixclock = (best->pixclock * div) / mul; + *pixclock = (best->pixclock * div) / mul; } #define FAIL(X) return -EINVAL @@ -497,10 +497,10 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var, if (mode & MODE_8BPP) /* pixel clock == vga clock / 2 */ - vga16fb_clock_chip(par, var->pixclock, info, 1, 2); + vga16fb_clock_chip(par, &var->pixclock, info, 1, 2); else /* pixel clock == vga clock */ - vga16fb_clock_chip(par, var->pixclock, info, 1, 1); + vga16fb_clock_chip(par, &var->pixclock, info, 1, 1); var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0; -- GitLab From 9ec2832e9cdd7b3ad58e39217775e5b10290e62f Mon Sep 17 00:00:00 2001 From: Rodrigo Alencar <455.rodrigo.alencar@gmail.com> Date: Fri, 24 Jul 2020 17:22:18 -0300 Subject: [PATCH 0939/1494] video: fbdev: ssd1307fb: Added support to Column offset This patch provides support for displays like VGM128064B0W10, which requires a column offset of 2, i.e., its segments starts in SEG2 and ends in SEG129. Signed-off-by: Rodrigo Alencar <455.rodrigo.alencar@gmail.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/1595622138-3965-1-git-send-email-455.rodrigo.alencar@gmail.com --- Documentation/devicetree/bindings/display/ssd1307fb.txt | 1 + drivers/video/fbdev/ssd1307fb.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/ssd1307fb.txt b/Documentation/devicetree/bindings/display/ssd1307fb.txt index 27333b9551b33..2dcb6d12d1371 100644 --- a/Documentation/devicetree/bindings/display/ssd1307fb.txt +++ b/Documentation/devicetree/bindings/display/ssd1307fb.txt @@ -19,6 +19,7 @@ Optional properties: - vbat-supply: The supply for VBAT - solomon,segment-no-remap: Display needs normal (non-inverted) data column to segment mapping + - solomon,col-offset: Offset of columns (COL/SEG) that the screen is mapped to. - solomon,com-seq: Display uses sequential COM pin configuration - solomon,com-lrremap: Display uses left-right COM pin remap - solomon,com-invdir: Display uses inverted COM pin scan direction diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 09425ec317ba2..eda448b7a0c9d 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -74,6 +74,7 @@ struct ssd1307fb_par { struct fb_info *info; u8 lookup_table[4]; u32 page_offset; + u32 col_offset; u32 prechargep1; u32 prechargep2; struct pwm_device *pwm; @@ -458,11 +459,11 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) if (ret < 0) return ret; - ret = ssd1307fb_write_cmd(par->client, 0x0); + ret = ssd1307fb_write_cmd(par->client, par->col_offset); if (ret < 0) return ret; - ret = ssd1307fb_write_cmd(par->client, par->width - 1); + ret = ssd1307fb_write_cmd(par->client, par->col_offset + par->width - 1); if (ret < 0) return ret; @@ -626,6 +627,9 @@ static int ssd1307fb_probe(struct i2c_client *client) if (device_property_read_u32(dev, "solomon,page-offset", &par->page_offset)) par->page_offset = 1; + if (device_property_read_u32(dev, "solomon,col-offset", &par->col_offset)) + par->col_offset = 0; + if (device_property_read_u32(dev, "solomon,com-offset", &par->com_offset)) par->com_offset = 0; -- GitLab From fe2ab107536d808ad0c8ddce3e35b048dc5acb0f Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 5 Aug 2020 11:28:05 +0100 Subject: [PATCH 0940/1494] omapfb: fix spelling mistake "propert" -> "property" There is a spelling mistake in a pr_err message. Fix it. Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805102805.15353-1-colin.king@canonical.com --- drivers/video/fbdev/omap2/omapfb/dss/venc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/venc.c b/drivers/video/fbdev/omap2/omapfb/dss/venc.c index 0b0ad20afd630..f560fa4d7786e 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/venc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/venc.c @@ -787,7 +787,7 @@ static int venc_probe_of(struct platform_device *pdev) venc.type = OMAP_DSS_VENC_TYPE_SVIDEO; break; default: - dev_err(&pdev->dev, "bad channel propert '%d'\n", channels); + dev_err(&pdev->dev, "bad channel property '%d'\n", channels); r = -EINVAL; goto err; } -- GitLab From ad6f93e9cd56f0b10e9b22e3e137d17a1a035242 Mon Sep 17 00:00:00 2001 From: Tom Rix <trix@redhat.com> Date: Wed, 5 Aug 2020 07:52:08 -0700 Subject: [PATCH 0941/1494] video: fbdev: sis: fix null ptr dereference Clang static analysis reports this representative error init.c:2501:18: warning: Array access (from variable 'queuedata') results in a null pointer dereference templ |= ((queuedata[i] & 0xc0) << 3); This is the problem block of code if(ModeNo > 0x13) { ... if(SiS_Pr->ChipType == SIS_730) { queuedata = &FQBQData730[0]; } else { queuedata = &FQBQData[0]; } } else { } queuedata is not set in the else block Reviewing the old code, the arrays FQBQData730 and FQBQData were used directly. So hoist the setting of queuedata out of the if-else block. Fixes: 544393fe584d ("[PATCH] sisfb update") Signed-off-by: Tom Rix <trix@redhat.com> Cc: Thomas Winischhofer <thomas@winischhofer.net> Cc: Andrew Morton <akpm@osdl.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200805145208.17727-1-trix@redhat.com --- drivers/video/fbdev/sis/init.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/video/fbdev/sis/init.c b/drivers/video/fbdev/sis/init.c index dfe3eb769638b..fde27feae5d0c 100644 --- a/drivers/video/fbdev/sis/init.c +++ b/drivers/video/fbdev/sis/init.c @@ -2428,6 +2428,11 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo, i = 0; + if (SiS_Pr->ChipType == SIS_730) + queuedata = &FQBQData730[0]; + else + queuedata = &FQBQData[0]; + if(ModeNo > 0x13) { /* Get VCLK */ @@ -2445,12 +2450,6 @@ SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo, /* Get half colordepth */ colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)]; - if(SiS_Pr->ChipType == SIS_730) { - queuedata = &FQBQData730[0]; - } else { - queuedata = &FQBQData[0]; - } - do { templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth; -- GitLab From fa41f2877429646ce062a034a6d5bfc4f8f04b8c Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:43 +0530 Subject: [PATCH 0942/1494] fbdev: gxfb: use generic power management Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. This way we can remove the legacy .suspend & .resume bindings from "gxfb_driver". The gxfb_suspend() is designed to function only in the case of Suspend. Thus, the code was kept inside "if (state.event == PM_EVENT_SUSPEND)" container. This is because, in the legacy framework, this callback was invoked even in the event of Freeze and Hibernate. Hence, added the load of unnecessary function-calls. The goal can be achieved by binding the callback with only "gxfb_pm_ops.suspend" in the new framework. This also avoids the step of checking "if (state.event == PM_EVENT_SUSPEND)" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-2-vaibhavgupta40@gmail.com --- drivers/video/fbdev/geode/gxfb.h | 5 ---- drivers/video/fbdev/geode/gxfb_core.c | 36 ++++++++++++++------------ drivers/video/fbdev/geode/suspend_gx.c | 4 --- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/video/fbdev/geode/gxfb.h b/drivers/video/fbdev/geode/gxfb.h index d2e9c5c8e2940..792c111c21e40 100644 --- a/drivers/video/fbdev/geode/gxfb.h +++ b/drivers/video/fbdev/geode/gxfb.h @@ -21,7 +21,6 @@ struct gxfb_par { void __iomem *dc_regs; void __iomem *vid_regs; void __iomem *gp_regs; -#ifdef CONFIG_PM int powered_down; /* register state, for power management functionality */ @@ -36,7 +35,6 @@ struct gxfb_par { uint64_t fp[FP_REG_COUNT]; uint32_t pal[DC_PAL_COUNT]; -#endif }; unsigned int gx_frame_buffer_size(void); @@ -49,11 +47,8 @@ void gx_set_dclk_frequency(struct fb_info *info); void gx_configure_display(struct fb_info *info); int gx_blank_display(struct fb_info *info, int blank_mode); -#ifdef CONFIG_PM int gx_powerdown(struct fb_info *info); int gx_powerup(struct fb_info *info); -#endif - /* Graphics Processor registers (table 6-23 from the data book) */ enum gp_registers { diff --git a/drivers/video/fbdev/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c index d38a148d4746f..44089b331f91d 100644 --- a/drivers/video/fbdev/geode/gxfb_core.c +++ b/drivers/video/fbdev/geode/gxfb_core.c @@ -322,17 +322,14 @@ static struct fb_info *gxfb_init_fbinfo(struct device *dev) return info; } -#ifdef CONFIG_PM -static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused gxfb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(pdev); + struct fb_info *info = dev_get_drvdata(dev); - if (state.event == PM_EVENT_SUSPEND) { - console_lock(); - gx_powerdown(info); - fb_set_suspend(info, 1); - console_unlock(); - } + console_lock(); + gx_powerdown(info); + fb_set_suspend(info, 1); + console_unlock(); /* there's no point in setting PCI states; we emulate PCI, so * we don't end up getting power savings anyways */ @@ -340,9 +337,9 @@ static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int gxfb_resume(struct pci_dev *pdev) +static int __maybe_unused gxfb_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(pdev); + struct fb_info *info = dev_get_drvdata(dev); int ret; console_lock(); @@ -356,7 +353,6 @@ static int gxfb_resume(struct pci_dev *pdev) console_unlock(); return 0; } -#endif static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -467,15 +463,23 @@ static const struct pci_device_id gxfb_id_table[] = { MODULE_DEVICE_TABLE(pci, gxfb_id_table); +static const struct dev_pm_ops gxfb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = gxfb_suspend, + .resume = gxfb_resume, + .freeze = NULL, + .thaw = gxfb_resume, + .poweroff = NULL, + .restore = gxfb_resume, +#endif +}; + static struct pci_driver gxfb_driver = { .name = "gxfb", .id_table = gxfb_id_table, .probe = gxfb_probe, .remove = gxfb_remove, -#ifdef CONFIG_PM - .suspend = gxfb_suspend, - .resume = gxfb_resume, -#endif + .driver.pm = &gxfb_pm_ops, }; #ifndef MODULE diff --git a/drivers/video/fbdev/geode/suspend_gx.c b/drivers/video/fbdev/geode/suspend_gx.c index 1110a527c35c5..8c49d4e987722 100644 --- a/drivers/video/fbdev/geode/suspend_gx.c +++ b/drivers/video/fbdev/geode/suspend_gx.c @@ -11,8 +11,6 @@ #include "gxfb.h" -#ifdef CONFIG_PM - static void gx_save_regs(struct gxfb_par *par) { int i; @@ -259,5 +257,3 @@ int gx_powerup(struct fb_info *info) par->powered_down = 0; return 0; } - -#endif -- GitLab From df7a9ec3bc12c6464491d3bee0e7983f48bc04e4 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:44 +0530 Subject: [PATCH 0943/1494] fbdev: lxfb: use generic power management Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. This way we can remove the legacy .suspend & .resume bindings from "lxfb_driver". The lxfb_suspend() is designed to function only in the case of Suspend. Thus, the code was kept inside "if (state.event == PM_EVENT_SUSPEND)" container. This is because, in the legacy framework, this callback was invoked even in the event of Freeze and Hibernate. Hence, added the load of unnecessary function-calls. The goal can be achieved by binding the callback with only "lxfb_pm_ops.suspend" in the new framework. This also avoids the step of checking "if (state.event == PM_EVENT_SUSPEND)" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-3-vaibhavgupta40@gmail.com --- drivers/video/fbdev/geode/lxfb.h | 5 ---- drivers/video/fbdev/geode/lxfb_core.c | 37 +++++++++++++++------------ drivers/video/fbdev/geode/lxfb_ops.c | 4 --- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/video/fbdev/geode/lxfb.h b/drivers/video/fbdev/geode/lxfb.h index ef24bf6d49dc9..d37b32dbcd686 100644 --- a/drivers/video/fbdev/geode/lxfb.h +++ b/drivers/video/fbdev/geode/lxfb.h @@ -29,7 +29,6 @@ struct lxfb_par { void __iomem *gp_regs; void __iomem *dc_regs; void __iomem *vp_regs; -#ifdef CONFIG_PM int powered_down; /* register state, for power mgmt functionality */ @@ -50,7 +49,6 @@ struct lxfb_par { uint32_t hcoeff[DC_HFILT_COUNT * 2]; uint32_t vcoeff[DC_VFILT_COUNT]; uint32_t vp_coeff[VP_COEFF_SIZE / 4]; -#endif }; static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) @@ -64,11 +62,8 @@ int lx_blank_display(struct fb_info *, int); void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, unsigned int, unsigned int); -#ifdef CONFIG_PM int lx_powerdown(struct fb_info *info); int lx_powerup(struct fb_info *info); -#endif - /* Graphics Processor registers (table 6-29 from the data book) */ enum gp_registers { diff --git a/drivers/video/fbdev/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c index adc2d9c2395e3..66c81262d18f8 100644 --- a/drivers/video/fbdev/geode/lxfb_core.c +++ b/drivers/video/fbdev/geode/lxfb_core.c @@ -443,17 +443,14 @@ static struct fb_info *lxfb_init_fbinfo(struct device *dev) return info; } -#ifdef CONFIG_PM -static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused lxfb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(pdev); + struct fb_info *info = dev_get_drvdata(dev); - if (state.event == PM_EVENT_SUSPEND) { - console_lock(); - lx_powerdown(info); - fb_set_suspend(info, 1); - console_unlock(); - } + console_lock(); + lx_powerdown(info); + fb_set_suspend(info, 1); + console_unlock(); /* there's no point in setting PCI states; we emulate PCI, so * we don't end up getting power savings anyways */ @@ -461,9 +458,9 @@ static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -static int lxfb_resume(struct pci_dev *pdev) +static int __maybe_unused lxfb_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(pdev); + struct fb_info *info = dev_get_drvdata(dev); int ret; console_lock(); @@ -477,10 +474,6 @@ static int lxfb_resume(struct pci_dev *pdev) console_unlock(); return 0; } -#else -#define lxfb_suspend NULL -#define lxfb_resume NULL -#endif static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -600,13 +593,23 @@ static struct pci_device_id lxfb_id_table[] = { MODULE_DEVICE_TABLE(pci, lxfb_id_table); +static const struct dev_pm_ops lxfb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = lxfb_suspend, + .resume = lxfb_resume, + .freeze = NULL, + .thaw = lxfb_resume, + .poweroff = NULL, + .restore = lxfb_resume, +#endif +}; + static struct pci_driver lxfb_driver = { .name = "lxfb", .id_table = lxfb_id_table, .probe = lxfb_probe, .remove = lxfb_remove, - .suspend = lxfb_suspend, - .resume = lxfb_resume, + .driver.pm = &lxfb_pm_ops, }; #ifndef MODULE diff --git a/drivers/video/fbdev/geode/lxfb_ops.c b/drivers/video/fbdev/geode/lxfb_ops.c index 5be8bc62844c2..b3a041fce570d 100644 --- a/drivers/video/fbdev/geode/lxfb_ops.c +++ b/drivers/video/fbdev/geode/lxfb_ops.c @@ -580,8 +580,6 @@ int lx_blank_display(struct fb_info *info, int blank_mode) return 0; } -#ifdef CONFIG_PM - static void lx_save_regs(struct lxfb_par *par) { uint32_t filt; @@ -837,5 +835,3 @@ int lx_powerup(struct fb_info *info) par->powered_down = 0; return 0; } - -#endif -- GitLab From ab5fe88aef4b4837bc2f92fc9f6f9c9b75ef633b Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:45 +0530 Subject: [PATCH 0944/1494] fbdev: via-core: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. The via_suspend() is designed to function only in the case of Suspend. Thus, the code checked for "if (state.event != PM_EVENT_SUSPEND)". This is because, in the legacy framework, this callback was invoked even in the event of Freeze and Hibernate. Hence, added the load of unnecessary function-calls. The goal can be achieved by binding the callback with only "via_pm_ops.suspend" in the new framework. This also avoids the step of checking "if (state.event != PM_EVENT_SUSPEND)" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-4-vaibhavgupta40@gmail.com --- drivers/video/fbdev/via/via-core.c | 39 ++++++++++++------------------ include/linux/via-core.h | 2 -- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c index 703ddee9a2443..89d75079b7307 100644 --- a/drivers/video/fbdev/via/via-core.c +++ b/drivers/video/fbdev/via/via-core.c @@ -558,9 +558,8 @@ static void via_teardown_subdevs(void) /* * Power management functions */ -#ifdef CONFIG_PM -static LIST_HEAD(viafb_pm_hooks); -static DEFINE_MUTEX(viafb_pm_hooks_lock); +static __maybe_unused LIST_HEAD(viafb_pm_hooks); +static __maybe_unused DEFINE_MUTEX(viafb_pm_hooks_lock); void viafb_pm_register(struct viafb_pm_hooks *hooks) { @@ -580,12 +579,10 @@ void viafb_pm_unregister(struct viafb_pm_hooks *hooks) } EXPORT_SYMBOL_GPL(viafb_pm_unregister); -static int via_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused via_suspend(struct device *dev) { struct viafb_pm_hooks *hooks; - if (state.event != PM_EVENT_SUSPEND) - return 0; /* * "I've occasionally hit a few drivers that caused suspend * failures, and each and every time it was a driver bug, and @@ -600,24 +597,13 @@ static int via_suspend(struct pci_dev *pdev, pm_message_t state) hooks->suspend(hooks->private); mutex_unlock(&viafb_pm_hooks_lock); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int via_resume(struct pci_dev *pdev) +static int __maybe_unused via_resume(struct device *dev) { struct viafb_pm_hooks *hooks; - /* Get the bus side powered up */ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - if (pci_enable_device(pdev)) - return 0; - - pci_set_master(pdev); - /* Now bring back any subdevs */ mutex_lock(&viafb_pm_hooks_lock); list_for_each_entry(hooks, &viafb_pm_hooks, list) @@ -626,7 +612,6 @@ static int via_resume(struct pci_dev *pdev) return 0; } -#endif /* CONFIG_PM */ static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -712,15 +697,23 @@ static const struct pci_device_id via_pci_table[] = { }; MODULE_DEVICE_TABLE(pci, via_pci_table); +static const struct dev_pm_ops via_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = via_suspend, + .resume = via_resume, + .freeze = NULL, + .thaw = via_resume, + .poweroff = NULL, + .restore = via_resume, +#endif +}; + static struct pci_driver via_driver = { .name = "viafb", .id_table = via_pci_table, .probe = via_pci_probe, .remove = via_pci_remove, -#ifdef CONFIG_PM - .suspend = via_suspend, - .resume = via_resume, -#endif + .driver.pm = &via_pm_ops, }; static int __init via_core_init(void) diff --git a/include/linux/via-core.h b/include/linux/via-core.h index 9e802deedb2d4..8737599b9148a 100644 --- a/include/linux/via-core.h +++ b/include/linux/via-core.h @@ -47,7 +47,6 @@ struct via_port_cfg { /* * Allow subdevs to register suspend/resume hooks. */ -#ifdef CONFIG_PM struct viafb_pm_hooks { struct list_head list; int (*suspend)(void *private); @@ -57,7 +56,6 @@ struct viafb_pm_hooks { void viafb_pm_register(struct viafb_pm_hooks *hooks); void viafb_pm_unregister(struct viafb_pm_hooks *hooks); -#endif /* CONFIG_PM */ /* * This is the global viafb "device" containing stuff needed by -- GitLab From 348b2956d5e6d9876b567226184de598d00c9bd1 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:46 +0530 Subject: [PATCH 0945/1494] fbdev: aty: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Now, - atyfb_pci_suspend() had a "pm_message_t" type parameter as per legacy PCI PM framework, that got deprecated in generic. - Rename the callback as atyfb_pci_suspend_late() and preserve the parameter. - Define 3 new callbacks as: * atyfb_pci_suspend() * atyfb_pci_freeze() * atyfb_pci_hibernate() which in turn call atyfb_pci_suspend_late() by passing appropriate value for "pm_message_t" type parameter. - Bind the callbacks in "struct dev_pm_ops" type variable "atyfb_pci_pm_ops". Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-5-vaibhavgupta40@gmail.com --- drivers/video/fbdev/aty/atyfb_base.c | 50 ++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index ad9cfe34c9ffa..c8feff0ee8da9 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -132,8 +132,8 @@ #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args) #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) -#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ -defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) +#if defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_GENERIC_LCD) || \ +defined(CONFIG_FB_ATY_BACKLIGHT) static const u32 lt_lcd_regs[] = { CNFG_PANEL_LG, LCD_GEN_CNTL_LG, @@ -175,7 +175,7 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par) return aty_ld_le32(LCD_DATA, par); } } -#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */ +#endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */ #ifdef CONFIG_FB_ATY_GENERIC_LCD /* @@ -1989,7 +1989,7 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -#if defined(CONFIG_PM) && defined(CONFIG_PCI) +#if defined(CONFIG_PCI) #ifdef CONFIG_PPC_PMAC /* Power management routines. Those are used for PowerBook sleep. @@ -2050,8 +2050,9 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) } #endif /* CONFIG_PPC_PMAC */ -static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int atyfb_pci_suspend_late(struct device *dev, pm_message_t state) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -2077,7 +2078,6 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) * first save the config space content so the core can * restore it properly on resume. */ - pci_save_state(pdev); #ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ @@ -2089,8 +2089,6 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) console_unlock(); return -EIO; } -#else - pci_set_power_state(pdev, pci_choose_state(pdev, state)); #endif console_unlock(); @@ -2100,6 +2098,21 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +static int __maybe_unused atyfb_pci_suspend(struct device *dev) +{ + return atyfb_pci_suspend_late(dev, PMSG_SUSPEND); +} + +static int __maybe_unused atyfb_pci_hibernate(struct device *dev) +{ + return atyfb_pci_suspend_late(dev, PMSG_HIBERNATE); +} + +static int __maybe_unused atyfb_pci_freeze(struct device *dev) +{ + return atyfb_pci_suspend_late(dev, PMSG_FREEZE); +} + static void aty_resume_chip(struct fb_info *info) { struct atyfb_par *par = info->par; @@ -2114,8 +2127,9 @@ static void aty_resume_chip(struct fb_info *info) aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); } -static int atyfb_pci_resume(struct pci_dev *pdev) +static int __maybe_unused atyfb_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -2157,7 +2171,18 @@ static int atyfb_pci_resume(struct pci_dev *pdev) return 0; } -#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */ +static const struct dev_pm_ops atyfb_pci_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = atyfb_pci_suspend, + .resume = atyfb_pci_resume, + .freeze = atyfb_pci_freeze, + .thaw = atyfb_pci_resume, + .poweroff = atyfb_pci_hibernate, + .restore = atyfb_pci_resume, +#endif /* CONFIG_PM_SLEEP */ +}; + +#endif /* defined(CONFIG_PCI) */ /* Backlight */ #ifdef CONFIG_FB_ATY_BACKLIGHT @@ -3796,10 +3821,7 @@ static struct pci_driver atyfb_driver = { .id_table = atyfb_pci_tbl, .probe = atyfb_pci_probe, .remove = atyfb_pci_remove, -#ifdef CONFIG_PM - .suspend = atyfb_pci_suspend, - .resume = atyfb_pci_resume, -#endif /* CONFIG_PM */ + .driver.pm = &atyfb_pci_pm_ops, }; #endif /* CONFIG_PCI */ -- GitLab From c1a477767137bc7023b95eb6caf0d9eb25072ea3 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:47 +0530 Subject: [PATCH 0946/1494] fbdev: aty128fb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Now, - aty128_pci_suspend() had a "pm_message_t" type parameter as per legacy PCI PM framework that got deprecated in generic. - Rename the callback as aty128_pci_suspend_late() and preserve the parameter. - Define 3 new callbacks as: * aty128_pci_suspend() * aty128_pci_freeze() * aty128_pci_hibernate() which in turn call aty128_pci_suspend_late() by passing appropriate value for "pm_message_t" type parameter. - Bind the callbacks in "struct dev_pm_ops" type variable "aty128_pci_pm_ops". Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-6-vaibhavgupta40@gmail.com --- drivers/video/fbdev/aty/aty128fb.c | 51 ++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index 6fae6ad6cb77b..e6a48689c2949 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -162,10 +162,22 @@ static char * const r128_family[] = { static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent); static void aty128_remove(struct pci_dev *pdev); -static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state); -static int aty128_pci_resume(struct pci_dev *pdev); +static int aty128_pci_suspend_late(struct device *dev, pm_message_t state); +static int __maybe_unused aty128_pci_suspend(struct device *dev); +static int __maybe_unused aty128_pci_hibernate(struct device *dev); +static int __maybe_unused aty128_pci_freeze(struct device *dev); +static int __maybe_unused aty128_pci_resume(struct device *dev); static int aty128_do_resume(struct pci_dev *pdev); +static const struct dev_pm_ops aty128_pci_pm_ops = { + .suspend = aty128_pci_suspend, + .resume = aty128_pci_resume, + .freeze = aty128_pci_freeze, + .thaw = aty128_pci_resume, + .poweroff = aty128_pci_hibernate, + .restore = aty128_pci_resume, +}; + /* supported Rage128 chipsets */ static const struct pci_device_id aty128_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_LE, @@ -272,8 +284,7 @@ static struct pci_driver aty128fb_driver = { .id_table = aty128_pci_tbl, .probe = aty128_probe, .remove = aty128_remove, - .suspend = aty128_pci_suspend, - .resume = aty128_pci_resume, + .driver.pm = &aty128_pci_pm_ops, }; /* packed BIOS settings */ @@ -2316,7 +2327,6 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg) static void aty128_set_suspend(struct aty128fb_par *par, int suspend) { u32 pmgt; - struct pci_dev *pdev = par->pdev; if (!par->pdev->pm_cap) return; @@ -2343,23 +2353,15 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) aty_st_le32(BUS_CNTL1, 0x00000010); aty_st_le32(MEM_POWER_MISC, 0x0c830000); msleep(100); - - /* Switch PCI power management to D2 */ - pci_set_power_state(pdev, PCI_D2); } } -static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int aty128_pci_suspend_late(struct device *dev, pm_message_t state) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct aty128fb_par *par = info->par; - /* Because we may change PCI D state ourselves, we need to - * first save the config space content so the core can - * restore it properly on resume. - */ - pci_save_state(pdev); - /* We don't do anything but D2, for now we return 0, but * we may want to change that. How do we know if the BIOS * can properly take care of D3 ? Also, with swsusp, we @@ -2418,6 +2420,21 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +static int __maybe_unused aty128_pci_suspend(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_SUSPEND); +} + +static int __maybe_unused aty128_pci_hibernate(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_HIBERNATE); +} + +static int __maybe_unused aty128_pci_freeze(struct device *dev) +{ + return aty128_pci_suspend_late(dev, PMSG_FREEZE); +} + static int aty128_do_resume(struct pci_dev *pdev) { struct fb_info *info = pci_get_drvdata(pdev); @@ -2464,12 +2481,12 @@ static int aty128_do_resume(struct pci_dev *pdev) return 0; } -static int aty128_pci_resume(struct pci_dev *pdev) +static int __maybe_unused aty128_pci_resume(struct device *dev) { int rc; console_lock(); - rc = aty128_do_resume(pdev); + rc = aty128_do_resume(to_pci_dev(dev)); console_unlock(); return rc; -- GitLab From 6d111187588cddc4d0fd84007756f396cdb2de85 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:48 +0530 Subject: [PATCH 0947/1494] fbdev: nvidia: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Now, - nvidiafb_suspend() had a "pm_message_t" type parameter as per legacy PCI PM framework that got deprecated in generic. - Rename the callback as nvidiafb_suspend_late() and preserve the parameter. - Define 3 new callbacks as: * nvidiafb_suspend() * nvidiafb_freeze() * nvidiafb_hibernate() which in turn call nvidiafb_suspend_late() by passing appropriate value for "pm_message_t" type parameter. - Bind the callbacks in "struct dev_pm_ops" type variable "nvidiafb_pm_ops". Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-7-vaibhavgupta40@gmail.com --- drivers/video/fbdev/nvidia/nvidia.c | 64 ++++++++++++++++------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c index c6820e21875d3..a372a183c1f01 100644 --- a/drivers/video/fbdev/nvidia/nvidia.c +++ b/drivers/video/fbdev/nvidia/nvidia.c @@ -1037,10 +1037,9 @@ static struct fb_ops nvidia_fb_ops = { .fb_sync = nvidiafb_sync, }; -#ifdef CONFIG_PM -static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg) +static int nvidiafb_suspend_late(struct device *dev, pm_message_t mesg) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct nvidia_par *par = info->par; if (mesg.event == PM_EVENT_PRETHAW) @@ -1052,46 +1051,54 @@ static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg) fb_set_suspend(info, 1); nvidiafb_blank(FB_BLANK_POWERDOWN, info); nvidia_write_regs(par, &par->SavedReg); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, mesg)); } - dev->dev.power.power_state = mesg; + dev->power.power_state = mesg; console_unlock(); return 0; } -static int nvidiafb_resume(struct pci_dev *dev) +static int __maybe_unused nvidiafb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); - struct nvidia_par *par = info->par; + return nvidiafb_suspend_late(dev, PMSG_SUSPEND); +} - console_lock(); - pci_set_power_state(dev, PCI_D0); +static int __maybe_unused nvidiafb_hibernate(struct device *dev) +{ + return nvidiafb_suspend_late(dev, PMSG_HIBERNATE); +} - if (par->pm_state != PM_EVENT_FREEZE) { - pci_restore_state(dev); +static int __maybe_unused nvidiafb_freeze(struct device *dev) +{ + return nvidiafb_suspend_late(dev, PMSG_FREEZE); +} - if (pci_enable_device(dev)) - goto fail; +static int __maybe_unused nvidiafb_resume(struct device *dev) +{ + struct fb_info *info = dev_get_drvdata(dev); + struct nvidia_par *par = info->par; - pci_set_master(dev); - } + console_lock(); par->pm_state = PM_EVENT_ON; nvidiafb_set_par(info); fb_set_suspend (info, 0); nvidiafb_blank(FB_BLANK_UNBLANK, info); -fail: console_unlock(); return 0; } -#else -#define nvidiafb_suspend NULL -#define nvidiafb_resume NULL -#endif + +static const struct dev_pm_ops nvidiafb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = nvidiafb_suspend, + .resume = nvidiafb_resume, + .freeze = nvidiafb_freeze, + .thaw = nvidiafb_resume, + .poweroff = nvidiafb_hibernate, + .restore = nvidiafb_resume, +#endif /* CONFIG_PM_SLEEP */ +}; static int nvidia_set_fbinfo(struct fb_info *info) { @@ -1492,12 +1499,11 @@ static int nvidiafb_setup(char *options) #endif /* !MODULE */ static struct pci_driver nvidiafb_driver = { - .name = "nvidiafb", - .id_table = nvidiafb_pci_tbl, - .probe = nvidiafb_probe, - .suspend = nvidiafb_suspend, - .resume = nvidiafb_resume, - .remove = nvidiafb_remove, + .name = "nvidiafb", + .id_table = nvidiafb_pci_tbl, + .probe = nvidiafb_probe, + .driver.pm = &nvidiafb_pm_ops, + .remove = nvidiafb_remove, }; /* ------------------------------------------------------------------------- * -- GitLab From a4ba7df57e56496349ed84f00310468ae97aea7b Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:49 +0530 Subject: [PATCH 0948/1494] fbdev: savagefb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Now, - savagefb_suspend() had a "pm_message_t" type parameter as per legacy PCI PM framework that got deprecated in generic. - Rename the callback as savagefb_suspend_late() and preserve the parameter. - Define 3 new callbacks as: * savagefb_suspend() * savagefb_freeze() * savagefb_hibernate() which in turn call savagefb_suspend_late() by passing appropriate value for "pm_message_t" type parameter. - Bind the callbacks in "struct dev_pm_ops" type variable "savagefb_pm_ops". Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-8-vaibhavgupta40@gmail.com --- drivers/video/fbdev/savage/savagefb_driver.c | 52 ++++++++++++-------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 661398e40ff43..0ac750cc5ea13 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -2347,9 +2347,9 @@ static void savagefb_remove(struct pci_dev *dev) } } -static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) +static int savagefb_suspend_late(struct device *dev, pm_message_t mesg) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct savagefb_par *par = info->par; DBG("savagefb_suspend"); @@ -2357,7 +2357,7 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) if (mesg.event == PM_EVENT_PRETHAW) mesg.event = PM_EVENT_FREEZE; par->pm_state = mesg.event; - dev->dev.power.power_state = mesg; + dev->power.power_state = mesg; /* * For PM_EVENT_FREEZE, do not power down so the console @@ -2375,17 +2375,29 @@ static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg) savagefb_blank(FB_BLANK_POWERDOWN, info); savage_set_default_par(par, &par->save); savage_disable_mmio(par); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, mesg)); console_unlock(); return 0; } -static int savagefb_resume(struct pci_dev* dev) +static int __maybe_unused savagefb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + return savagefb_suspend_late(dev, PMSG_SUSPEND); +} + +static int __maybe_unused savagefb_hibernate(struct device *dev) +{ + return savagefb_suspend_late(dev, PMSG_HIBERNATE); +} + +static int __maybe_unused savagefb_freeze(struct device *dev) +{ + return savagefb_suspend_late(dev, PMSG_FREEZE); +} + +static int __maybe_unused savagefb_resume(struct device *dev) +{ + struct fb_info *info = dev_get_drvdata(dev); struct savagefb_par *par = info->par; int cur_state = par->pm_state; @@ -2397,20 +2409,11 @@ static int savagefb_resume(struct pci_dev* dev) * The adapter was not powered down coming back from a * PM_EVENT_FREEZE. */ - if (cur_state == PM_EVENT_FREEZE) { - pci_set_power_state(dev, PCI_D0); + if (cur_state == PM_EVENT_FREEZE) return 0; - } console_lock(); - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - - if (pci_enable_device(dev)) - DBG("err"); - - pci_set_master(dev); savage_enable_mmio(par); savage_init_hw(par); savagefb_set_par(info); @@ -2421,6 +2424,16 @@ static int savagefb_resume(struct pci_dev* dev) return 0; } +static const struct dev_pm_ops savagefb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = savagefb_suspend, + .resume = savagefb_resume, + .freeze = savagefb_freeze, + .thaw = savagefb_resume, + .poweroff = savagefb_hibernate, + .restore = savagefb_resume, +#endif +}; static const struct pci_device_id savagefb_devices[] = { {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128, @@ -2501,8 +2514,7 @@ static struct pci_driver savagefb_driver = { .name = "savagefb", .id_table = savagefb_devices, .probe = savagefb_probe, - .suspend = savagefb_suspend, - .resume = savagefb_resume, + .driver.pm = &savagefb_pm_ops, .remove = savagefb_remove, }; -- GitLab From c62c0f575230ae1494852b0c17740520b3327464 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:50 +0530 Subject: [PATCH 0949/1494] fbdev: cyber2000fb: use generic power management Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. This way we can remove the legacy .suspend & .resume bindings from "lxfb_driver". Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-9-vaibhavgupta40@gmail.com --- drivers/video/fbdev/cyber2000fb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c index 42d37bed518af..d45355b9a58ca 100644 --- a/drivers/video/fbdev/cyber2000fb.c +++ b/drivers/video/fbdev/cyber2000fb.c @@ -1810,7 +1810,7 @@ static void cyberpro_pci_remove(struct pci_dev *dev) } } -static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state) +static int __maybe_unused cyberpro_pci_suspend(struct device *dev) { return 0; } @@ -1818,9 +1818,9 @@ static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state) /* * Re-initialise the CyberPro hardware */ -static int cyberpro_pci_resume(struct pci_dev *dev) +static int __maybe_unused cyberpro_pci_resume(struct device *dev) { - struct cfb_info *cfb = pci_get_drvdata(dev); + struct cfb_info *cfb = dev_get_drvdata(dev); if (cfb) { cyberpro_pci_enable_mmio(cfb); @@ -1846,12 +1846,15 @@ static struct pci_device_id cyberpro_pci_table[] = { MODULE_DEVICE_TABLE(pci, cyberpro_pci_table); +static SIMPLE_DEV_PM_OPS(cyberpro_pci_pm_ops, + cyberpro_pci_suspend, + cyberpro_pci_resume); + static struct pci_driver cyberpro_driver = { .name = "CyberPro", .probe = cyberpro_pci_probe, .remove = cyberpro_pci_remove, - .suspend = cyberpro_pci_suspend, - .resume = cyberpro_pci_resume, + .driver.pm = &cyberpro_pci_pm_ops, .id_table = cyberpro_pci_table }; -- GitLab From 805a5c45ff2d51c36e90c675cd751c17632bd502 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:51 +0530 Subject: [PATCH 0950/1494] fbdev: i740fb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. The i740fb_suspend() is not designed to function in the case of Freeze. Thus, the code checked for "if (state.event == PM_EVENT_FREEZE....)". This is because, in the legacy framework, this callback was invoked even in the event of Freeze. Hence, added the load of unnecessary function-call. The goal can be achieved by binding the callback with only ".suspend" and ".poweroff" in the "i740fb_pm_ops" const variable. This also avoids the step of checking "if (state.event == PM_EVENT_FREEZE....)" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-10-vaibhavgupta40@gmail.com --- drivers/video/fbdev/i740fb.c | 40 +++++++++++++++--------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index e6f35f8feefcb..52cce0db8bd34 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -1175,16 +1175,11 @@ static void i740fb_remove(struct pci_dev *dev) } } -#ifdef CONFIG_PM -static int i740fb_suspend(struct pci_dev *dev, pm_message_t state) +static int __maybe_unused i740fb_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct i740fb_par *par = info->par; - /* don't disable console during hibernation and wakeup from it */ - if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW) - return 0; - console_lock(); mutex_lock(&(par->open_lock)); @@ -1197,19 +1192,15 @@ static int i740fb_suspend(struct pci_dev *dev, pm_message_t state) fb_set_suspend(info, 1); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - mutex_unlock(&(par->open_lock)); console_unlock(); return 0; } -static int i740fb_resume(struct pci_dev *dev) +static int __maybe_unused i740fb_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct i740fb_par *par = info->par; console_lock(); @@ -1218,11 +1209,6 @@ static int i740fb_resume(struct pci_dev *dev) if (par->ref_count == 0) goto fail; - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - if (pci_enable_device(dev)) - goto fail; - i740fb_set_par(info); fb_set_suspend(info, 0); @@ -1231,10 +1217,17 @@ static int i740fb_resume(struct pci_dev *dev) console_unlock(); return 0; } -#else -#define i740fb_suspend NULL -#define i740fb_resume NULL -#endif /* CONFIG_PM */ + +static const struct dev_pm_ops i740fb_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = i740fb_suspend, + .resume = i740fb_resume, + .freeze = NULL, + .thaw = i740fb_resume, + .poweroff = i740fb_suspend, + .restore = i740fb_resume, +#endif /* CONFIG_PM_SLEEP */ +}; #define I740_ID_PCI 0x00d1 #define I740_ID_AGP 0x7800 @@ -1251,8 +1244,7 @@ static struct pci_driver i740fb_driver = { .id_table = i740fb_id_table, .probe = i740fb_probe, .remove = i740fb_remove, - .suspend = i740fb_suspend, - .resume = i740fb_resume, + .driver.pm = &i740fb_pm_ops, }; #ifndef MODULE -- GitLab From 59d026b10a3dcd2edb5f77b6f74a119b72615270 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:52 +0530 Subject: [PATCH 0951/1494] fbdev: vt8623fb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. The vt8623_pci_suspend() is not designed to function in the case of Freeze. Thus, the code checked for "if (state.event == PM_EVENT_FREEZE....)". This is because, in the legacy framework, this callback was invoked even in the event of Freeze. Hence, added the load of unnecessary function-call. The goal can be achieved by binding the callback with only ".suspend" and ".poweroff" in the "vt8623_pci_pm_ops" const variable. This also avoids the step of checking "state.event == PM_EVENT_FREEZE" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-11-vaibhavgupta40@gmail.com --- drivers/video/fbdev/vt8623fb.c | 41 ++++++++++++++-------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/video/fbdev/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c index 98ff8235c9e99..7a959e5ba90b8 100644 --- a/drivers/video/fbdev/vt8623fb.c +++ b/drivers/video/fbdev/vt8623fb.c @@ -815,12 +815,11 @@ static void vt8623_pci_remove(struct pci_dev *dev) } -#ifdef CONFIG_PM /* PCI suspend */ -static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) +static int __maybe_unused vt8623_pci_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct vt8623fb_info *par = info->par; dev_info(info->device, "suspend\n"); @@ -828,7 +827,7 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) console_lock(); mutex_lock(&(par->open_lock)); - if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { + if (par->ref_count == 0) { mutex_unlock(&(par->open_lock)); console_unlock(); return 0; @@ -836,10 +835,6 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) fb_set_suspend(info, 1); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - mutex_unlock(&(par->open_lock)); console_unlock(); @@ -849,9 +844,9 @@ static int vt8623_pci_suspend(struct pci_dev* dev, pm_message_t state) /* PCI resume */ -static int vt8623_pci_resume(struct pci_dev* dev) +static int __maybe_unused vt8623_pci_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct vt8623fb_info *par = info->par; dev_info(info->device, "resume\n"); @@ -862,14 +857,6 @@ static int vt8623_pci_resume(struct pci_dev* dev) if (par->ref_count == 0) goto fail; - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - - if (pci_enable_device(dev)) - goto fail; - - pci_set_master(dev); - vt8623fb_set_par(info); fb_set_suspend(info, 0); @@ -879,10 +866,17 @@ static int vt8623_pci_resume(struct pci_dev* dev) return 0; } -#else -#define vt8623_pci_suspend NULL -#define vt8623_pci_resume NULL -#endif /* CONFIG_PM */ + +static const struct dev_pm_ops vt8623_pci_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = vt8623_pci_suspend, + .resume = vt8623_pci_resume, + .freeze = NULL, + .thaw = vt8623_pci_resume, + .poweroff = vt8623_pci_suspend, + .restore = vt8623_pci_resume, +#endif /* CONFIG_PM_SLEEP */ +}; /* List of boards that we are trying to support */ @@ -898,8 +892,7 @@ static struct pci_driver vt8623fb_pci_driver = { .id_table = vt8623_devices, .probe = vt8623_pci_probe, .remove = vt8623_pci_remove, - .suspend = vt8623_pci_suspend, - .resume = vt8623_pci_resume, + .driver.pm = &vt8623_pci_pm_ops, }; /* Cleanup */ -- GitLab From fb6e2db899e7483a5fb47a94cf03bd6d03e8bbe6 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:53 +0530 Subject: [PATCH 0952/1494] fbdev: s3fb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. The s3_pci_suspend() is not designed to function in the case of Freeze. Thus, the code checked for "if (state.event == PM_EVENT_FREEZE....)". This is because, in the legacy framework, this callback was invoked even in the event of Freeze. Hence, added the load of unnecessary function-call. The goal can be achieved by binding the callback with only ".suspend" and ".poweroff" in the "s3_pci_pm_ops" const variable. This also avoids the step of checking "state.event == PM_EVENT_FREEZE" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-12-vaibhavgupta40@gmail.com --- drivers/video/fbdev/s3fb.c | 39 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/video/fbdev/s3fb.c b/drivers/video/fbdev/s3fb.c index 60c424fae9883..5c74253e7b2c0 100644 --- a/drivers/video/fbdev/s3fb.c +++ b/drivers/video/fbdev/s3fb.c @@ -1410,9 +1410,9 @@ static void s3_pci_remove(struct pci_dev *dev) /* PCI suspend */ -static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) +static int __maybe_unused s3_pci_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct s3fb_info *par = info->par; dev_info(info->device, "suspend\n"); @@ -1420,7 +1420,7 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) console_lock(); mutex_lock(&(par->open_lock)); - if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { + if (par->ref_count == 0) { mutex_unlock(&(par->open_lock)); console_unlock(); return 0; @@ -1428,10 +1428,6 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) fb_set_suspend(info, 1); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - mutex_unlock(&(par->open_lock)); console_unlock(); @@ -1441,11 +1437,10 @@ static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state) /* PCI resume */ -static int s3_pci_resume(struct pci_dev* dev) +static int __maybe_unused s3_pci_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct s3fb_info *par = info->par; - int err; dev_info(info->device, "resume\n"); @@ -1458,17 +1453,6 @@ static int s3_pci_resume(struct pci_dev* dev) return 0; } - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - err = pci_enable_device(dev); - if (err) { - mutex_unlock(&(par->open_lock)); - console_unlock(); - dev_err(info->device, "error %d enabling device for resume\n", err); - return err; - } - pci_set_master(dev); - s3fb_set_par(info); fb_set_suspend(info, 0); @@ -1478,6 +1462,16 @@ static int s3_pci_resume(struct pci_dev* dev) return 0; } +static const struct dev_pm_ops s3_pci_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = s3_pci_suspend, + .resume = s3_pci_resume, + .freeze = NULL, + .thaw = s3_pci_resume, + .poweroff = s3_pci_suspend, + .restore = s3_pci_resume, +#endif +}; /* List of boards that we are trying to support */ @@ -1510,8 +1504,7 @@ static struct pci_driver s3fb_pci_driver = { .id_table = s3_devices, .probe = s3_pci_probe, .remove = s3_pci_remove, - .suspend = s3_pci_suspend, - .resume = s3_pci_resume, + .driver.pm = &s3_pci_pm_ops, }; /* Parse user specified options */ -- GitLab From a91df118990083a47ab644f8ef63f17eeae4b1ad Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 20 Aug 2020 00:26:54 +0530 Subject: [PATCH 0953/1494] fbdev: arkfb: use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. The ark_pci_suspend() is not designed to function in the case of Freeze. Thus, the code checked for "if (state.event == PM_EVENT_FREEZE....)". This is because, in the legacy framework, this callback was invoked even in the event of Freeze. Hence, added the load of unnecessary function-call. The goal can be achieved by binding the callback with only ".suspend" and ".poweroff" in the "ark_pci_pm_ops" const variable. This also avoids the step of checking "state.event == PM_EVENT_FREEZE" every time the callback is invoked. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Russell King <linux@armlinux.org.uk> Cc: Andres Salomon <dilinger@queued.net> CC: Antonino Daplas <adaplas@gmail.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819185654.151170-13-vaibhavgupta40@gmail.com --- drivers/video/fbdev/arkfb.c | 41 +++++++++++++++---------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c index 11ab9a1538608..edf169d0816e6 100644 --- a/drivers/video/fbdev/arkfb.c +++ b/drivers/video/fbdev/arkfb.c @@ -1085,12 +1085,11 @@ static void ark_pci_remove(struct pci_dev *dev) } -#ifdef CONFIG_PM /* PCI suspend */ -static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) +static int __maybe_unused ark_pci_suspend(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct arkfb_info *par = info->par; dev_info(info->device, "suspend\n"); @@ -1098,7 +1097,7 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) console_lock(); mutex_lock(&(par->open_lock)); - if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) { + if (par->ref_count == 0) { mutex_unlock(&(par->open_lock)); console_unlock(); return 0; @@ -1106,10 +1105,6 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) fb_set_suspend(info, 1); - pci_save_state(dev); - pci_disable_device(dev); - pci_set_power_state(dev, pci_choose_state(dev, state)); - mutex_unlock(&(par->open_lock)); console_unlock(); @@ -1119,9 +1114,9 @@ static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state) /* PCI resume */ -static int ark_pci_resume (struct pci_dev* dev) +static int __maybe_unused ark_pci_resume(struct device *dev) { - struct fb_info *info = pci_get_drvdata(dev); + struct fb_info *info = dev_get_drvdata(dev); struct arkfb_info *par = info->par; dev_info(info->device, "resume\n"); @@ -1132,14 +1127,6 @@ static int ark_pci_resume (struct pci_dev* dev) if (par->ref_count == 0) goto fail; - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - - if (pci_enable_device(dev)) - goto fail; - - pci_set_master(dev); - arkfb_set_par(info); fb_set_suspend(info, 0); @@ -1148,10 +1135,17 @@ static int ark_pci_resume (struct pci_dev* dev) console_unlock(); return 0; } -#else -#define ark_pci_suspend NULL -#define ark_pci_resume NULL -#endif /* CONFIG_PM */ + +static const struct dev_pm_ops ark_pci_pm_ops = { +#ifdef CONFIG_PM_SLEEP + .suspend = ark_pci_suspend, + .resume = ark_pci_resume, + .freeze = NULL, + .thaw = ark_pci_resume, + .poweroff = ark_pci_suspend, + .restore = ark_pci_resume, +#endif +}; /* List of boards that we are trying to support */ @@ -1168,8 +1162,7 @@ static struct pci_driver arkfb_pci_driver = { .id_table = ark_devices, .probe = ark_pci_probe, .remove = ark_pci_remove, - .suspend = ark_pci_suspend, - .resume = ark_pci_resume, + .driver.pm = &ark_pci_pm_ops, }; /* Cleanup */ -- GitLab From e2028c8e6bf9a12dfe83fc12ce6d5d9ab1628b0b Mon Sep 17 00:00:00 2001 From: Sven Schneider <s.schneider@arkona-technologies.de> Date: Thu, 20 Aug 2020 10:21:37 +0200 Subject: [PATCH 0954/1494] lib/fonts: add font 6x8 for OLED display This font is derived from lib/fonts/font_6x10.c and is useful for small OLED displays Signed-off-by: Sven Schneider <s.schneider@arkona-technologies.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200820082137.5907-1-s.hauer@pengutronix.de --- include/linux/font.h | 4 +- lib/fonts/Kconfig | 7 + lib/fonts/Makefile | 1 + lib/fonts/font_6x8.c | 2576 ++++++++++++++++++++++++++++++++++++++++++ lib/fonts/fonts.c | 3 + 5 files changed, 2590 insertions(+), 1 deletion(-) create mode 100644 lib/fonts/font_6x8.c diff --git a/include/linux/font.h b/include/linux/font.h index 51b91c8b69d58..4a3f8741bb7e5 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -33,6 +33,7 @@ struct font_desc { #define MINI4x6_IDX 9 #define FONT6x10_IDX 10 #define TER16x32_IDX 11 +#define FONT6x8_IDX 12 extern const struct font_desc font_vga_8x8, font_vga_8x16, @@ -45,7 +46,8 @@ extern const struct font_desc font_vga_8x8, font_acorn_8x8, font_mini_4x6, font_6x10, - font_ter_16x32; + font_ter_16x32, + font_6x8; /* Find a font with a specific name */ diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig index 37baa79cdd71f..c035fde66aebe 100644 --- a/lib/fonts/Kconfig +++ b/lib/fonts/Kconfig @@ -119,6 +119,12 @@ config FONT_TER16x32 This is the high resolution, large version for use with HiDPI screens. If the standard font is unreadable for you, say Y, otherwise say N. +config FONT_6x8 + bool "OLED 6x8 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + help + This font is useful for small displays (OLED). + config FONT_AUTOSELECT def_bool y depends on !FONT_8x8 @@ -132,6 +138,7 @@ config FONT_AUTOSELECT depends on !FONT_SUN12x22 depends on !FONT_10x18 depends on !FONT_TER16x32 + depends on !FONT_6x8 select FONT_8x16 endif # FONT_SUPPORT diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile index ed95070860deb..e16f68492174a 100644 --- a/lib/fonts/Makefile +++ b/lib/fonts/Makefile @@ -15,6 +15,7 @@ font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o font-objs-$(CONFIG_FONT_6x10) += font_6x10.o font-objs-$(CONFIG_FONT_TER16x32) += font_ter16x32.o +font-objs-$(CONFIG_FONT_6x8) += font_6x8.o font-objs += $(font-objs-y) diff --git a/lib/fonts/font_6x8.c b/lib/fonts/font_6x8.c new file mode 100644 index 0000000000000..e064477884186 --- /dev/null +++ b/lib/fonts/font_6x8.c @@ -0,0 +1,2576 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/font.h> + +#define FONTDATAMAX 2048 + +static const unsigned char fontdata_6x8[FONTDATAMAX] = { + + /* 0 0x00 '^@' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 1 0x01 '^A' */ + 0x78, /* 011110 */ + 0x84, /* 100001 */ + 0xCC, /* 110011 */ + 0x84, /* 100001 */ + 0xCC, /* 110011 */ + 0xB4, /* 101101 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 2 0x02 '^B' */ + 0x78, /* 011110 */ + 0xFC, /* 111111 */ + 0xB4, /* 101101 */ + 0xFC, /* 111111 */ + 0xB4, /* 101101 */ + 0xCC, /* 110011 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x6C, /* 011011 */ + 0x6C, /* 011011 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x78, /* 011110 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 8 0x08 '^H' */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xCC, /* 110011 */ + 0x84, /* 100001 */ + 0xCC, /* 110011 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x84, /* 100001 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 10 0x0A '^J' */ + 0xFC, /* 111111 */ + 0xCC, /* 110011 */ + 0xB4, /* 101101 */ + 0x78, /* 011110 */ + 0xB4, /* 101101 */ + 0xCC, /* 110011 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + + /* 11 0x0B '^K' */ + 0x3C, /* 001111 */ + 0x14, /* 000101 */ + 0x20, /* 001000 */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 12 0x0C '^L' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 13 0x0D '^M' */ + 0x18, /* 000110 */ + 0x14, /* 000101 */ + 0x14, /* 000101 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x70, /* 011100 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ + + /* 14 0x0E '^N' */ + 0x3C, /* 001111 */ + 0x24, /* 001001 */ + 0x3C, /* 001111 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x6C, /* 011011 */ + 0x6C, /* 011011 */ + 0x00, /* 000000 */ + + /* 15 0x0F '^O' */ + 0x10, /* 000100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x6C, /* 011011 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 16 0x10 '^P' */ + 0x40, /* 010000 */ + 0x60, /* 011000 */ + 0x70, /* 011100 */ + 0x78, /* 011110 */ + 0x70, /* 011100 */ + 0x60, /* 011000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 17 0x11 '^Q' */ + 0x04, /* 000001 */ + 0x0C, /* 000011 */ + 0x1C, /* 000111 */ + 0x3C, /* 001111 */ + 0x1C, /* 000111 */ + 0x0C, /* 000011 */ + 0x04, /* 000001 */ + 0x00, /* 000000 */ + + /* 18 0x12 '^R' */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x10, /* 000100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 19 0x13 '^S' */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + + /* 20 0x14 '^T' */ + 0x3C, /* 001111 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x3C, /* 001111 */ + 0x14, /* 000101 */ + 0x14, /* 000101 */ + 0x14, /* 000101 */ + 0x00, /* 000000 */ + + /* 21 0x15 '^U' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x30, /* 001100 */ + 0x28, /* 001010 */ + 0x14, /* 000101 */ + 0x0C, /* 000011 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + + /* 22 0x16 '^V' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF8, /* 111110 */ + 0xF8, /* 111110 */ + 0xF8, /* 111110 */ + 0x00, /* 000000 */ + + /* 23 0x17 '^W' */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x10, /* 000100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + + /* 24 0x18 '^X' */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 25 0x19 '^Y' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 26 0x1A '^Z' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x7C, /* 011111 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 27 0x1B '^[' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x7C, /* 011111 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 28 0x1C '^\' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 29 0x1D '^]' */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x84, /* 100001 */ + 0xFC, /* 111111 */ + 0x84, /* 100001 */ + 0x48, /* 010010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 30 0x1E '^^' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 31 0x1F '^_' */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x7C, /* 011111 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 33 0x21 '!' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 34 0x22 '"' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + + /* 36 0x24 '$' */ + 0x10, /* 000000 */ + 0x38, /* 001000 */ + 0x40, /* 010000 */ + 0x30, /* 001000 */ + 0x08, /* 000000 */ + 0x70, /* 011000 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + + /* 37 0x25 '%' */ + 0x64, /* 011001 */ + 0x64, /* 011001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x4C, /* 010011 */ + 0x4C, /* 010011 */ + 0x00, /* 000000 */ + + /* 38 0x26 '&' */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x50, /* 010100 */ + 0x20, /* 001000 */ + 0x54, /* 010101 */ + 0x48, /* 010010 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 39 0x27 ''' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 40 0x28 '(' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x20, /* 001000 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + + /* 41 0x29 ')' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + + /* 42 0x2A '*' */ + 0x10, /* 000100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 43 0x2B '+' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 44 0x2C ',' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x30, /* 001100 */ + 0x20, /* 001000 */ + + /* 45 0x2D '-' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 46 0x2E '.' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + + /* 47 0x2F '/' */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x20, /* 001000 */ + 0x40, /* 010000 */ + + /* 48 0x30 '0' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x54, /* 010101 */ + 0x64, /* 011001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 49 0x31 '1' */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ + 0x50, /* 010100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 50 0x32 '2' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 51 0x33 '3' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x04, /* 000001 */ + 0x18, /* 000110 */ + 0x04, /* 000001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 52 0x34 '4' */ + 0x08, /* 000010 */ + 0x18, /* 000110 */ + 0x28, /* 001010 */ + 0x48, /* 010010 */ + 0x7C, /* 011111 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + + /* 53 0x35 '5' */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 54 0x36 '6' */ + 0x18, /* 000110 */ + 0x20, /* 001000 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 55 0x37 '7' */ + 0x7C, /* 011111 */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 56 0x38 '8' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 57 0x39 '9' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + + /* 58 0x3A ':' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x18, /* 000110 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + + /* 59 0x3B ';' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x30, /* 001100 */ + 0x20, /* 001000 */ + + /* 60 0x3C '<' */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x04, /* 000001 */ + 0x00, /* 000000 */ + + /* 61 0x3D '=' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 62 0x3E '>' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + + /* 63 0x3F '?' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 64 0x40 '@' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x5C, /* 010111 */ + 0x54, /* 010101 */ + 0x5C, /* 010111 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 65 0x41 'A' */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 66 0x42 'B' */ + 0x78, /* 011110 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x38, /* 001110 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 67 0x43 'C' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 68 0x44 'D' */ + 0x78, /* 011110 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 69 0x45 'E' */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 70 0x46 'F' */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 71 0x47 'G' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x5C, /* 010111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 72 0x48 'H' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 73 0x49 'I' */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 74 0x4A 'J' */ + 0x1C, /* 000111 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + + /* 75 0x4B 'K' */ + 0x44, /* 010001 */ + 0x48, /* 010010 */ + 0x50, /* 010100 */ + 0x60, /* 011000 */ + 0x50, /* 010100 */ + 0x48, /* 010010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 76 0x4C 'L' */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 77 0x4D 'M' */ + 0x44, /* 010001 */ + 0x6C, /* 011011 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 78 0x4E 'N' */ + 0x44, /* 010001 */ + 0x64, /* 011001 */ + 0x54, /* 010101 */ + 0x4C, /* 010011 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 79 0x4F 'O' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 80 0x50 'P' */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 81 0x51 'Q' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x54, /* 010101 */ + 0x48, /* 010010 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 82 0x52 'R' */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x50, /* 010100 */ + 0x48, /* 010010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 83 0x53 'S' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 84 0x54 'T' */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 85 0x55 'U' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 86 0x56 'V' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 87 0x57 'W' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x6C, /* 011011 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 88 0x58 'X' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 89 0x59 'Y' */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 90 0x5A 'Z' */ + 0x7C, /* 011111 */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 91 0x5B '[' */ + 0x18, /* 000110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + + /* 92 0x5C '\' */ + 0x40, /* 010000 */ + 0x20, /* 001000 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x04, /* 000001 */ + + /* 93 0x5D ']' */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + + /* 94 0x5E '^' */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 95 0x5F '_' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + + /* 96 0x60 '`' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 98 0x62 'b' */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x58, /* 010110 */ + 0x64, /* 011001 */ + 0x44, /* 010001 */ + 0x64, /* 011001 */ + 0x58, /* 010110 */ + 0x00, /* 000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 100 0x64 'd' */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + 0x34, /* 001101 */ + 0x4C, /* 010011 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 102 0x66 'f' */ + 0x0C, /* 000011 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 000000 */ + 0x34, /* 001101 */ + 0x4C, /* 010011 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x04, /* 000001 */ + 0x38, /* 001110 */ + + /* 104 0x68 'h' */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 105 0x69 'i' */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 106 0x6A 'j' */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x60, /* 011000 */ + + /* 107 0x6B 'k' */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x48, /* 010010 */ + 0x50, /* 010100 */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 108 0x6C 'l' */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 109 0x6D 'm' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x68, /* 011010 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x00, /* 000000 */ + + /* 110 0x6E 'n' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x58, /* 010110 */ + 0x64, /* 011001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 111 0x6F 'o' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x44, /* 010001 */ + 0x64, /* 011001 */ + 0x58, /* 010110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + + /* 113 0x71 'q' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + + /* 114 0x72 'r' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x58, /* 010110 */ + 0x64, /* 011001 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 115 0x73 's' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 116 0x74 't' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x0C, /* 000011 */ + 0x00, /* 000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x04, /* 000001 */ + 0x38, /* 001110 */ + + /* 122 0x7A 'z' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 123 0x7B '{' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + + /* 124 0x7C '|' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 125 0x7D '}' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + + /* 126 0x7E '~' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x20, /* 001000 */ + 0x54, /* 010101 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 127 0x7F '' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 128 0x80 '\200' */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + + /* 129 0x81 '\201' */ + 0x00, /* 000000 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 130 0x82 '\202' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 131 0x83 '\203' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 132 0x84 '\204' */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 133 0x85 '\205' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 134 0x86 '\206' */ + 0x3C, /* 001111 */ + 0x18, /* 000110 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 135 0x87 '\207' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + + /* 136 0x88 '\210' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 137 0x89 '\211' */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 138 0x8A '\212' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 139 0x8B '\213' */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 140 0x8C '\214' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 141 0x8D '\215' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 142 0x8E '\216' */ + 0x44, /* 010001 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 143 0x8F '\217' */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 144 0x90 '\220' */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x78, /* 011110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 145 0x91 '\221' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x78, /* 011110 */ + 0x14, /* 000101 */ + 0x7C, /* 011111 */ + 0x50, /* 010100 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 146 0x92 '\222' */ + 0x3C, /* 001111 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x78, /* 011110 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x5C, /* 010111 */ + 0x00, /* 000000 */ + + /* 147 0x93 '\223' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 148 0x94 '\224' */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 149 0x95 '\225' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 150 0x96 '\226' */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 151 0x97 '\227' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 152 0x98 '\230' */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x04, /* 000001 */ + 0x38, /* 001110 */ + + /* 153 0x99 '\231' */ + 0x84, /* 100001 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 154 0x9A '\232' */ + 0x88, /* 100010 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 155 0x9B '\233' */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x50, /* 010100 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 156 0x9C '\234' */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x40, /* 010000 */ + 0x70, /* 011100 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x78, /* 011110 */ + 0x00, /* 000000 */ + + /* 157 0x9D '\235' */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 158 0x9E '\236' */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x70, /* 011100 */ + 0x48, /* 010010 */ + 0x5C, /* 010111 */ + 0x48, /* 010010 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 159 0x9F '\237' */ + 0x0C, /* 000011 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x60, /* 011000 */ + 0x00, /* 000000 */ + + /* 160 0xA0 '\240' */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 161 0xA1 '\241' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x30, /* 001100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 162 0xA2 '\242' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 163 0xA3 '\243' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x4C, /* 010011 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 164 0xA4 '\244' */ + 0x34, /* 001101 */ + 0x58, /* 010110 */ + 0x00, /* 000000 */ + 0x58, /* 010110 */ + 0x64, /* 011001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 165 0xA5 '\245' */ + 0x58, /* 010110 */ + 0x44, /* 010001 */ + 0x64, /* 011001 */ + 0x54, /* 010101 */ + 0x4C, /* 010011 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 166 0xA6 '\246' */ + 0x38, /* 001110 */ + 0x04, /* 000001 */ + 0x3C, /* 001111 */ + 0x44, /* 010001 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 167 0xA7 '\247' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 168 0xA8 '\250' */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x40, /* 010000 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 169 0xA9 '\251' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 170 0xAA '\252' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x04, /* 000001 */ + 0x04, /* 000001 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 171 0xAB '\253' */ + 0x20, /* 001000 */ + 0x24, /* 001001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x44, /* 010001 */ + 0x08, /* 000010 */ + 0x1C, /* 000111 */ + + /* 172 0xAC '\254' */ + 0x20, /* 001000 */ + 0x24, /* 001001 */ + 0x28, /* 001010 */ + 0x10, /* 000100 */ + 0x28, /* 001010 */ + 0x58, /* 010110 */ + 0x3C, /* 001111 */ + 0x08, /* 000010 */ + + /* 173 0xAD '\255' */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + + /* 174 0xAE '\256' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x24, /* 001001 */ + 0x48, /* 010010 */ + 0x90, /* 100100 */ + 0x48, /* 010010 */ + 0x24, /* 001001 */ + 0x00, /* 000000 */ + + /* 175 0xAF '\257' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x90, /* 100100 */ + 0x48, /* 010010 */ + 0x24, /* 001001 */ + 0x48, /* 010010 */ + 0x90, /* 100100 */ + 0x00, /* 000000 */ + + /* 176 0xB0 '\260' */ + 0x10, /* 000100 */ + 0x44, /* 010001 */ + 0x10, /* 000100 */ + 0x44, /* 010001 */ + 0x10, /* 000100 */ + 0x44, /* 010001 */ + 0x10, /* 000100 */ + 0x44, /* 010001 */ + + /* 177 0xB1 '\261' */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + 0xA8, /* 101010 */ + 0x54, /* 010101 */ + + /* 178 0xB2 '\262' */ + 0xDC, /* 110111 */ + 0x74, /* 011101 */ + 0xDC, /* 110111 */ + 0x74, /* 011101 */ + 0xDC, /* 110111 */ + 0x74, /* 011101 */ + 0xDC, /* 110111 */ + 0x74, /* 011101 */ + + /* 179 0xB3 '\263' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 180 0xB4 '\264' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 181 0xB5 '\265' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 182 0xB6 '\266' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xE8, /* 111010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 183 0xB7 '\267' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF8, /* 111110 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 184 0xB8 '\270' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 185 0xB9 '\271' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xE8, /* 111010 */ + 0x08, /* 000010 */ + 0xE8, /* 111010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 186 0xBA '\272' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 187 0xBB '\273' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF8, /* 111110 */ + 0x08, /* 000010 */ + 0xE8, /* 111010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 188 0xBC '\274' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xE8, /* 111010 */ + 0x08, /* 000010 */ + 0xF8, /* 111110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 189 0xBD '\275' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xF8, /* 111110 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 190 0xBE '\276' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 191 0xBF '\277' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xF0, /* 111100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 192 0xC0 '\300' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 193 0xC1 '\301' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 194 0xC2 '\302' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 195 0xC3 '\303' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 196 0xC4 '\304' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 197 0xC5 '\305' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 198 0xC6 '\306' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 199 0xC7 '\307' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x2C, /* 001011 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 200 0xC8 '\310' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x2C, /* 001011 */ + 0x20, /* 001000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 201 0xC9 '\311' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x20, /* 001000 */ + 0x2C, /* 001011 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 202 0xCA '\312' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xEC, /* 111011 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 203 0xCB '\313' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xEC, /* 111011 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 204 0xCC '\314' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x2C, /* 001011 */ + 0x20, /* 001000 */ + 0x2C, /* 001011 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 205 0xCD '\315' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 206 0xCE '\316' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xEC, /* 111011 */ + 0x00, /* 000000 */ + 0xEC, /* 111011 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 207 0xCF '\317' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 208 0xD0 '\320' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 209 0xD1 '\321' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 210 0xD2 '\322' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 211 0xD3 '\323' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 212 0xD4 '\324' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 213 0xD5 '\325' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 214 0xD6 '\326' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 215 0xD7 '\327' */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0xFC, /* 111111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + + /* 216 0xD8 '\330' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0xFC, /* 111111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 217 0xD9 '\331' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0xF0, /* 111100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 218 0xDA '\332' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x1C, /* 000111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 219 0xDB '\333' */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + + /* 220 0xDC '\334' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + + /* 221 0xDD '\335' */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + 0xE0, /* 111000 */ + + /* 222 0xDE '\336' */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + 0x1C, /* 000111 */ + + /* 223 0xDF '\337' */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 224 0xE0 '\340' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x34, /* 001101 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x34, /* 001101 */ + 0x00, /* 000000 */ + + /* 225 0xE1 '\341' */ + 0x24, /* 001001 */ + 0x44, /* 010001 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x58, /* 010110 */ + 0x40, /* 010000 */ + + /* 226 0xE2 '\342' */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 227 0xE3 '\343' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x28, /* 001010 */ + 0x00, /* 000000 */ + + /* 228 0xE4 '\344' */ + 0x7C, /* 011111 */ + 0x24, /* 001001 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x24, /* 001001 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 229 0xE5 '\345' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x3C, /* 001111 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + + /* 230 0xE6 '\346' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x74, /* 011101 */ + 0x40, /* 010000 */ + + /* 231 0xE7 '\347' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x0C, /* 000011 */ + 0x00, /* 000000 */ + + /* 232 0xE8 '\350' */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 233 0xE9 '\351' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x7C, /* 011111 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 234 0xEA '\352' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x28, /* 001010 */ + 0x6C, /* 011011 */ + 0x00, /* 000000 */ + + /* 235 0xEB '\353' */ + 0x18, /* 000110 */ + 0x20, /* 001000 */ + 0x18, /* 000110 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x24, /* 001001 */ + 0x18, /* 000110 */ + 0x00, /* 000000 */ + + /* 236 0xEC '\354' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 237 0xED '\355' */ + 0x00, /* 000000 */ + 0x04, /* 000001 */ + 0x38, /* 001110 */ + 0x54, /* 010101 */ + 0x54, /* 010101 */ + 0x38, /* 001110 */ + 0x40, /* 010000 */ + 0x00, /* 000000 */ + + /* 238 0xEE '\356' */ + 0x3C, /* 001111 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x38, /* 001110 */ + 0x40, /* 010000 */ + 0x40, /* 010000 */ + 0x3C, /* 001111 */ + 0x00, /* 000000 */ + + /* 239 0xEF '\357' */ + 0x38, /* 001110 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x44, /* 010001 */ + 0x00, /* 000000 */ + + /* 240 0xF0 '\360' */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0xFC, /* 111111 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 241 0xF1 '\361' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x7C, /* 011111 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + + /* 242 0xF2 '\362' */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 243 0xF3 '\363' */ + 0x08, /* 000010 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x10, /* 000100 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 244 0xF4 '\364' */ + 0x0C, /* 000011 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + + /* 245 0xF5 '\365' */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x10, /* 000100 */ + 0x60, /* 011000 */ + + /* 246 0xF6 '\366' */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x7C, /* 011111 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 247 0xF7 '\367' */ + 0x00, /* 000000 */ + 0x20, /* 001000 */ + 0x54, /* 010101 */ + 0x08, /* 000010 */ + 0x20, /* 001000 */ + 0x54, /* 010101 */ + 0x08, /* 000010 */ + 0x00, /* 000000 */ + + /* 248 0xF8 '\370' */ + 0x30, /* 001100 */ + 0x48, /* 010010 */ + 0x48, /* 010010 */ + 0x30, /* 001100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 249 0xF9 '\371' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x38, /* 001110 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 250 0xFA '\372' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x10, /* 000100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 251 0xFB '\373' */ + 0x04, /* 000001 */ + 0x08, /* 000010 */ + 0x08, /* 000010 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x20, /* 001000 */ + 0x20, /* 001000 */ + 0x00, /* 000000 */ + + /* 252 0xFC '\374' */ + 0x60, /* 011000 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x50, /* 010100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 253 0xFD '\375' */ + 0x60, /* 011000 */ + 0x10, /* 000100 */ + 0x20, /* 001000 */ + 0x70, /* 011100 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + + /* 254 0xFE '\376' */ + 0x00, /* 000000 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x38, /* 001110 */ + 0x00, /* 000000 */ + + /* 255 0xFF '\377' */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ + 0x00, /* 000000 */ +}; + +const struct font_desc font_6x8 = { + .idx = FONT6x8_IDX, + .name = "6x8", + .width = 6, + .height = 8, + .data = fontdata_6x8, + .pref = 0, +}; diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c index e7258d8c252b2..5f4b07b56cd9c 100644 --- a/lib/fonts/fonts.c +++ b/lib/fonts/fonts.c @@ -57,6 +57,9 @@ static const struct font_desc *fonts[] = { #ifdef CONFIG_FONT_TER16x32 &font_ter_16x32, #endif +#ifdef CONFIG_FONT_6x8 + &font_6x8, +#endif }; #define num_fonts ARRAY_SIZE(fonts) -- GitLab From 3f9dfc2a0ea9f8f34229d43e3a171c8aaf1dcaf4 Mon Sep 17 00:00:00 2001 From: Bilal Wasim <bilalwasim676@gmail.com> Date: Mon, 24 Aug 2020 19:51:55 +0500 Subject: [PATCH 0955/1494] docs: fb: Correcting the location of FRAMEBUFFER_CONSOLE option. fbcon doc mentions FRAMEBUFFER_CONSOLE option to be under Device Drivers->Graphics Support->Frame buffer Devices-> Console display driver support->Framebuffer Console Support, while its under Device Drivers->Graphics Support-> Console display driver support->Framebuffer Console Support. Correcting it in the docs. Signed-off-by: Bilal Wasim <bilalwasim676@gmail.com> Cc: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200824145155.42502-1-bilalwasim676@gmail.com --- Documentation/fb/fbcon.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/fb/fbcon.rst b/Documentation/fb/fbcon.rst index e57a3d1d085ad..a7b487cba307e 100644 --- a/Documentation/fb/fbcon.rst +++ b/Documentation/fb/fbcon.rst @@ -20,8 +20,8 @@ A. Configuration ================ The framebuffer console can be enabled by using your favorite kernel -configuration tool. It is under Device Drivers->Graphics Support->Frame -buffer Devices->Console display driver support->Framebuffer Console Support. +configuration tool. It is under Device Drivers->Graphics Support-> +Console display driver support->Framebuffer Console Support. Select 'y' to compile support statically or 'm' for module support. The module will be fbcon. -- GitLab From 3f614236406f4642306b59a5659760ebf0ce9087 Mon Sep 17 00:00:00 2001 From: Alex Dewar <alex.dewar90@gmail.com> Date: Mon, 24 Aug 2020 18:44:03 +0100 Subject: [PATCH 0956/1494] video: fbdev: sstfb: replace spurious snprintf() with sprintf() par->vgapass is a u8, so if we are assuming that buf is at least PAGE_SIZE then the extra checking is pointless. Signed-off-by: Alex Dewar <alex.dewar90@gmail.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jani Nikula <jani.nikula@intel.com> Cc: Arnd Bergmann <arnd@arndb.de> [b.zolnierkie: minor patch summary fixup] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200824174407.429817-1-alex.dewar90@gmail.com --- drivers/video/fbdev/sstfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index afe6d1b7c3a0d..c05cdabeb11c2 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -733,7 +733,7 @@ static ssize_t show_vgapass(struct device *device, struct device_attribute *attr { struct fb_info *info = dev_get_drvdata(device); struct sstfb_par *par = info->par; - return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass); + return sprintf(buf, "%d\n", par->vgapass); } static struct device_attribute device_attrs[] = { -- GitLab From 925896486522e5f3f9cac1ea5c3a659247cca223 Mon Sep 17 00:00:00 2001 From: Joe Perches <joe@perches.com> Date: Mon, 24 Aug 2020 21:56:19 -0700 Subject: [PATCH 0957/1494] video: fbdev: tgafb: Avoid comma separated statements Use semicolons and braces. Signed-off-by: Joe Perches <joe@perches.com> Cc: Jiri Kosina <trivial@kernel.org> [b.zolnierkie: minor patch summary fixup] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/ <3e56046e67e583ac93030297ff6d58c08ca54086.1598331149.git.joe@perches.com --- drivers/video/fbdev/tgafb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c index e9869135d833a..666fbe2f671c9 100644 --- a/drivers/video/fbdev/tgafb.c +++ b/drivers/video/fbdev/tgafb.c @@ -989,8 +989,10 @@ tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) /* We can fill 2k pixels per operation. Notice blocks that fit the width of the screen so that we can take advantage of this and fill more than one line per write. */ - if (width == line_length) - width *= height, height = 1; + if (width == line_length) { + width *= height; + height = 1; + } /* The write into the frame buffer must be aligned to 4 bytes, but we are allowed to encode the offset within the word in @@ -1171,8 +1173,10 @@ copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy, More than anything else, these control how we do copies. */ depos = dy * line_length + dx; sepos = sy * line_length + sx; - if (backward) - depos += width, sepos += width; + if (backward) { + depos += width; + sepos += width; + } /* Next copy full words at a time. */ n32 = width / 32; -- GitLab From fe6c6a4af2be8c15bac77f7ea160f947c04840d1 Mon Sep 17 00:00:00 2001 From: Dinghao Liu <dinghao.liu@zju.edu.cn> Date: Tue, 25 Aug 2020 14:29:00 +0800 Subject: [PATCH 0958/1494] video: fbdev: radeon: Fix memleak in radeonfb_pci_register When radeon_kick_out_firmware_fb() fails, info should be freed just like the subsequent error paths. Fixes: 069ee21a82344 ("fbdev: Fix loading of module radeonfb on PowerMac") Signed-off-by: Dinghao Liu <dinghao.liu@zju.edu.cn> Reviewed-by: Mathieu Malaterre <malat@debian.org> Cc: Kangjie Lu <kjlu@umn.edu> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200825062900.11210-1-dinghao.liu@zju.edu.cn --- drivers/video/fbdev/aty/radeon_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index 3fe509cb9b874..13bd2bd5c043a 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -2307,7 +2307,7 @@ static int radeonfb_pci_register(struct pci_dev *pdev, ret = radeon_kick_out_firmware_fb(pdev); if (ret) - return ret; + goto err_release_fb; /* request the mem regions */ ret = pci_request_region(pdev, 0, "radeonfb framebuffer"); -- GitLab From 6bfea83eec8e266ffe0da90037c17bca5e698eb4 Mon Sep 17 00:00:00 2001 From: kernel test robot <lkp@intel.com> Date: Wed, 26 Aug 2020 22:54:05 +0200 Subject: [PATCH 0959/1494] video: fbdev: udlfb: fix kobj_to_dev.cocci warnings Use kobj_to_dev() instead of container_of() Generated by: scripts/coccinelle/api/kobj_to_dev.cocci Cc: Denis Efremov <efremov@linux.com> Signed-off-by: kernel test robot <lkp@intel.com> Signed-off-by: Julia Lawall <julia.lawall@inria.fr> Cc: Bernie Thompson <bernie@plugable.com> [b.zolnierkie: minor patch summary fixup] [b.zolnierkie: removed "Fixes:" tag (not in upstream tree)] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/alpine.DEB.2.22.394.2008262252270.2522@hadrien --- drivers/video/fbdev/udlfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index 5b014b479f831..f9b3c1cb9530f 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -1457,7 +1457,7 @@ static ssize_t edid_show( struct file *filp, struct kobject *kobj, struct bin_attribute *a, char *buf, loff_t off, size_t count) { - struct device *fbdev = container_of(kobj, struct device, kobj); + struct device *fbdev = kobj_to_dev(kobj); struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dlfb = fb_info->par; @@ -1479,7 +1479,7 @@ static ssize_t edid_store( struct file *filp, struct kobject *kobj, struct bin_attribute *a, char *src, loff_t src_off, size_t src_size) { - struct device *fbdev = container_of(kobj, struct device, kobj); + struct device *fbdev = kobj_to_dev(kobj); struct fb_info *fb_info = dev_get_drvdata(fbdev); struct dlfb_data *dlfb = fb_info->par; int ret; -- GitLab From 1c46f4e44af937c8dd8cd068ed1241553b47778b Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Thu, 27 Aug 2020 21:00:08 +0800 Subject: [PATCH 0960/1494] video: fbdev: kyro: remove set but not used 'ulBestVCO' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This addresses the following gcc warning with "make W=1": drivers/video/fbdev/kyro/STG4000InitDevice.c: In function ‘ProgramClock’: drivers/video/fbdev/kyro/STG4000InitDevice.c:123:6: warning: variable ‘ulBestVCO’ set but not used [-Wunused-but-set-variable] 123 | u32 ulBestVCO = 0, ulBestClk = 0, ulBestScore = 0; | ^~~~~~~~~ Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> [b.zolnierkie: minor patch summary fixup] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200827130008.428706-1-yanaijie@huawei.com --- drivers/video/fbdev/kyro/STG4000InitDevice.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/video/fbdev/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c index 1d3f2080aa6f4..39438ba66ddcf 100644 --- a/drivers/video/fbdev/kyro/STG4000InitDevice.c +++ b/drivers/video/fbdev/kyro/STG4000InitDevice.c @@ -120,7 +120,7 @@ u32 ProgramClock(u32 refClock, { u32 R = 0, F = 0, OD = 0, ODIndex = 0; u32 ulBestR = 0, ulBestF = 0, ulBestOD = 0; - u32 ulBestVCO = 0, ulBestClk = 0, ulBestScore = 0; + u32 ulBestClk = 0, ulBestScore = 0; u32 ulScore, ulPhaseScore, ulVcoScore; u32 ulTmp = 0, ulVCO; u32 ulScaleClockReq, ulMinClock, ulMaxClock; @@ -189,7 +189,6 @@ u32 ProgramClock(u32 refClock, ulScore = ulPhaseScore + ulVcoScore; if (!ulBestScore) { - ulBestVCO = ulVCO; ulBestOD = OD; ulBestF = F; ulBestR = R; @@ -206,7 +205,6 @@ u32 ProgramClock(u32 refClock, but we shall keep this code in case new restrictions come into play --------------------------------------------------------------------------*/ if ((ulScore >= ulBestScore) && (OD > 0)) { - ulBestVCO = ulVCO; ulBestOD = OD; ulBestF = F; ulBestR = R; -- GitLab From 28657c307160234f37f3182c6f3ddd7e22ebf1fc Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Thu, 27 Aug 2020 21:00:28 +0800 Subject: [PATCH 0961/1494] video: fbdev: kyro: remove set but not used 'ulCoreClock' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This addresses the following gcc warning with "make W=1": drivers/video/fbdev/kyro/STG4000InitDevice.c: In function ‘SetCoreClockPLL’: drivers/video/fbdev/kyro/STG4000InitDevice.c:247:6: warning: variable ‘ulCoreClock’ set but not used [-Wunused-but-set-variable] // yanaijie fixed 247 | u32 ulCoreClock; | ^~~~~~~~~~~ Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> [b.zolnierkie: minor patch summary fixup] Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200827130028.428893-1-yanaijie@huawei.com --- drivers/video/fbdev/kyro/STG4000InitDevice.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/video/fbdev/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c index 39438ba66ddcf..21875d3c2dc20 100644 --- a/drivers/video/fbdev/kyro/STG4000InitDevice.c +++ b/drivers/video/fbdev/kyro/STG4000InitDevice.c @@ -242,7 +242,6 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev) { u32 F, R, P; u16 core_pll = 0, sub; - u32 ulCoreClock; u32 tmp; u32 ulChipSpeed; @@ -280,7 +279,7 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev) if (ulChipSpeed == 0) return -EINVAL; - ulCoreClock = ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P); + ProgramClock(REF_FREQ, CORE_PLL_FREQ, &F, &R, &P); core_pll |= ((P) | ((F - 2) << 2) | ((R - 2) << 11)); -- GitLab From 5c15291223949763c13f8c79279dc9700069a2bc Mon Sep 17 00:00:00 2001 From: Mike Rapoport <rppt@linux.ibm.com> Date: Sun, 30 Aug 2020 14:55:24 +0300 Subject: [PATCH 0962/1494] fbdev: remove mbx framebuffer driver The only in-tree user for mbx driver for Intel 2700G graphics chip was cm-x270 platform. Since this platform was removed by the commit 9d3239147d6d ("ARM: pxa: remove Compulab pxa2xx boards") there is no point to keep the obsolete framebuffer driver. Signed-off-by: Mike Rapoport <rppt@linux.ibm.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200830115524.431278-1-rppt@kernel.org --- .../userspace-api/ioctl/ioctl-number.rst | 2 - drivers/video/fbdev/Kconfig | 19 - drivers/video/fbdev/Makefile | 1 - drivers/video/fbdev/mbx/Makefile | 4 - drivers/video/fbdev/mbx/mbxdebugfs.c | 232 ---- drivers/video/fbdev/mbx/mbxfb.c | 1053 ----------------- drivers/video/fbdev/mbx/reg_bits.h | 614 ---------- drivers/video/fbdev/mbx/regs.h | 196 --- include/video/mbxfb.h | 99 -- 9 files changed, 2220 deletions(-) delete mode 100644 drivers/video/fbdev/mbx/Makefile delete mode 100644 drivers/video/fbdev/mbx/mbxdebugfs.c delete mode 100644 drivers/video/fbdev/mbx/mbxfb.c delete mode 100644 drivers/video/fbdev/mbx/reg_bits.h delete mode 100644 drivers/video/fbdev/mbx/regs.h delete mode 100644 include/video/mbxfb.h diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 2a198838fca91..a20102f7db69a 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -356,8 +356,6 @@ Code Seq# Include File Comments 0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver 0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development) <mailto:thomas@winischhofer.net> -0xF4 00-1F video/mbxfb.h mbxfb - <mailto:raph@8d.com> 0xF6 all LTTng Linux Trace Toolkit Next Generation <mailto:mathieu.desnoyers@efficios.com> 0xFD all linux/dm-ioctl.h diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index b2c9dd4f0cb5e..e36578258b5bb 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1775,25 +1775,6 @@ config PXA3XX_GCU If you compile this as a module, it will be called pxa3xx_gcu. -config FB_MBX - tristate "2700G LCD framebuffer support" - depends on FB && ARCH_PXA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Framebuffer driver for the Intel 2700G (Marathon) Graphics - Accelerator - -config FB_MBX_DEBUG - bool "Enable debugging info via debugfs" - depends on FB_MBX && DEBUG_FS - help - Enable this if you want debugging information using the debug - filesystem (debugfs) - - If unsure, say N. - config FB_FSL_DIU tristate "Freescale DIU framebuffer support" depends on FB && FSL_SOC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index cad4fb64442a1..2ff8849ffde61 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -31,7 +31,6 @@ obj-$(CONFIG_FB_VIA) += via/ obj-$(CONFIG_FB_KYRO) += kyro/ obj-$(CONFIG_FB_SAVAGE) += savage/ obj-$(CONFIG_FB_GEODE) += geode/ -obj-$(CONFIG_FB_MBX) += mbx/ obj-$(CONFIG_FB_NEOMAGIC) += neofb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o obj-$(CONFIG_FB_CONTROL) += controlfb.o diff --git a/drivers/video/fbdev/mbx/Makefile b/drivers/video/fbdev/mbx/Makefile deleted file mode 100644 index 3e8e7ff41f180..0000000000000 --- a/drivers/video/fbdev/mbx/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for the 2700G controller driver. - -obj-y += mbxfb.o diff --git a/drivers/video/fbdev/mbx/mbxdebugfs.c b/drivers/video/fbdev/mbx/mbxdebugfs.c deleted file mode 100644 index 09af721638fb6..0000000000000 --- a/drivers/video/fbdev/mbx/mbxdebugfs.c +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/debugfs.h> -#include <linux/slab.h> - -#define BIG_BUFFER_SIZE (1024) - -static char big_buffer[BIG_BUFFER_SIZE]; - -struct mbxfb_debugfs_data { - struct dentry *dir; - struct dentry *sysconf; - struct dentry *clock; - struct dentry *display; - struct dentry *gsctl; - struct dentry *sdram; - struct dentry *misc; -}; - -static ssize_t write_file_dummy(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return count; -} - -static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG)); - s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE)); - s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL)); - s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG)); - s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - - -static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL)); - s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL)); - s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE)); - s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE)); - s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL)); - s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK)); - s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR)); - s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR)); - s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE)); - s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE)); - s += sprintf(s, "GSADR = %08x\n", readl(GSADR)); - s += sprintf(s, "VSADR = %08x\n", readl(VSADR)); - s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL)); - s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE)); - s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS)); - s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR)); - s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK)); - s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - -static ssize_t display_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL)); - s += sprintf(s, "DHT01 = %08x\n", readl(DHT01)); - s += sprintf(s, "DHT02 = %08x\n", readl(DHT02)); - s += sprintf(s, "DHT03 = %08x\n", readl(DHT03)); - s += sprintf(s, "DVT01 = %08x\n", readl(DVT01)); - s += sprintf(s, "DVT02 = %08x\n", readl(DVT02)); - s += sprintf(s, "DVT03 = %08x\n", readl(DVT03)); - s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL)); - s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR)); - s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS)); - s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE)); - s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT)); - s += sprintf(s, "DSIG = %08x\n", readl(DSIG)); - s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL)); - s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL)); - s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL)); - s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL)); - s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS)); - s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL)); - s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM)); - s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL)); - s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL)); - s += sprintf(s, "DHDET = %08x\n", readl(DHDET)); - s += sprintf(s, "DVDET = %08x\n", readl(DVDET)); - s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK)); - s += sprintf(s, "CSC01 = %08x\n", readl(CSC01)); - s += sprintf(s, "CSC02 = %08x\n", readl(CSC02)); - s += sprintf(s, "CSC03 = %08x\n", readl(CSC03)); - s += sprintf(s, "CSC04 = %08x\n", readl(CSC04)); - s += sprintf(s, "CSC05 = %08x\n", readl(CSC05)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - -static ssize_t clock_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC)); - s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC)); - s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP)); - s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL)); - s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL)); - s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT)); - s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK)); - s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK)); - s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK)); - s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK)); - s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK)); - s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK)); - s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - -static ssize_t sdram_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "LMRST = %08x\n", readl(LMRST)); - s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG)); - s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR)); - s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT)); - s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR)); - s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE)); - s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM)); - s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH)); - s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN)); - s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX)); - s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG)); - s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - -static ssize_t misc_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - char * s = big_buffer; - - s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG)); - s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR)); - s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT)); - s += sprintf(s, "ID = %08x\n", readl(ID)); - - return simple_read_from_buffer(userbuf, count, ppos, - big_buffer, s-big_buffer); -} - - -static const struct file_operations sysconf_fops = { - .read = sysconf_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static const struct file_operations clock_fops = { - .read = clock_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static const struct file_operations display_fops = { - .read = display_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static const struct file_operations gsctl_fops = { - .read = gsctl_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static const struct file_operations sdram_fops = { - .read = sdram_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static const struct file_operations misc_fops = { - .read = misc_read_file, - .write = write_file_dummy, - .open = simple_open, - .llseek = default_llseek, -}; - -static void mbxfb_debugfs_init(struct fb_info *fbi) -{ - struct mbxfb_info *mfbi = fbi->par; - struct dentry *dir; - - dir = debugfs_create_dir("mbxfb", NULL); - mfbi->debugfs_dir = dir; - - debugfs_create_file("sysconf", 0444, dir, fbi, &sysconf_fops); - debugfs_create_file("clock", 0444, dir, fbi, &clock_fops); - debugfs_create_file("display", 0444, dir, fbi, &display_fops); - debugfs_create_file("gsctl", 0444, dir, fbi, &gsctl_fops); - debugfs_create_file("sdram", 0444, dir, fbi, &sdram_fops); - debugfs_create_file("misc", 0444, dir, fbi, &misc_fops); -} - -static void mbxfb_debugfs_remove(struct fb_info *fbi) -{ - struct mbxfb_info *mfbi = fbi->par; - - debugfs_remove_recursive(mfbi->debugfs_dir); -} diff --git a/drivers/video/fbdev/mbx/mbxfb.c b/drivers/video/fbdev/mbx/mbxfb.c deleted file mode 100644 index 6dc287c819cb5..0000000000000 --- a/drivers/video/fbdev/mbx/mbxfb.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * linux/drivers/video/mbx/mbxfb.c - * - * Copyright (C) 2006-2007 8D Technologies inc - * Raphael Assenat <raph@8d.com> - * - Added video overlay support - * - Various improvements - * - * Copyright (C) 2006 Compulab, Ltd. - * Mike Rapoport <mike@compulab.co.il> - * - Creation of driver - * - * Based on pxafb.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver - * - */ - -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -#include <video/mbxfb.h> - -#include "regs.h" -#include "reg_bits.h" - -static void __iomem *virt_base_2700; - -#define write_reg(val, reg) do { writel((val), (reg)); } while(0) - -/* Without this delay, the graphics appears somehow scaled and - * there is a lot of jitter in scanlines. This delay is probably - * needed only after setting some specific register(s) somewhere, - * not all over the place... */ -#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0) - -#define MIN_XRES 16 -#define MIN_YRES 16 -#define MAX_XRES 2048 -#define MAX_YRES 2048 - -#define MAX_PALETTES 16 - -/* FIXME: take care of different chip revisions with different sizes - of ODFB */ -#define MEMORY_OFFSET 0x60000 - -struct mbxfb_info { - struct device *dev; - - struct resource *fb_res; - struct resource *fb_req; - - struct resource *reg_res; - struct resource *reg_req; - - void __iomem *fb_virt_addr; - unsigned long fb_phys_addr; - - void __iomem *reg_virt_addr; - unsigned long reg_phys_addr; - - int (*platform_probe) (struct fb_info * fb); - int (*platform_remove) (struct fb_info * fb); - - u32 pseudo_palette[MAX_PALETTES]; -#ifdef CONFIG_FB_MBX_DEBUG - struct dentry *debugfs_dir; -#endif - -}; - -static const struct fb_var_screeninfo mbxfb_default = { - .xres = 640, - .yres = 480, - .xres_virtual = 640, - .yres_virtual = 480, - .bits_per_pixel = 16, - .red = {11, 5, 0}, - .green = {5, 6, 0}, - .blue = {0, 5, 0}, - .activate = FB_ACTIVATE_TEST, - .height = -1, - .width = -1, - .pixclock = 40000, - .left_margin = 48, - .right_margin = 16, - .upper_margin = 33, - .lower_margin = 10, - .hsync_len = 96, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, - .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, -}; - -static const struct fb_fix_screeninfo mbxfb_fix = { - .id = "MBX", - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 0, - .ypanstep = 0, - .ywrapstep = 0, - .accel = FB_ACCEL_NONE, -}; - -struct pixclock_div { - u8 m; - u8 n; - u8 p; -}; - -static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, - struct pixclock_div *div) -{ - u8 m, n, p; - unsigned int err = 0; - unsigned int min_err = ~0x0; - unsigned int clk; - unsigned int best_clk = 0; - unsigned int ref_clk = 13000; /* FIXME: take from platform data */ - unsigned int pixclock; - - /* convert pixclock to KHz */ - pixclock = PICOS2KHZ(pixclock_ps); - - /* PLL output freq = (ref_clk * M) / (N * 2^P) - * - * M: 1 to 63 - * N: 1 to 7 - * P: 0 to 7 - */ - - /* RAPH: When N==1, the resulting pixel clock appears to - * get divided by 2. Preventing N=1 by starting the following - * loop at 2 prevents this. Is this a bug with my chip - * revision or something I dont understand? */ - for (m = 1; m < 64; m++) { - for (n = 2; n < 8; n++) { - for (p = 0; p < 8; p++) { - clk = (ref_clk * m) / (n * (1 << p)); - err = (clk > pixclock) ? (clk - pixclock) : - (pixclock - clk); - if (err < min_err) { - min_err = err; - best_clk = clk; - div->m = m; - div->n = n; - div->p = p; - } - } - } - } - return KHZ2PICOS(best_clk); -} - -static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int trans, struct fb_info *info) -{ - u32 val, ret = 1; - - if (regno < MAX_PALETTES) { - u32 *pal = info->pseudo_palette; - - val = (red & 0xf800) | ((green & 0xfc00) >> 5) | - ((blue & 0xf800) >> 11); - pal[regno] = val; - ret = 0; - } - - return ret; -} - -static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct pixclock_div div; - - var->pixclock = mbxfb_get_pixclock(var->pixclock, &div); - - if (var->xres < MIN_XRES) - var->xres = MIN_XRES; - if (var->yres < MIN_YRES) - var->yres = MIN_YRES; - if (var->xres > MAX_XRES) - return -EINVAL; - if (var->yres > MAX_YRES) - return -EINVAL; - var->xres_virtual = max(var->xres_virtual, var->xres); - var->yres_virtual = max(var->yres_virtual, var->yres); - - switch (var->bits_per_pixel) { - /* 8 bits-per-pixel is not supported yet */ - case 8: - return -EINVAL; - case 16: - var->green.length = (var->green.length == 5) ? 5 : 6; - var->red.length = 5; - var->blue.length = 5; - var->transp.length = 6 - var->green.length; - var->blue.offset = 0; - var->green.offset = 5; - var->red.offset = 5 + var->green.length; - var->transp.offset = (5 + var->red.offset) & 15; - break; - case 24: /* RGB 888 */ - case 32: /* RGBA 8888 */ - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.length = var->bits_per_pixel - 24; - var->transp.offset = (var->transp.length) ? 24 : 0; - break; - } - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; - - return 0; -} - -static int mbxfb_set_par(struct fb_info *info) -{ - struct fb_var_screeninfo *var = &info->var; - struct pixclock_div div; - ushort hbps, ht, hfps, has; - ushort vbps, vt, vfps, vas; - u32 gsctrl = readl(GSCTRL); - u32 gsadr = readl(GSADR); - - info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; - - /* setup color mode */ - gsctrl &= ~(FMsk(GSCTRL_GPIXFMT)); - /* FIXME: add *WORKING* support for 8-bits per color */ - if (info->var.bits_per_pixel == 8) { - return -EINVAL; - } else { - fb_dealloc_cmap(&info->cmap); - gsctrl &= ~GSCTRL_LUT_EN; - - info->fix.visual = FB_VISUAL_TRUECOLOR; - switch (info->var.bits_per_pixel) { - case 16: - if (info->var.green.length == 5) - gsctrl |= GSCTRL_GPIXFMT_ARGB1555; - else - gsctrl |= GSCTRL_GPIXFMT_RGB565; - break; - case 24: - gsctrl |= GSCTRL_GPIXFMT_RGB888; - break; - case 32: - gsctrl |= GSCTRL_GPIXFMT_ARGB8888; - break; - } - } - - /* setup resolution */ - gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); - gsctrl |= Gsctrl_Width(info->var.xres) | - Gsctrl_Height(info->var.yres); - write_reg_dly(gsctrl, GSCTRL); - - gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); - gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / - (8 * 16) - 1); - write_reg_dly(gsadr, GSADR); - - /* setup timings */ - var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); - - write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | - Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); - - hbps = var->hsync_len; - has = hbps + var->left_margin; - hfps = has + var->xres; - ht = hfps + var->right_margin; - - vbps = var->vsync_len; - vas = vbps + var->upper_margin; - vfps = vas + var->yres; - vt = vfps + var->lower_margin; - - write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); - write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); - write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); - write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); - - write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); - write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); - write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); - write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); - write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); - - write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - - write_reg_dly(DINTRE_VEVENT0_EN, DINTRE); - - return 0; -} - -static int mbxfb_blank(int blank, struct fb_info *info) -{ - switch (blank) { - case FB_BLANK_POWERDOWN: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_NORMAL: - write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); - write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); - write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); - break; - case FB_BLANK_UNBLANK: - write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK); - break; - } - return 0; -} - -static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set) -{ - u32 vsctrl, vscadr, vsadr; - u32 sssize, spoctrl, shctrl; - u32 vubase, vvbase; - u32 vovrclk; - - if (set->scaled_width==0 || set->scaled_height==0) - return -EINVAL; - - /* read registers which have reserved bits - * so we can write them back as-is. */ - vovrclk = readl(VOVRCLK); - vsctrl = readl(VSCTRL); - vscadr = readl(VSCADR); - vubase = readl(VUBASE); - vvbase = readl(VVBASE); - shctrl = readl(SHCTRL); - - spoctrl = readl(SPOCTRL); - sssize = readl(SSSIZE); - - vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) | - FMsk(VSCTRL_VSHEIGHT) | - FMsk(VSCTRL_VPIXFMT) | - VSCTRL_GAMMA_EN | VSCTRL_CSC_EN | - VSCTRL_COSITED ); - vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) | - VSCTRL_CSC_EN; - - vscadr &= ~(VSCADR_STR_EN | FMsk(VSCADR_VBASE_ADR) ); - vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR)); - vvbase &= ~(FMsk(VVBASE_VBASE_ADR)); - - switch (set->fmt) { - case MBXFB_FMT_YUV16: - vsctrl |= VSCTRL_VPIXFMT_YUV12; - - set->Y_stride = ((set->width) + 0xf ) & ~0xf; - break; - case MBXFB_FMT_YUV12: - vsctrl |= VSCTRL_VPIXFMT_YUV12; - - set->Y_stride = ((set->width) + 0xf ) & ~0xf; - vubase |= VUBASE_UVHALFSTR; - - break; - case MBXFB_FMT_UY0VY1: - vsctrl |= VSCTRL_VPIXFMT_UY0VY1; - set->Y_stride = (set->width*2 + 0xf ) & ~0xf; - break; - case MBXFB_FMT_VY0UY1: - vsctrl |= VSCTRL_VPIXFMT_VY0UY1; - set->Y_stride = (set->width*2 + 0xf ) & ~0xf; - break; - case MBXFB_FMT_Y0UY1V: - vsctrl |= VSCTRL_VPIXFMT_Y0UY1V; - set->Y_stride = (set->width*2 + 0xf ) & ~0xf; - break; - case MBXFB_FMT_Y0VY1U: - vsctrl |= VSCTRL_VPIXFMT_Y0VY1U; - set->Y_stride = (set->width*2 + 0xf ) & ~0xf; - break; - default: - return -EINVAL; - } - - /* VSCTRL has the bits which sets the Video Pixel Format. - * When passing from a packed to planar format, - * if we write VSCTRL first, VVBASE and VUBASE would - * be zero if we would not set them here. (And then, - * the chips hangs and only a reset seems to fix it). - * - * If course, the values calculated here have no meaning - * for packed formats. - */ - set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7; - set->U_offset = set->height * set->Y_stride; - set->V_offset = set->U_offset + - set->height * set->UV_stride; - vubase |= Vubase_Ubase_Adr( - (0x60000 + set->mem_offset + set->U_offset)>>3); - vvbase |= Vvbase_Vbase_Adr( - (0x60000 + set->mem_offset + set->V_offset)>>3); - - - vscadr |= Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4); - - if (set->enable) - vscadr |= VSCADR_STR_EN; - - - vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) | - Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y); - - sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT)); - sssize = Sssize_Sc_Width(set->scaled_width-1) | - Sssize_Sc_Height(set->scaled_height-1); - - spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | - SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C | - FMsk(SPOCTRL_VPITCH)); - spoctrl |= Spoctrl_Vpitch((set->height<<11)/set->scaled_height); - - /* Bypass horiz/vert scaler when same size */ - if (set->scaled_width == set->width) - spoctrl |= SPOCTRL_H_SC_BP; - if (set->scaled_height == set->height) - spoctrl |= SPOCTRL_V_SC_BP; - - shctrl &= ~(FMsk(SHCTRL_HPITCH) | SHCTRL_HDECIM); - shctrl |= Shctrl_Hpitch((set->width<<11)/set->scaled_width); - - /* Video plane registers */ - write_reg(vsctrl, VSCTRL); - write_reg(vscadr, VSCADR); - write_reg(vubase, VUBASE); - write_reg(vvbase, VVBASE); - write_reg(vsadr, VSADR); - - /* Video scaler registers */ - write_reg(sssize, SSSIZE); - write_reg(spoctrl, SPOCTRL); - write_reg(shctrl, SHCTRL); - - /* Clock */ - if (set->enable) - vovrclk |= 1; - else - vovrclk &= ~1; - - write_reg(vovrclk, VOVRCLK); - - return 0; -} - -static int mbxfb_ioctl_planeorder(struct mbxfb_planeorder *porder) -{ - unsigned long gscadr, vscadr; - - if (porder->bottom == porder->top) - return -EINVAL; - - gscadr = readl(GSCADR); - vscadr = readl(VSCADR); - - gscadr &= ~(FMsk(GSCADR_BLEND_POS)); - vscadr &= ~(FMsk(VSCADR_BLEND_POS)); - - switch (porder->bottom) { - case MBXFB_PLANE_GRAPHICS: - gscadr |= GSCADR_BLEND_GFX; - break; - case MBXFB_PLANE_VIDEO: - vscadr |= VSCADR_BLEND_GFX; - break; - default: - return -EINVAL; - } - - switch (porder->top) { - case MBXFB_PLANE_GRAPHICS: - gscadr |= GSCADR_BLEND_VID; - break; - case MBXFB_PLANE_VIDEO: - vscadr |= GSCADR_BLEND_VID; - break; - default: - return -EINVAL; - } - - write_reg_dly(vscadr, VSCADR); - write_reg_dly(gscadr, GSCADR); - - return 0; - -} - -static int mbxfb_ioctl_alphactl(struct mbxfb_alphaCtl *alpha) -{ - unsigned long vscadr, vbbase, vcmsk; - unsigned long gscadr, gbbase, gdrctrl; - - vbbase = Vbbase_Glalpha(alpha->overlay_global_alpha) | - Vbbase_Colkey(alpha->overlay_colorkey); - - gbbase = Gbbase_Glalpha(alpha->graphics_global_alpha) | - Gbbase_Colkey(alpha->graphics_colorkey); - - vcmsk = readl(VCMSK); - vcmsk &= ~(FMsk(VCMSK_COLKEY_M)); - vcmsk |= Vcmsk_colkey_m(alpha->overlay_colorkey_mask); - - gdrctrl = readl(GDRCTRL); - gdrctrl &= ~(FMsk(GDRCTRL_COLKEYM)); - gdrctrl |= Gdrctrl_Colkeym(alpha->graphics_colorkey_mask); - - vscadr = readl(VSCADR); - vscadr &= ~(FMsk(VSCADR_BLEND_M) | VSCADR_COLKEYSRC | VSCADR_COLKEY_EN); - - gscadr = readl(GSCADR); - gscadr &= ~(FMsk(GSCADR_BLEND_M) | GSCADR_COLKEY_EN | GSCADR_COLKEYSRC); - - switch (alpha->overlay_colorkey_mode) { - case MBXFB_COLORKEY_DISABLED: - break; - case MBXFB_COLORKEY_PREVIOUS: - vscadr |= VSCADR_COLKEY_EN; - break; - case MBXFB_COLORKEY_CURRENT: - vscadr |= VSCADR_COLKEY_EN | VSCADR_COLKEYSRC; - break; - default: - return -EINVAL; - } - - switch (alpha->overlay_blend_mode) { - case MBXFB_ALPHABLEND_NONE: - vscadr |= VSCADR_BLEND_NONE; - break; - case MBXFB_ALPHABLEND_GLOBAL: - vscadr |= VSCADR_BLEND_GLOB; - break; - case MBXFB_ALPHABLEND_PIXEL: - vscadr |= VSCADR_BLEND_PIX; - break; - default: - return -EINVAL; - } - - switch (alpha->graphics_colorkey_mode) { - case MBXFB_COLORKEY_DISABLED: - break; - case MBXFB_COLORKEY_PREVIOUS: - gscadr |= GSCADR_COLKEY_EN; - break; - case MBXFB_COLORKEY_CURRENT: - gscadr |= GSCADR_COLKEY_EN | GSCADR_COLKEYSRC; - break; - default: - return -EINVAL; - } - - switch (alpha->graphics_blend_mode) { - case MBXFB_ALPHABLEND_NONE: - gscadr |= GSCADR_BLEND_NONE; - break; - case MBXFB_ALPHABLEND_GLOBAL: - gscadr |= GSCADR_BLEND_GLOB; - break; - case MBXFB_ALPHABLEND_PIXEL: - gscadr |= GSCADR_BLEND_PIX; - break; - default: - return -EINVAL; - } - - write_reg_dly(vbbase, VBBASE); - write_reg_dly(gbbase, GBBASE); - write_reg_dly(vcmsk, VCMSK); - write_reg_dly(gdrctrl, GDRCTRL); - write_reg_dly(gscadr, GSCADR); - write_reg_dly(vscadr, VSCADR); - - return 0; -} - -static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - struct mbxfb_overlaySetup setup; - struct mbxfb_planeorder porder; - struct mbxfb_alphaCtl alpha; - struct mbxfb_reg reg; - int res; - __u32 tmp; - - switch (cmd) - { - case MBXFB_IOCX_OVERLAY: - if (copy_from_user(&setup, (void __user*)arg, - sizeof(struct mbxfb_overlaySetup))) - return -EFAULT; - - res = mbxfb_setupOverlay(&setup); - if (res) - return res; - - if (copy_to_user((void __user*)arg, &setup, - sizeof(struct mbxfb_overlaySetup))) - return -EFAULT; - - return 0; - - case MBXFB_IOCS_PLANEORDER: - if (copy_from_user(&porder, (void __user*)arg, - sizeof(struct mbxfb_planeorder))) - return -EFAULT; - - return mbxfb_ioctl_planeorder(&porder); - - case MBXFB_IOCS_ALPHA: - if (copy_from_user(&alpha, (void __user*)arg, - sizeof(struct mbxfb_alphaCtl))) - return -EFAULT; - - return mbxfb_ioctl_alphactl(&alpha); - - case MBXFB_IOCS_REG: - if (copy_from_user(®, (void __user*)arg, - sizeof(struct mbxfb_reg))) - return -EFAULT; - - if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */ - return -EINVAL; - - tmp = readl(virt_base_2700 + reg.addr); - tmp &= ~reg.mask; - tmp |= reg.val & reg.mask; - writel(tmp, virt_base_2700 + reg.addr); - - return 0; - case MBXFB_IOCX_REG: - if (copy_from_user(®, (void __user*)arg, - sizeof(struct mbxfb_reg))) - return -EFAULT; - - if (reg.addr >= 0x10000) /* regs are from 0x3fe0000 to 0x3feffff */ - return -EINVAL; - reg.val = readl(virt_base_2700 + reg.addr); - - if (copy_to_user((void __user*)arg, ®, - sizeof(struct mbxfb_reg))) - return -EFAULT; - - return 0; - } - return -EINVAL; -} - -static const struct fb_ops mbxfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = mbxfb_check_var, - .fb_set_par = mbxfb_set_par, - .fb_setcolreg = mbxfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_blank = mbxfb_blank, - .fb_ioctl = mbxfb_ioctl, -}; - -/* - Enable external SDRAM controller. Assume that all clocks are active - by now. -*/ -static void setup_memc(struct fb_info *fbi) -{ - unsigned long tmp; - int i; - - /* FIXME: use platform specific parameters */ - /* setup SDRAM controller */ - write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | - LMCFG_LMA_TS), - LMCFG); - - write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); - - /* setup SDRAM timings */ - write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | - Lmtim_Trc(9) | Lmtim_Tdpl(2)), - LMTIM); - /* setup SDRAM refresh rate */ - write_reg_dly(0xc2b, LMREFRESH); - /* setup SDRAM type parameters */ - write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | - LMTYPE_COLSZ_8), - LMTYPE); - /* enable memory controller */ - write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); - /* perform dummy reads */ - for ( i = 0; i < 16; i++ ) { - tmp = readl(fbi->screen_base); - } -} - -static void enable_clocks(struct fb_info *fbi) -{ - /* enable clocks */ - write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC); - write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC); - write_reg_dly(0x00000000, CLKSLEEP); - - /* PLL output = (Frefclk * M) / (N * 2^P ) - * - * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz! - * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz - * */ - write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) | - CORE_PLL_EN), - COREPLL); - - write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | - DISP_PLL_EN), - DISPPLL); - - write_reg_dly(0x00000000, VOVRCLK); - write_reg_dly(PIXCLK_EN, PIXCLK); - write_reg_dly(MEMCLK_EN, MEMCLK); - write_reg_dly(0x00000001, M24CLK); - write_reg_dly(0x00000001, MBXCLK); - write_reg_dly(SDCLK_EN, SDCLK); - write_reg_dly(0x00000001, PIXCLKDIV); -} - -static void setup_graphics(struct fb_info *fbi) -{ - unsigned long gsctrl; - unsigned long vscadr; - - gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres) | - Gsctrl_Height(fbi->var.yres); - switch (fbi->var.bits_per_pixel) { - case 16: - if (fbi->var.green.length == 5) - gsctrl |= GSCTRL_GPIXFMT_ARGB1555; - else - gsctrl |= GSCTRL_GPIXFMT_RGB565; - break; - case 24: - gsctrl |= GSCTRL_GPIXFMT_RGB888; - break; - case 32: - gsctrl |= GSCTRL_GPIXFMT_ARGB8888; - break; - } - - write_reg_dly(gsctrl, GSCTRL); - write_reg_dly(0x00000000, GBBASE); - write_reg_dly(0x00ffffff, GDRCTRL); - write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); - write_reg_dly(0x00000000, GPLUT); - - vscadr = readl(VSCADR); - vscadr &= ~(FMsk(VSCADR_BLEND_POS) | FMsk(VSCADR_BLEND_M)); - vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_NONE; - write_reg_dly(vscadr, VSCADR); -} - -static void setup_display(struct fb_info *fbi) -{ - unsigned long dsctrl = 0; - - dsctrl = DSCTRL_BLNK_POL; - if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) - dsctrl |= DSCTRL_HS_POL; - if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) - dsctrl |= DSCTRL_VS_POL; - write_reg_dly(dsctrl, DSCTRL); - write_reg_dly(0xd0303010, DMCTRL); - write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); -} - -static void enable_controller(struct fb_info *fbi) -{ - u32 svctrl, shctrl; - - write_reg_dly(SYSRST_RST, SYSRST); - - /* setup a timeout, raise drive strength */ - write_reg_dly(0xffffff0c, SYSCFG); - - enable_clocks(fbi); - setup_memc(fbi); - setup_graphics(fbi); - setup_display(fbi); - - shctrl = readl(SHCTRL); - shctrl &= ~(FMsk(SHCTRL_HINITIAL)); - shctrl |= Shctrl_Hinitial(4<<11); - writel(shctrl, SHCTRL); - - svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10); - writel(svctrl, SVCTRL); - - writel(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | SPOCTRL_VORDER_4TAP - , SPOCTRL); - - /* Those coefficients are good for scaling up. For scaling - * down, the application has to calculate them. */ - write_reg(0xff000100, VSCOEFF0); - write_reg(0xfdfcfdfe, VSCOEFF1); - write_reg(0x170d0500, VSCOEFF2); - write_reg(0x3d372d22, VSCOEFF3); - write_reg(0x00000040, VSCOEFF4); - - write_reg(0xff010100, HSCOEFF0); - write_reg(0x00000000, HSCOEFF1); - write_reg(0x02010000, HSCOEFF2); - write_reg(0x01020302, HSCOEFF3); - write_reg(0xf9fbfe00, HSCOEFF4); - write_reg(0xfbf7f6f7, HSCOEFF5); - write_reg(0x1c110700, HSCOEFF6); - write_reg(0x3e393127, HSCOEFF7); - write_reg(0x00000040, HSCOEFF8); - -} - -#ifdef CONFIG_PM -/* - * Power management hooks. Note that we won't be called from IRQ context, - * unlike the blank functions above, so we may sleep. - */ -static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) -{ - /* make frame buffer memory enter self-refresh mode */ - write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); - while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM) - ; /* empty statement */ - - /* reset the device, since it's initial state is 'mostly sleeping' */ - write_reg_dly(SYSRST_RST, SYSRST); - return 0; -} - -static int mbxfb_resume(struct platform_device *dev) -{ - struct fb_info *fbi = platform_get_drvdata(dev); - - enable_clocks(fbi); -/* setup_graphics(fbi); */ -/* setup_display(fbi); */ - - write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - return 0; -} -#else -#define mbxfb_suspend NULL -#define mbxfb_resume NULL -#endif - -/* debugfs entries */ -#ifndef CONFIG_FB_MBX_DEBUG -#define mbxfb_debugfs_init(x) do {} while(0) -#define mbxfb_debugfs_remove(x) do {} while(0) -#else -#include "mbxdebugfs.c" -#endif - -#define res_size(_r) (((_r)->end - (_r)->start) + 1) - -static int mbxfb_probe(struct platform_device *dev) -{ - int ret; - struct fb_info *fbi; - struct mbxfb_info *mfbi; - struct mbxfb_platform_data *pdata; - - dev_dbg(&dev->dev, "mbxfb_probe\n"); - - pdata = dev_get_platdata(&dev->dev); - if (!pdata) { - dev_err(&dev->dev, "platform data is required\n"); - return -EINVAL; - } - - fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); - if (!fbi) - return -ENOMEM; - - mfbi = fbi->par; - fbi->pseudo_palette = mfbi->pseudo_palette; - - - if (pdata->probe) - mfbi->platform_probe = pdata->probe; - if (pdata->remove) - mfbi->platform_remove = pdata->remove; - - mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0); - mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1); - - if (!mfbi->fb_res || !mfbi->reg_res) { - dev_err(&dev->dev, "no resources found\n"); - ret = -ENODEV; - goto err1; - } - - mfbi->fb_req = request_mem_region(mfbi->fb_res->start, - res_size(mfbi->fb_res), dev->name); - if (mfbi->fb_req == NULL) { - dev_err(&dev->dev, "failed to claim framebuffer memory\n"); - ret = -EINVAL; - goto err1; - } - mfbi->fb_phys_addr = mfbi->fb_res->start; - - mfbi->reg_req = request_mem_region(mfbi->reg_res->start, - res_size(mfbi->reg_res), dev->name); - if (mfbi->reg_req == NULL) { - dev_err(&dev->dev, "failed to claim Marathon registers\n"); - ret = -EINVAL; - goto err2; - } - mfbi->reg_phys_addr = mfbi->reg_res->start; - - mfbi->reg_virt_addr = devm_ioremap(&dev->dev, - mfbi->reg_phys_addr, - res_size(mfbi->reg_req)); - if (!mfbi->reg_virt_addr) { - dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); - ret = -EINVAL; - goto err3; - } - virt_base_2700 = mfbi->reg_virt_addr; - - mfbi->fb_virt_addr = devm_ioremap(&dev->dev, mfbi->fb_phys_addr, - res_size(mfbi->fb_req)); - if (!mfbi->fb_virt_addr) { - dev_err(&dev->dev, "failed to ioremap frame buffer\n"); - ret = -EINVAL; - goto err3; - } - - fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); - fbi->screen_size = pdata->memsize; - fbi->fbops = &mbxfb_ops; - - fbi->var = mbxfb_default; - fbi->fix = mbxfb_fix; - fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; - fbi->fix.smem_len = pdata->memsize; - fbi->fix.line_length = mbxfb_default.xres_virtual * - mbxfb_default.bits_per_pixel / 8; - - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret < 0) { - dev_err(&dev->dev, "fb_alloc_cmap failed\n"); - ret = -EINVAL; - goto err3; - } - - platform_set_drvdata(dev, fbi); - - fb_info(fbi, "mbx frame buffer device\n"); - - if (mfbi->platform_probe) - mfbi->platform_probe(fbi); - - enable_controller(fbi); - - mbxfb_debugfs_init(fbi); - - ret = register_framebuffer(fbi); - if (ret < 0) { - dev_err(&dev->dev, "register_framebuffer failed\n"); - ret = -EINVAL; - goto err6; - } - - return 0; - -err6: - fb_dealloc_cmap(&fbi->cmap); -err3: - release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res)); -err2: - release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res)); -err1: - framebuffer_release(fbi); - - return ret; -} - -static int mbxfb_remove(struct platform_device *dev) -{ - struct fb_info *fbi = platform_get_drvdata(dev); - - write_reg_dly(SYSRST_RST, SYSRST); - - mbxfb_debugfs_remove(fbi); - - if (fbi) { - struct mbxfb_info *mfbi = fbi->par; - - unregister_framebuffer(fbi); - if (mfbi) { - if (mfbi->platform_remove) - mfbi->platform_remove(fbi); - - - if (mfbi->reg_req) - release_mem_region(mfbi->reg_req->start, - res_size(mfbi->reg_req)); - if (mfbi->fb_req) - release_mem_region(mfbi->fb_req->start, - res_size(mfbi->fb_req)); - } - framebuffer_release(fbi); - } - - return 0; -} - -static struct platform_driver mbxfb_driver = { - .probe = mbxfb_probe, - .remove = mbxfb_remove, - .suspend = mbxfb_suspend, - .resume = mbxfb_resume, - .driver = { - .name = "mbx-fb", - }, -}; - -module_platform_driver(mbxfb_driver); - -MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); -MODULE_AUTHOR("Mike Rapoport, Compulab"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/mbx/reg_bits.h b/drivers/video/fbdev/mbx/reg_bits.h deleted file mode 100644 index 6607f353639b6..0000000000000 --- a/drivers/video/fbdev/mbx/reg_bits.h +++ /dev/null @@ -1,614 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __REG_BITS_2700G_ -#define __REG_BITS_2700G_ - -/* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */ -#define UData(Data) ((unsigned long) (Data)) -#define Fld(Size, Shft) (((Size) << 16) + (Shft)) -#define FSize(Field) ((Field) >> 16) -#define FShft(Field) ((Field) & 0x0000FFFF) -#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field)) -#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1) -#define F1stBit(Field) (UData (1) << FShft (Field)) - -#define SYSRST_RST (1 << 0) - -/* SYSCLKSRC - SYSCLK Source Control Register */ -#define SYSCLKSRC_SEL Fld(2,0) -#define SYSCLKSRC_REF ((0x0) << FShft(SYSCLKSRC_SEL)) -#define SYSCLKSRC_PLL_1 ((0x1) << FShft(SYSCLKSRC_SEL)) -#define SYSCLKSRC_PLL_2 ((0x2) << FShft(SYSCLKSRC_SEL)) - -/* PIXCLKSRC - PIXCLK Source Control Register */ -#define PIXCLKSRC_SEL Fld(2,0) -#define PIXCLKSRC_REF ((0x0) << FShft(PIXCLKSRC_SEL)) -#define PIXCLKSRC_PLL_1 ((0x1) << FShft(PIXCLKSRC_SEL)) -#define PIXCLKSRC_PLL_2 ((0x2) << FShft(PIXCLKSRC_SEL)) - -/* Clock Disable Register */ -#define CLKSLEEP_SLP (1 << 0) - -/* Core PLL Control Register */ -#define CORE_PLL_M Fld(6,7) -#define Core_Pll_M(x) ((x) << FShft(CORE_PLL_M)) -#define CORE_PLL_N Fld(3,4) -#define Core_Pll_N(x) ((x) << FShft(CORE_PLL_N)) -#define CORE_PLL_P Fld(3,1) -#define Core_Pll_P(x) ((x) << FShft(CORE_PLL_P)) -#define CORE_PLL_EN (1 << 0) - -/* Display PLL Control Register */ -#define DISP_PLL_M Fld(6,7) -#define Disp_Pll_M(x) ((x) << FShft(DISP_PLL_M)) -#define DISP_PLL_N Fld(3,4) -#define Disp_Pll_N(x) ((x) << FShft(DISP_PLL_N)) -#define DISP_PLL_P Fld(3,1) -#define Disp_Pll_P(x) ((x) << FShft(DISP_PLL_P)) -#define DISP_PLL_EN (1 << 0) - -/* PLL status register */ -#define PLLSTAT_CORE_PLL_LOST_L (1 << 3) -#define PLLSTAT_CORE_PLL_LSTS (1 << 2) -#define PLLSTAT_DISP_PLL_LOST_L (1 << 1) -#define PLLSTAT_DISP_PLL_LSTS (1 << 0) - -/* Video and scale clock control register */ -#define VOVRCLK_EN (1 << 0) - -/* Pixel clock control register */ -#define PIXCLK_EN (1 << 0) - -/* Memory clock control register */ -#define MEMCLK_EN (1 << 0) - -/* MBX clock control register */ -#define MBXCLK_DIV Fld(2,2) -#define MBXCLK_DIV_1 ((0x0) << FShft(MBXCLK_DIV)) -#define MBXCLK_DIV_2 ((0x1) << FShft(MBXCLK_DIV)) -#define MBXCLK_DIV_3 ((0x2) << FShft(MBXCLK_DIV)) -#define MBXCLK_DIV_4 ((0x3) << FShft(MBXCLK_DIV)) -#define MBXCLK_EN Fld(2,0) -#define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN)) -#define MBXCLK_EN_2D ((0x1) << FShft(MBXCLK_EN)) -#define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN)) - -/* M24 clock control register */ -#define M24CLK_DIV Fld(2,1) -#define M24CLK_DIV_1 ((0x0) << FShft(M24CLK_DIV)) -#define M24CLK_DIV_2 ((0x1) << FShft(M24CLK_DIV)) -#define M24CLK_DIV_3 ((0x2) << FShft(M24CLK_DIV)) -#define M24CLK_DIV_4 ((0x3) << FShft(M24CLK_DIV)) -#define M24CLK_EN (1 << 0) - -/* SDRAM clock control register */ -#define SDCLK_EN (1 << 0) - -/* PixClk Divisor Register */ -#define PIXCLKDIV_PD Fld(9,0) -#define Pixclkdiv_Pd(x) ((x) << FShft(PIXCLKDIV_PD)) - -/* LCD Config control register */ -#define LCDCFG_IN_FMT Fld(3,28) -#define Lcdcfg_In_Fmt(x) ((x) << FShft(LCDCFG_IN_FMT)) -#define LCDCFG_LCD1DEN_POL (1 << 27) -#define LCDCFG_LCD1FCLK_POL (1 << 26) -#define LCDCFG_LCD1LCLK_POL (1 << 25) -#define LCDCFG_LCD1D_POL (1 << 24) -#define LCDCFG_LCD2DEN_POL (1 << 23) -#define LCDCFG_LCD2FCLK_POL (1 << 22) -#define LCDCFG_LCD2LCLK_POL (1 << 21) -#define LCDCFG_LCD2D_POL (1 << 20) -#define LCDCFG_LCD1_TS (1 << 19) -#define LCDCFG_LCD1D_DS (1 << 18) -#define LCDCFG_LCD1C_DS (1 << 17) -#define LCDCFG_LCD1_IS_IN (1 << 16) -#define LCDCFG_LCD2_TS (1 << 3) -#define LCDCFG_LCD2D_DS (1 << 2) -#define LCDCFG_LCD2C_DS (1 << 1) -#define LCDCFG_LCD2_IS_IN (1 << 0) - -/* On-Die Frame Buffer Power Control Register */ -#define ODFBPWR_SLOW (1 << 2) -#define ODFBPWR_MODE Fld(2,0) -#define ODFBPWR_MODE_ACT ((0x0) << FShft(ODFBPWR_MODE)) -#define ODFBPWR_MODE_ACT_LP ((0x1) << FShft(ODFBPWR_MODE)) -#define ODFBPWR_MODE_SLEEP ((0x2) << FShft(ODFBPWR_MODE)) -#define ODFBPWR_MODE_SHUTD ((0x3) << FShft(ODFBPWR_MODE)) - -/* On-Die Frame Buffer Power State Status Register */ -#define ODFBSTAT_ACT (1 << 2) -#define ODFBSTAT_SLP (1 << 1) -#define ODFBSTAT_SDN (1 << 0) - -/* LMRST - Local Memory (SDRAM) Reset */ -#define LMRST_MC_RST (1 << 0) - -/* LMCFG - Local Memory (SDRAM) Configuration Register */ -#define LMCFG_LMC_DS (1 << 5) -#define LMCFG_LMD_DS (1 << 4) -#define LMCFG_LMA_DS (1 << 3) -#define LMCFG_LMC_TS (1 << 2) -#define LMCFG_LMD_TS (1 << 1) -#define LMCFG_LMA_TS (1 << 0) - -/* LMPWR - Local Memory (SDRAM) Power Control Register */ -#define LMPWR_MC_PWR_CNT Fld(2,0) -#define LMPWR_MC_PWR_ACT ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */ -#define LMPWR_MC_PWR_SRM ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */ -#define LMPWR_MC_PWR_DPD ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */ - -/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */ -#define LMPWRSTAT_MC_PWR_CNT Fld(2,0) -#define LMPWRSTAT_MC_PWR_ACT ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */ -#define LMPWRSTAT_MC_PWR_SRM ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */ -#define LMPWRSTAT_MC_PWR_DPD ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */ - -/* LMTYPE - Local Memory (SDRAM) Type Register */ -#define LMTYPE_CASLAT Fld(3,10) -#define LMTYPE_CASLAT_1 ((0x1) << FShft(LMTYPE_CASLAT)) -#define LMTYPE_CASLAT_2 ((0x2) << FShft(LMTYPE_CASLAT)) -#define LMTYPE_CASLAT_3 ((0x3) << FShft(LMTYPE_CASLAT)) -#define LMTYPE_BKSZ Fld(2,8) -#define LMTYPE_BKSZ_1 ((0x1) << FShft(LMTYPE_BKSZ)) -#define LMTYPE_BKSZ_2 ((0x2) << FShft(LMTYPE_BKSZ)) -#define LMTYPE_ROWSZ Fld(4,4) -#define LMTYPE_ROWSZ_11 ((0xb) << FShft(LMTYPE_ROWSZ)) -#define LMTYPE_ROWSZ_12 ((0xc) << FShft(LMTYPE_ROWSZ)) -#define LMTYPE_ROWSZ_13 ((0xd) << FShft(LMTYPE_ROWSZ)) -#define LMTYPE_COLSZ Fld(4,0) -#define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ)) -#define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ)) -#define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ)) -#define LMTYPE_COLSZ_10 ((0xa) << FShft(LMTYPE_COLSZ)) -#define LMTYPE_COLSZ_11 ((0xb) << FShft(LMTYPE_COLSZ)) -#define LMTYPE_COLSZ_12 ((0xc) << FShft(LMTYPE_COLSZ)) - -/* LMTIM - Local Memory (SDRAM) Timing Register */ -#define LMTIM_TRAS Fld(4,16) -#define Lmtim_Tras(x) ((x) << FShft(LMTIM_TRAS)) -#define LMTIM_TRP Fld(4,12) -#define Lmtim_Trp(x) ((x) << FShft(LMTIM_TRP)) -#define LMTIM_TRCD Fld(4,8) -#define Lmtim_Trcd(x) ((x) << FShft(LMTIM_TRCD)) -#define LMTIM_TRC Fld(4,4) -#define Lmtim_Trc(x) ((x) << FShft(LMTIM_TRC)) -#define LMTIM_TDPL Fld(4,0) -#define Lmtim_Tdpl(x) ((x) << FShft(LMTIM_TDPL)) - -/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */ -#define LMREFRESH_TREF Fld(2,0) -#define Lmrefresh_Tref(x) ((x) << FShft(LMREFRESH_TREF)) - -/* GSCTRL - Graphics surface control register */ -#define GSCTRL_LUT_EN (1 << 31) -#define GSCTRL_GPIXFMT Fld(4,27) -#define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GPIXFMT_ARGB4444 ((0x4) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GPIXFMT_ARGB1555 ((0x5) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GPIXFMT_RGB888 ((0x6) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GPIXFMT_RGB565 ((0x7) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GPIXFMT_ARGB8888 ((0x8) << FShft(GSCTRL_GPIXFMT)) -#define GSCTRL_GAMMA_EN (1 << 26) - -#define GSCTRL_GSWIDTH Fld(11,11) -#define Gsctrl_Width(Pixel) /* Display Width [1..2048 pix.] */ \ - (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH)) - -#define GSCTRL_GSHEIGHT Fld(11,0) -#define Gsctrl_Height(Pixel) /* Display Height [1..2048 pix.] */ \ - (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT)) - -/* GBBASE fileds */ -#define GBBASE_GLALPHA Fld(8,24) -#define Gbbase_Glalpha(x) ((x) << FShft(GBBASE_GLALPHA)) - -#define GBBASE_COLKEY Fld(24,0) -#define Gbbase_Colkey(x) ((x) << FShft(GBBASE_COLKEY)) - -/* GDRCTRL fields */ -#define GDRCTRL_PIXDBL (1 << 31) -#define GDRCTRL_PIXHLV (1 << 30) -#define GDRCTRL_LNDBL (1 << 29) -#define GDRCTRL_LNHLV (1 << 28) -#define GDRCTRL_COLKEYM Fld(24,0) -#define Gdrctrl_Colkeym(x) ((x) << FShft(GDRCTRL_COLKEYM)) - -/* GSCADR graphics stream control address register fields */ -#define GSCADR_STR_EN (1 << 31) -#define GSCADR_COLKEY_EN (1 << 30) -#define GSCADR_COLKEYSRC (1 << 29) -#define GSCADR_BLEND_M Fld(2,27) -#define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M)) -#define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M)) -#define GSCADR_BLEND_GLOB ((0x2) << FShft(GSCADR_BLEND_M)) -#define GSCADR_BLEND_PIX ((0x3) << FShft(GSCADR_BLEND_M)) -#define GSCADR_BLEND_POS Fld(2,24) -#define GSCADR_BLEND_GFX ((0x0) << FShft(GSCADR_BLEND_POS)) -#define GSCADR_BLEND_VID ((0x1) << FShft(GSCADR_BLEND_POS)) -#define GSCADR_BLEND_CUR ((0x2) << FShft(GSCADR_BLEND_POS)) -#define GSCADR_GBASE_ADR Fld(23,0) -#define Gscadr_Gbase_Adr(x) ((x) << FShft(GSCADR_GBASE_ADR)) - -/* GSADR graphics stride address register fields */ -#define GSADR_SRCSTRIDE Fld(10,22) -#define Gsadr_Srcstride(x) ((x) << FShft(GSADR_SRCSTRIDE)) -#define GSADR_XSTART Fld(11,11) -#define Gsadr_Xstart(x) ((x) << FShft(GSADR_XSTART)) -#define GSADR_YSTART Fld(11,0) -#define Gsadr_Ystart(y) ((y) << FShft(GSADR_YSTART)) - -/* GPLUT graphics palette register fields */ -#define GPLUT_LUTADR Fld(8,24) -#define Gplut_Lutadr(x) ((x) << FShft(GPLUT_LUTADR)) -#define GPLUT_LUTDATA Fld(24,0) -#define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) - -/* VSCTRL - Video Surface Control Register */ -#define VSCTRL_VPIXFMT Fld(4,27) -#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_GAMMA_EN (1 << 26) -#define VSCTRL_CSC_EN (1 << 25) -#define VSCTRL_COSITED (1 << 22) -#define VSCTRL_VSWIDTH Fld(11,11) -#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \ - (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH)) -#define VSCTRL_VSHEIGHT Fld(11,0) -#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \ - (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT)) - -/* VBBASE - Video Blending Base Register */ -#define VBBASE_GLALPHA Fld(8,24) -#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA)) - -#define VBBASE_COLKEY Fld(24,0) -#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY)) - -/* VCMSK - Video Color Key Mask Register */ -#define VCMSK_COLKEY_M Fld(24,0) -#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M)) - -/* VSCADR - Video Stream Control Rddress Register */ -#define VSCADR_STR_EN (1 << 31) -#define VSCADR_COLKEY_EN (1 << 30) -#define VSCADR_COLKEYSRC (1 << 29) -#define VSCADR_BLEND_M Fld(2,27) -#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_POS Fld(2,24) -#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_VBASE_ADR Fld(23,0) -#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR)) - -/* VUBASE - Video U Base Register */ -#define VUBASE_UVHALFSTR (1 << 31) -#define VUBASE_UBASE_ADR Fld(24,0) -#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR)) - -/* VVBASE - Video V Base Register */ -#define VVBASE_VBASE_ADR Fld(24,0) -#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR)) - -/* VSADR - Video Stride Address Register */ -#define VSADR_SRCSTRIDE Fld(10,22) -#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE)) -#define VSADR_XSTART Fld(11,11) -#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART)) -#define VSADR_YSTART Fld(11,0) -#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART)) - -/* VSCTRL - Video Surface Control Register */ -#define VSCTRL_VPIXFMT Fld(4,27) -#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT)) -#define VSCTRL_GAMMA_EN (1 << 26) -#define VSCTRL_CSC_EN (1 << 25) -#define VSCTRL_COSITED (1 << 22) -#define VSCTRL_VSWIDTH Fld(11,11) -#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \ - (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH)) -#define VSCTRL_VSHEIGHT Fld(11,0) -#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \ - (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT)) - -/* VBBASE - Video Blending Base Register */ -#define VBBASE_GLALPHA Fld(8,24) -#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA)) - -#define VBBASE_COLKEY Fld(24,0) -#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY)) - -/* VCMSK - Video Color Key Mask Register */ -#define VCMSK_COLKEY_M Fld(24,0) -#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M)) - -/* VSCADR - Video Stream Control Rddress Register */ -#define VSCADR_STR_EN (1 << 31) -#define VSCADR_COLKEY_EN (1 << 30) -#define VSCADR_COLKEYSRC (1 << 29) -#define VSCADR_BLEND_M Fld(2,27) -#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M)) -#define VSCADR_BLEND_POS Fld(2,24) -#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS)) -#define VSCADR_VBASE_ADR Fld(23,0) -#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR)) - -/* VUBASE - Video U Base Register */ -#define VUBASE_UVHALFSTR (1 << 31) -#define VUBASE_UBASE_ADR Fld(24,0) -#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR)) - -/* VVBASE - Video V Base Register */ -#define VVBASE_VBASE_ADR Fld(24,0) -#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR)) - -/* VSADR - Video Stride Address Register */ -#define VSADR_SRCSTRIDE Fld(10,22) -#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE)) -#define VSADR_XSTART Fld(11,11) -#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART)) -#define VSADR_YSTART Fld(11,0) -#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART)) - -/* HCCTRL - Hardware Cursor Register fields */ -#define HCCTRL_CUR_EN (1 << 31) -#define HCCTRL_COLKEY_EN (1 << 29) -#define HCCTRL_COLKEYSRC (1 << 28) -#define HCCTRL_BLEND_M Fld(2,26) -#define HCCTRL_BLEND_NONE ((0x0) << FShft(HCCTRL_BLEND_M)) -#define HCCTRL_BLEND_INV ((0x1) << FShft(HCCTRL_BLEND_M)) -#define HCCTRL_BLEND_GLOB ((0x2) << FShft(HCCTRL_BLEND_M)) -#define HCCTRL_BLEND_PIX ((0x3) << FShft(HCCTRL_BLEND_M)) -#define HCCTRL_CPIXFMT Fld(3,23) -#define HCCTRL_CPIXFMT_RGB332 ((0x3) << FShft(HCCTRL_CPIXFMT)) -#define HCCTRL_CPIXFMT_ARGB4444 ((0x4) << FShft(HCCTRL_CPIXFMT)) -#define HCCTRL_CPIXFMT_ARGB1555 ((0x5) << FShft(HCCTRL_CPIXFMT)) -#define HCCTRL_CBASE_ADR Fld(23,0) -#define Hcctrl_Cbase_Adr(x) ((x) << FShft(HCCTRL_CBASE_ADR)) - -/* HCSIZE Hardware Cursor Size Register fields */ -#define HCSIZE_BLEND_POS Fld(2,29) -#define HCSIZE_BLEND_GFX ((0x0) << FShft(HCSIZE_BLEND_POS)) -#define HCSIZE_BLEND_VID ((0x1) << FShft(HCSIZE_BLEND_POS)) -#define HCSIZE_BLEND_CUR ((0x2) << FShft(HCSIZE_BLEND_POS)) -#define HCSIZE_CWIDTH Fld(3,16) -#define Hcsize_Cwidth(x) ((x) << FShft(HCSIZE_CWIDTH)) -#define HCSIZE_CHEIGHT Fld(3,0) -#define Hcsize_Cheight(x) ((x) << FShft(HCSIZE_CHEIGHT)) - -/* HCPOS Hardware Cursor Position Register fields */ -#define HCPOS_SWITCHSRC (1 << 30) -#define HCPOS_CURBLINK Fld(6,24) -#define Hcpos_Curblink(x) ((x) << FShft(HCPOS_CURBLINK)) -#define HCPOS_XSTART Fld(12,12) -#define Hcpos_Xstart(x) ((x) << FShft(HCPOS_XSTART)) -#define HCPOS_YSTART Fld(12,0) -#define Hcpos_Ystart(y) ((y) << FShft(HCPOS_YSTART)) - -/* HCBADR Hardware Cursor Blend Address Register */ -#define HCBADR_GLALPHA Fld(8,24) -#define Hcbadr_Glalpha(x) ((x) << FShft(HCBADR_GLALPHA)) -#define HCBADR_COLKEY Fld(24,0) -#define Hcbadr_Colkey(x) ((x) << FShft(HCBADR_COLKEY)) - -/* HCCKMSK - Hardware Cursor Color Key Mask Register */ -#define HCCKMSK_COLKEY_M Fld(24,0) -#define Hcckmsk_Colkey_M(x) ((x) << FShft(HCCKMSK_COLKEY_M)) - -/* DSCTRL - Display sync control register */ -#define DSCTRL_SYNCGEN_EN (1 << 31) -#define DSCTRL_DPL_RST (1 << 29) -#define DSCTRL_PWRDN_M (1 << 28) -#define DSCTRL_UPDSYNCCNT (1 << 26) -#define DSCTRL_UPDINTCNT (1 << 25) -#define DSCTRL_UPDCNT (1 << 24) -#define DSCTRL_UPDWAIT Fld(4,16) -#define Dsctrl_Updwait(x) ((x) << FShft(DSCTRL_UPDWAIT)) -#define DSCTRL_CLKPOL (1 << 11) -#define DSCTRL_CSYNC_EN (1 << 10) -#define DSCTRL_VS_SLAVE (1 << 7) -#define DSCTRL_HS_SLAVE (1 << 6) -#define DSCTRL_BLNK_POL (1 << 5) -#define DSCTRL_BLNK_DIS (1 << 4) -#define DSCTRL_VS_POL (1 << 3) -#define DSCTRL_VS_DIS (1 << 2) -#define DSCTRL_HS_POL (1 << 1) -#define DSCTRL_HS_DIS (1 << 0) - -/* DHT01 - Display horizontal timing register 01 */ -#define DHT01_HBPS Fld(12,16) -#define Dht01_Hbps(x) ((x) << FShft(DHT01_HBPS)) -#define DHT01_HT Fld(12,0) -#define Dht01_Ht(x) ((x) << FShft(DHT01_HT)) - -/* DHT02 - Display horizontal timing register 02 */ -#define DHT02_HAS Fld(12,16) -#define Dht02_Has(x) ((x) << FShft(DHT02_HAS)) -#define DHT02_HLBS Fld(12,0) -#define Dht02_Hlbs(x) ((x) << FShft(DHT02_HLBS)) - -/* DHT03 - Display horizontal timing register 03 */ -#define DHT03_HFPS Fld(12,16) -#define Dht03_Hfps(x) ((x) << FShft(DHT03_HFPS)) -#define DHT03_HRBS Fld(12,0) -#define Dht03_Hrbs(x) ((x) << FShft(DHT03_HRBS)) - -/* DVT01 - Display vertical timing register 01 */ -#define DVT01_VBPS Fld(12,16) -#define Dvt01_Vbps(x) ((x) << FShft(DVT01_VBPS)) -#define DVT01_VT Fld(12,0) -#define Dvt01_Vt(x) ((x) << FShft(DVT01_VT)) - -/* DVT02 - Display vertical timing register 02 */ -#define DVT02_VAS Fld(12,16) -#define Dvt02_Vas(x) ((x) << FShft(DVT02_VAS)) -#define DVT02_VTBS Fld(12,0) -#define Dvt02_Vtbs(x) ((x) << FShft(DVT02_VTBS)) - -/* DVT03 - Display vertical timing register 03 */ -#define DVT03_VFPS Fld(12,16) -#define Dvt03_Vfps(x) ((x) << FShft(DVT03_VFPS)) -#define DVT03_VBBS Fld(12,0) -#define Dvt03_Vbbs(x) ((x) << FShft(DVT03_VBBS)) - -/* DVECTRL - display vertical event control register */ -#define DVECTRL_VEVENT Fld(12,16) -#define Dvectrl_Vevent(x) ((x) << FShft(DVECTRL_VEVENT)) -#define DVECTRL_VFETCH Fld(12,0) -#define Dvectrl_Vfetch(x) ((x) << FShft(DVECTRL_VFETCH)) - -/* DHDET - display horizontal DE timing register */ -#define DHDET_HDES Fld(12,16) -#define Dhdet_Hdes(x) ((x) << FShft(DHDET_HDES)) -#define DHDET_HDEF Fld(12,0) -#define Dhdet_Hdef(x) ((x) << FShft(DHDET_HDEF)) - -/* DVDET - display vertical DE timing register */ -#define DVDET_VDES Fld(12,16) -#define Dvdet_Vdes(x) ((x) << FShft(DVDET_VDES)) -#define DVDET_VDEF Fld(12,0) -#define Dvdet_Vdef(x) ((x) << FShft(DVDET_VDEF)) - -/* DODMSK - display output data mask register */ -#define DODMSK_MASK_LVL (1 << 31) -#define DODMSK_BLNK_LVL (1 << 30) -#define DODMSK_MASK_B Fld(8,16) -#define Dodmsk_Mask_B(x) ((x) << FShft(DODMSK_MASK_B)) -#define DODMSK_MASK_G Fld(8,8) -#define Dodmsk_Mask_G(x) ((x) << FShft(DODMSK_MASK_G)) -#define DODMSK_MASK_R Fld(8,0) -#define Dodmsk_Mask_R(x) ((x) << FShft(DODMSK_MASK_R)) - -/* DBCOL - display border color control register */ -#define DBCOL_BORDCOL Fld(24,0) -#define Dbcol_Bordcol(x) ((x) << FShft(DBCOL_BORDCOL)) - -/* DVLNUM - display vertical line number register */ -#define DVLNUM_VLINE Fld(12,0) -#define Dvlnum_Vline(x) ((x) << FShft(DVLNUM_VLINE)) - -/* DMCTRL - Display Memory Control Register */ -#define DMCTRL_MEM_REF Fld(2,30) -#define DMCTRL_MEM_REF_ACT ((0x0) << FShft(DMCTRL_MEM_REF)) -#define DMCTRL_MEM_REF_HB ((0x1) << FShft(DMCTRL_MEM_REF)) -#define DMCTRL_MEM_REF_VB ((0x2) << FShft(DMCTRL_MEM_REF)) -#define DMCTRL_MEM_REF_BOTH ((0x3) << FShft(DMCTRL_MEM_REF)) -#define DMCTRL_UV_THRHLD Fld(6,24) -#define Dmctrl_Uv_Thrhld(x) ((x) << FShft(DMCTRL_UV_THRHLD)) -#define DMCTRL_V_THRHLD Fld(7,16) -#define Dmctrl_V_Thrhld(x) ((x) << FShft(DMCTRL_V_THRHLD)) -#define DMCTRL_D_THRHLD Fld(7,8) -#define Dmctrl_D_Thrhld(x) ((x) << FShft(DMCTRL_D_THRHLD)) -#define DMCTRL_BURSTLEN Fld(6,0) -#define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) - -/* DINTRS - Display Interrupt Status Register */ -#define DINTRS_CUR_OR_S (1 << 18) -#define DINTRS_STR2_OR_S (1 << 17) -#define DINTRS_STR1_OR_S (1 << 16) -#define DINTRS_CUR_UR_S (1 << 6) -#define DINTRS_STR2_UR_S (1 << 5) -#define DINTRS_STR1_UR_S (1 << 4) -#define DINTRS_VEVENT1_S (1 << 3) -#define DINTRS_VEVENT0_S (1 << 2) -#define DINTRS_HBLNK1_S (1 << 1) -#define DINTRS_HBLNK0_S (1 << 0) - -/* DINTRE - Display Interrupt Enable Register */ -#define DINTRE_CUR_OR_EN (1 << 18) -#define DINTRE_STR2_OR_EN (1 << 17) -#define DINTRE_STR1_OR_EN (1 << 16) -#define DINTRE_CUR_UR_EN (1 << 6) -#define DINTRE_STR2_UR_EN (1 << 5) -#define DINTRE_STR1_UR_EN (1 << 4) -#define DINTRE_VEVENT1_EN (1 << 3) -#define DINTRE_VEVENT0_EN (1 << 2) -#define DINTRE_HBLNK1_EN (1 << 1) -#define DINTRE_HBLNK0_EN (1 << 0) - -/* DINTRS - Display Interrupt Status Register */ -#define DINTRS_CUR_OR_S (1 << 18) -#define DINTRS_STR2_OR_S (1 << 17) -#define DINTRS_STR1_OR_S (1 << 16) -#define DINTRS_CUR_UR_S (1 << 6) -#define DINTRS_STR2_UR_S (1 << 5) -#define DINTRS_STR1_UR_S (1 << 4) -#define DINTRS_VEVENT1_S (1 << 3) -#define DINTRS_VEVENT0_S (1 << 2) -#define DINTRS_HBLNK1_S (1 << 1) -#define DINTRS_HBLNK0_S (1 << 0) - -/* DINTRE - Display Interrupt Enable Register */ -#define DINTRE_CUR_OR_EN (1 << 18) -#define DINTRE_STR2_OR_EN (1 << 17) -#define DINTRE_STR1_OR_EN (1 << 16) -#define DINTRE_CUR_UR_EN (1 << 6) -#define DINTRE_STR2_UR_EN (1 << 5) -#define DINTRE_STR1_UR_EN (1 << 4) -#define DINTRE_VEVENT1_EN (1 << 3) -#define DINTRE_VEVENT0_EN (1 << 2) -#define DINTRE_HBLNK1_EN (1 << 1) -#define DINTRE_HBLNK0_EN (1 << 0) - - -/* DLSTS - display load status register */ -#define DLSTS_RLD_ADONE (1 << 23) -/* #define DLSTS_RLD_ADOUT Fld(23,0) */ - -/* DLLCTRL - display list load control register */ -#define DLLCTRL_RLD_ADRLN Fld(8,24) -#define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) - -/* CLIPCTRL - Clipping Control Register */ -#define CLIPCTRL_HSKIP Fld(11,16) -#define Clipctrl_Hskip ((x) << FShft(CLIPCTRL_HSKIP)) -#define CLIPCTRL_VSKIP Fld(11,0) -#define Clipctrl_Vskip ((x) << FShft(CLIPCTRL_VSKIP)) - -/* SPOCTRL - Scale Pitch/Order Control Register */ -#define SPOCTRL_H_SC_BP (1 << 31) -#define SPOCTRL_V_SC_BP (1 << 30) -#define SPOCTRL_HV_SC_OR (1 << 29) -#define SPOCTRL_VS_UR_C (1 << 27) -#define SPOCTRL_VORDER Fld(2,16) -#define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VPITCH Fld(16,0) -#define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) - -/* SVCTRL - Scale Vertical Control Register */ -#define SVCTRL_INITIAL1 Fld(16,16) -#define Svctrl_Initial1(x) ((x) << FShft(SVCTRL_INITIAL1)) -#define SVCTRL_INITIAL2 Fld(16,0) -#define Svctrl_Initial2(x) ((x) << FShft(SVCTRL_INITIAL2)) - -/* SHCTRL - Scale Horizontal Control Register */ -#define SHCTRL_HINITIAL Fld(16,16) -#define Shctrl_Hinitial(x) ((x) << FShft(SHCTRL_HINITIAL)) -#define SHCTRL_HDECIM (1 << 15) -#define SHCTRL_HPITCH Fld(15,0) -#define Shctrl_Hpitch(x) ((x) << FShft(SHCTRL_HPITCH)) - -/* SSSIZE - Scale Surface Size Register */ -#define SSSIZE_SC_WIDTH Fld(11,16) -#define Sssize_Sc_Width(x) ((x) << FShft(SSSIZE_SC_WIDTH)) -#define SSSIZE_SC_HEIGHT Fld(11,0) -#define Sssize_Sc_Height(x) ((x) << FShft(SSSIZE_SC_HEIGHT)) - -#endif /* __REG_BITS_2700G_ */ diff --git a/drivers/video/fbdev/mbx/regs.h b/drivers/video/fbdev/mbx/regs.h deleted file mode 100644 index 591fc9d260846..0000000000000 --- a/drivers/video/fbdev/mbx/regs.h +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __REGS_2700G_ -#define __REGS_2700G_ - -/* extern unsigned long virt_base_2700; */ -/* #define __REG_2700G(x) (*(volatile unsigned long*)((x)+virt_base_2700)) */ -#define __REG_2700G(x) ((x)+virt_base_2700) - -/* System Configuration Registers (0x0000_0000 0x0000_0010) */ -#define SYSCFG __REG_2700G(0x00000000) -#define PFBASE __REG_2700G(0x00000004) -#define PFCEIL __REG_2700G(0x00000008) -#define POLLFLAG __REG_2700G(0x0000000c) -#define SYSRST __REG_2700G(0x00000010) - -/* Interrupt Control Registers (0x0000_0014 0x0000_002F) */ -#define NINTPW __REG_2700G(0x00000014) -#define MINTENABLE __REG_2700G(0x00000018) -#define MINTSTAT __REG_2700G(0x0000001c) -#define SINTENABLE __REG_2700G(0x00000020) -#define SINTSTAT __REG_2700G(0x00000024) -#define SINTCLR __REG_2700G(0x00000028) - -/* Clock Control Registers (0x0000_002C 0x0000_005F) */ -#define SYSCLKSRC __REG_2700G(0x0000002c) -#define PIXCLKSRC __REG_2700G(0x00000030) -#define CLKSLEEP __REG_2700G(0x00000034) -#define COREPLL __REG_2700G(0x00000038) -#define DISPPLL __REG_2700G(0x0000003c) -#define PLLSTAT __REG_2700G(0x00000040) -#define VOVRCLK __REG_2700G(0x00000044) -#define PIXCLK __REG_2700G(0x00000048) -#define MEMCLK __REG_2700G(0x0000004c) -#define M24CLK __REG_2700G(0x00000050) -#define MBXCLK __REG_2700G(0x00000054) -#define SDCLK __REG_2700G(0x00000058) -#define PIXCLKDIV __REG_2700G(0x0000005c) - -/* LCD Port Control Register (0x0000_0060 0x0000_006F) */ -#define LCD_CONFIG __REG_2700G(0x00000060) - -/* On-Die Frame Buffer Registers (0x0000_0064 0x0000_006B) */ -#define ODFBPWR __REG_2700G(0x00000064) -#define ODFBSTAT __REG_2700G(0x00000068) - -/* GPIO Registers (0x0000_006C 0x0000_007F) */ -#define GPIOCGF __REG_2700G(0x0000006c) -#define GPIOHI __REG_2700G(0x00000070) -#define GPIOLO __REG_2700G(0x00000074) -#define GPIOSTAT __REG_2700G(0x00000078) - -/* Pulse Width Modulator (PWM) Registers (0x0000_0200 0x0000_02FF) */ -#define PWMRST __REG_2700G(0x00000200) -#define PWMCFG __REG_2700G(0x00000204) -#define PWM0DIV __REG_2700G(0x00000210) -#define PWM0DUTY __REG_2700G(0x00000214) -#define PWM0PER __REG_2700G(0x00000218) -#define PWM1DIV __REG_2700G(0x00000220) -#define PWM1DUTY __REG_2700G(0x00000224) -#define PWM1PER __REG_2700G(0x00000228) - -/* Identification (ID) Registers (0x0000_0300 0x0000_0FFF) */ -#define ID __REG_2700G(0x00000FF0) - -/* Local Memory (SDRAM) Interface Registers (0x0000_1000 0x0000_1FFF) */ -#define LMRST __REG_2700G(0x00001000) -#define LMCFG __REG_2700G(0x00001004) -#define LMPWR __REG_2700G(0x00001008) -#define LMPWRSTAT __REG_2700G(0x0000100c) -#define LMCEMR __REG_2700G(0x00001010) -#define LMTYPE __REG_2700G(0x00001014) -#define LMTIM __REG_2700G(0x00001018) -#define LMREFRESH __REG_2700G(0x0000101c) -#define LMPROTMIN __REG_2700G(0x00001020) -#define LMPROTMAX __REG_2700G(0x00001024) -#define LMPROTCFG __REG_2700G(0x00001028) -#define LMPROTERR __REG_2700G(0x0000102c) - -/* Plane Controller Registers (0x0000_2000 0x0000_2FFF) */ -#define GSCTRL __REG_2700G(0x00002000) -#define VSCTRL __REG_2700G(0x00002004) -#define GBBASE __REG_2700G(0x00002020) -#define VBBASE __REG_2700G(0x00002024) -#define GDRCTRL __REG_2700G(0x00002040) -#define VCMSK __REG_2700G(0x00002044) -#define GSCADR __REG_2700G(0x00002060) -#define VSCADR __REG_2700G(0x00002064) -#define VUBASE __REG_2700G(0x00002084) -#define VVBASE __REG_2700G(0x000020a4) -#define GSADR __REG_2700G(0x000020c0) -#define VSADR __REG_2700G(0x000020c4) -#define HCCTRL __REG_2700G(0x00002100) -#define HCSIZE __REG_2700G(0x00002110) -#define HCPOS __REG_2700G(0x00002120) -#define HCBADR __REG_2700G(0x00002130) -#define HCCKMSK __REG_2700G(0x00002140) -#define GPLUT __REG_2700G(0x00002150) -#define DSCTRL __REG_2700G(0x00002154) -#define DHT01 __REG_2700G(0x00002158) -#define DHT02 __REG_2700G(0x0000215c) -#define DHT03 __REG_2700G(0x00002160) -#define DVT01 __REG_2700G(0x00002164) -#define DVT02 __REG_2700G(0x00002168) -#define DVT03 __REG_2700G(0x0000216c) -#define DBCOL __REG_2700G(0x00002170) -#define BGCOLOR __REG_2700G(0x00002174) -#define DINTRS __REG_2700G(0x00002178) -#define DINTRE __REG_2700G(0x0000217c) -#define DINTRCNT __REG_2700G(0x00002180) -#define DSIG __REG_2700G(0x00002184) -#define DMCTRL __REG_2700G(0x00002188) -#define CLIPCTRL __REG_2700G(0x0000218c) -#define SPOCTRL __REG_2700G(0x00002190) -#define SVCTRL __REG_2700G(0x00002194) - -/* 0x0000_2198 */ -/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */ -#define VSCOEFF0 __REG_2700G(0x00002198) -#define VSCOEFF1 __REG_2700G(0x0000219c) -#define VSCOEFF2 __REG_2700G(0x000021a0) -#define VSCOEFF3 __REG_2700G(0x000021a4) -#define VSCOEFF4 __REG_2700G(0x000021a8) - -#define SHCTRL __REG_2700G(0x000021b0) - -/* 0x0000_21B4 */ -/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */ -#define HSCOEFF0 __REG_2700G(0x000021b4) -#define HSCOEFF1 __REG_2700G(0x000021b8) -#define HSCOEFF2 __REG_2700G(0x000021bc) -#define HSCOEFF3 __REG_2700G(0x000021c0) -#define HSCOEFF4 __REG_2700G(0x000021c4) -#define HSCOEFF5 __REG_2700G(0x000021c8) -#define HSCOEFF6 __REG_2700G(0x000021cc) -#define HSCOEFF7 __REG_2700G(0x000021d0) -#define HSCOEFF8 __REG_2700G(0x000021d4) - -#define SSSIZE __REG_2700G(0x000021D8) - -/* 0x0000_2200 */ -/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */ -#define VIDGAM0 __REG_2700G(0x00002200) -#define VIDGAM1 __REG_2700G(0x00002204) -#define VIDGAM2 __REG_2700G(0x00002208) -#define VIDGAM3 __REG_2700G(0x0000220c) -#define VIDGAM4 __REG_2700G(0x00002210) -#define VIDGAM5 __REG_2700G(0x00002214) -#define VIDGAM6 __REG_2700G(0x00002218) -#define VIDGAM7 __REG_2700G(0x0000221c) -#define VIDGAM8 __REG_2700G(0x00002220) -#define VIDGAM9 __REG_2700G(0x00002224) -#define VIDGAM10 __REG_2700G(0x00002228) -#define VIDGAM11 __REG_2700G(0x0000222c) -#define VIDGAM12 __REG_2700G(0x00002230) -#define VIDGAM13 __REG_2700G(0x00002234) -#define VIDGAM14 __REG_2700G(0x00002238) -#define VIDGAM15 __REG_2700G(0x0000223c) -#define VIDGAM16 __REG_2700G(0x00002240) - -/* 0x0000_2250 */ -/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */ -#define GFXGAM0 __REG_2700G(0x00002250) -#define GFXGAM1 __REG_2700G(0x00002254) -#define GFXGAM2 __REG_2700G(0x00002258) -#define GFXGAM3 __REG_2700G(0x0000225c) -#define GFXGAM4 __REG_2700G(0x00002260) -#define GFXGAM5 __REG_2700G(0x00002264) -#define GFXGAM6 __REG_2700G(0x00002268) -#define GFXGAM7 __REG_2700G(0x0000226c) -#define GFXGAM8 __REG_2700G(0x00002270) -#define GFXGAM9 __REG_2700G(0x00002274) -#define GFXGAM10 __REG_2700G(0x00002278) -#define GFXGAM11 __REG_2700G(0x0000227c) -#define GFXGAM12 __REG_2700G(0x00002280) -#define GFXGAM13 __REG_2700G(0x00002284) -#define GFXGAM14 __REG_2700G(0x00002288) -#define GFXGAM15 __REG_2700G(0x0000228c) -#define GFXGAM16 __REG_2700G(0x00002290) - -#define DLSTS __REG_2700G(0x00002300) -#define DLLCTRL __REG_2700G(0x00002304) -#define DVLNUM __REG_2700G(0x00002308) -#define DUCTRL __REG_2700G(0x0000230c) -#define DVECTRL __REG_2700G(0x00002310) -#define DHDET __REG_2700G(0x00002314) -#define DVDET __REG_2700G(0x00002318) -#define DODMSK __REG_2700G(0x0000231c) -#define CSC01 __REG_2700G(0x00002330) -#define CSC02 __REG_2700G(0x00002334) -#define CSC03 __REG_2700G(0x00002338) -#define CSC04 __REG_2700G(0x0000233c) -#define CSC05 __REG_2700G(0x00002340) - -#define FB_MEMORY_START __REG_2700G(0x00060000) - -#endif /* __REGS_2700G_ */ diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h deleted file mode 100644 index 35921cb6d1e52..0000000000000 --- a/include/video/mbxfb.h +++ /dev/null @@ -1,99 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __MBX_FB_H -#define __MBX_FB_H - -#include <asm/ioctl.h> -#include <asm/types.h> - -struct mbxfb_val { - unsigned int defval; - unsigned int min; - unsigned int max; -}; - -struct fb_info; - -struct mbxfb_platform_data { - /* Screen info */ - struct mbxfb_val xres; - struct mbxfb_val yres; - struct mbxfb_val bpp; - - /* Memory info */ - unsigned long memsize; /* if 0 use ODFB? */ - unsigned long timings1; - unsigned long timings2; - unsigned long timings3; - - int (*probe)(struct fb_info *fb); - int (*remove)(struct fb_info *fb); -}; - -/* planar */ -#define MBXFB_FMT_YUV16 0 -#define MBXFB_FMT_YUV12 1 - -/* packed */ -#define MBXFB_FMT_UY0VY1 2 -#define MBXFB_FMT_VY0UY1 3 -#define MBXFB_FMT_Y0UY1V 4 -#define MBXFB_FMT_Y0VY1U 5 -struct mbxfb_overlaySetup { - __u32 enable; - __u32 x, y; - __u32 width, height; - __u32 fmt; - __u32 mem_offset; - __u32 scaled_width; - __u32 scaled_height; - - /* Filled by the driver */ - __u32 U_offset; - __u32 V_offset; - - __u16 Y_stride; - __u16 UV_stride; -}; - -#define MBXFB_ALPHABLEND_NONE 0 -#define MBXFB_ALPHABLEND_GLOBAL 1 -#define MBXFB_ALPHABLEND_PIXEL 2 - -#define MBXFB_COLORKEY_DISABLED 0 -#define MBXFB_COLORKEY_PREVIOUS 1 -#define MBXFB_COLORKEY_CURRENT 2 -struct mbxfb_alphaCtl { - __u8 overlay_blend_mode; - __u8 overlay_colorkey_mode; - __u8 overlay_global_alpha; - __u32 overlay_colorkey; - __u32 overlay_colorkey_mask; - - __u8 graphics_blend_mode; - __u8 graphics_colorkey_mode; - __u8 graphics_global_alpha; - __u32 graphics_colorkey; - __u32 graphics_colorkey_mask; -}; - -#define MBXFB_PLANE_GRAPHICS 0 -#define MBXFB_PLANE_VIDEO 1 -struct mbxfb_planeorder { - __u8 bottom; - __u8 top; -}; - -struct mbxfb_reg { - __u32 addr; /* offset from 0x03fe 0000 */ - __u32 val; /* value */ - __u32 mask; /* which bits to touch (for write) */ -}; - -#define MBXFB_IOCX_OVERLAY _IOWR(0xF4, 0x00,struct mbxfb_overlaySetup) -#define MBXFB_IOCG_ALPHA _IOR(0xF4, 0x01,struct mbxfb_alphaCtl) -#define MBXFB_IOCS_ALPHA _IOW(0xF4, 0x02,struct mbxfb_alphaCtl) -#define MBXFB_IOCS_PLANEORDER _IOR(0xF4, 0x03,struct mbxfb_planeorder) -#define MBXFB_IOCS_REG _IOW(0xF4, 0x04,struct mbxfb_reg) -#define MBXFB_IOCX_REG _IOWR(0xF4, 0x05,struct mbxfb_reg) - -#endif /* __MBX_FB_H */ -- GitLab From 8c2bb49f38c94063a739da1758364645e5cd53e1 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Mon, 7 Sep 2020 12:32:20 +0530 Subject: [PATCH 0963/1494] video: fbdev: aty: radeon_pm: remove redundant CONFIG_PM container Fixes commit 42ddb453a0cd ("radeon: Conditionally compile PM code") Before the above mentioned patch, codes between the line number 547 and 2803 were already inside "#ifdef CONFIG_PM" container. Thus, addition of "#if defined(CONFIG_PM)" was not required in the patch. It also affected the "#ifdef CONFIG_PPC_OF" container (line 1943-2510). From the current snapshot of radeon_pm.c, remove: 1434 | #if defined(CONFIG_PM) and, 2213 | #endif This removes the redundant CONFIG_PM directive as well as fixes the CONFIG_PPC (earlier CONFIG_PPC_OF) container. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Thierry Reding <treding@nvidia.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907070221.29938-2-vaibhavgupta40@gmail.com --- drivers/video/fbdev/aty/radeon_pm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index f3d8123d7f363..91ceec2f9ac0f 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c @@ -1431,7 +1431,6 @@ static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) mdelay( 15); } -#if defined(CONFIG_PM) #if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC) static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo) { @@ -2210,7 +2209,6 @@ static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo) radeon_pm_m10_enable_lvds_spread_spectrum(rinfo); } #endif -#endif #if 0 /* Not ready yet */ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) -- GitLab From 8e0bd31dad0665d8b942cb05495abb5ec931fde0 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Mon, 7 Sep 2020 12:32:21 +0530 Subject: [PATCH 0964/1494] fbdev: radeonfb: use generic power management Drivers using legacy PCI power management .suspend()/.resume() callbacks have to manage PCI states and device's PM states themselves. They also need to take care of standard configuration registers. Switch to generic power management framework using a "struct dev_pm_ops" variable to take the unnecessary load from the driver. This also avoids the need for the driver to directly call most of the PCI helper functions and device power state control functions, as through the generic framework PCI Core takes care of the necessary operations, and drivers are required to do only device-specific jobs. Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Cc: Bjorn Helgaas <helgaas@kernel.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Bjorn Helgaas <bjorn@helgaas.com> Cc: Vaibhav Gupta <vaibhav.varodek@gmail.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Thierry Reding <treding@nvidia.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907070221.29938-3-vaibhavgupta40@gmail.com --- drivers/video/fbdev/aty/radeon_base.c | 10 +++++--- drivers/video/fbdev/aty/radeon_pm.c | 36 +++++++++++++++++++++------ drivers/video/fbdev/aty/radeonfb.h | 3 +-- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index 13bd2bd5c043a..2fe6901504206 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -2555,16 +2555,18 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) framebuffer_release(info); } +#ifdef CONFIG_PM +#define RADEONFB_PCI_PM_OPS (&radeonfb_pci_pm_ops) +#else +#define RADEONFB_PCI_PM_OPS NULL +#endif static struct pci_driver radeonfb_driver = { .name = "radeonfb", .id_table = radeonfb_pci_table, .probe = radeonfb_pci_register, .remove = radeonfb_pci_unregister, -#ifdef CONFIG_PM - .suspend = radeonfb_pci_suspend, - .resume = radeonfb_pci_resume, -#endif /* CONFIG_PM */ + .driver.pm = RADEONFB_PCI_PM_OPS, }; #ifndef MODULE diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index 91ceec2f9ac0f..b5fbd53296528 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c @@ -2611,8 +2611,9 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) } } -int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) +static int radeonfb_pci_suspend_late(struct device *dev, pm_message_t mesg) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; @@ -2660,11 +2661,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) pmac_suspend_agp_for_card(pdev); #endif /* CONFIG_PPC_PMAC */ - /* It's unclear whether or when the generic code will do that, so let's - * do it ourselves. We save state before we do any power management - */ - pci_save_state(pdev); - /* If we support wakeup from poweroff, we save all regs we can including cfg * space */ @@ -2689,7 +2685,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) msleep(20); OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); } - pci_disable_device(pdev); } /* If we support D2, we go to it (should be fixed later with a flag forcing * D3 only for some laptops) @@ -2705,6 +2700,21 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) return 0; } +static int radeonfb_pci_suspend(struct device *dev) +{ + return radeonfb_pci_suspend_late(dev, PMSG_SUSPEND); +} + +static int radeonfb_pci_hibernate(struct device *dev) +{ + return radeonfb_pci_suspend_late(dev, PMSG_HIBERNATE); +} + +static int radeonfb_pci_freeze(struct device *dev) +{ + return radeonfb_pci_suspend_late(dev, PMSG_FREEZE); +} + static int radeon_check_power_loss(struct radeonfb_info *rinfo) { return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || @@ -2712,8 +2722,9 @@ static int radeon_check_power_loss(struct radeonfb_info *rinfo) rinfo->save_regs[3] != INPLL(SCLK_CNTL); } -int radeonfb_pci_resume(struct pci_dev *pdev) +static int radeonfb_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct fb_info *info = pci_get_drvdata(pdev); struct radeonfb_info *rinfo = info->par; int rc = 0; @@ -2795,6 +2806,15 @@ int radeonfb_pci_resume(struct pci_dev *pdev) return rc; } +const struct dev_pm_ops radeonfb_pci_pm_ops = { + .suspend = radeonfb_pci_suspend, + .resume = radeonfb_pci_resume, + .freeze = radeonfb_pci_freeze, + .thaw = radeonfb_pci_resume, + .poweroff = radeonfb_pci_hibernate, + .restore = radeonfb_pci_resume, +}; + #ifdef CONFIG_PPC__disabled static void radeonfb_early_resume(void *data) { diff --git a/drivers/video/fbdev/aty/radeonfb.h b/drivers/video/fbdev/aty/radeonfb.h index 131b34dd65af6..93f403cbb4150 100644 --- a/drivers/video/fbdev/aty/radeonfb.h +++ b/drivers/video/fbdev/aty/radeonfb.h @@ -483,8 +483,7 @@ extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo); extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid); /* PM Functions */ -extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); -extern int radeonfb_pci_resume(struct pci_dev *pdev); +extern const struct dev_pm_ops radeonfb_pci_pm_ops; extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep); extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); -- GitLab From 884e5cc1dd119d1761f6ea19e904a1492a81f9ee Mon Sep 17 00:00:00 2001 From: Melissa Wen <melissa.srw@gmail.com> Date: Fri, 4 Sep 2020 10:06:05 -0300 Subject: [PATCH 0965/1494] MAINTAINERS: add entry for VKMS Add myself as maintainer of VKMS driver Signed-off-by: Melissa Wen <melissa.srw@gmail.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904130605.vs5tnfhgnemnz6pt@smtp.gmail.com --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 01fb9ee6b951e..d4277824a01c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5640,6 +5640,7 @@ F: drivers/gpu/drm/udl/ DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS) M: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> +M: Melissa Wen <melissa.srw@gmail.com> R: Haneen Mohammed <hamohammed.sa@gmail.com> R: Daniel Vetter <daniel@ffwll.ch> L: dri-devel@lists.freedesktop.org -- GitLab From ecfe6953fa00115414a6fefe49023a1ebc187a98 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:18 +1000 Subject: [PATCH 0966/1494] drm/ttm: introduce ttm_bo_move_null MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pattern is cut-n-pasted across 4 drivers, switch it to a WARN_ON instead, as BUG_ON is considered a bad idea usually. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 24 +++--------------------- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +--- drivers/gpu/drm/qxl/qxl_ttm.c | 12 +----------- drivers/gpu/drm/radeon/radeon_ttm.c | 14 ++------------ include/drm/ttm/ttm_bo_driver.h | 17 +++++++++++++++++ 5 files changed, 24 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c6f4d9ede0e0d..5f7a8e23ed9d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -174,24 +174,6 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) filp->private_data); } -/** - * amdgpu_move_null - Register memory for a buffer object - * - * @bo: The bo to assign the memory to - * @new_mem: The memory to be assigned. - * - * Assign the memory from new_mem to the memory of the buffer object bo. - */ -static void amdgpu_move_null(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem) -{ - struct ttm_resource *old_mem = &bo->mem; - - BUG_ON(old_mem->mm_node != NULL); - *old_mem = *new_mem; - new_mem->mm_node = NULL; -} - /** * amdgpu_mm_node_addr - Compute the GPU relative offset of a GTT buffer. * @@ -676,7 +658,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, adev = amdgpu_ttm_adev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { - amdgpu_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } if ((old_mem->mem_type == TTM_PL_TT && @@ -684,7 +666,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, (old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_TT)) { /* bind is enough */ - amdgpu_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } if (old_mem->mem_type == AMDGPU_PL_GDS || @@ -694,7 +676,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, new_mem->mem_type == AMDGPU_PL_GWS || new_mem->mem_type == AMDGPU_PL_OA) { /* Nothing to save here */ - amdgpu_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 83fdd169a27a5..2c230e0b34dac 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -993,9 +993,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, /* Fake bo copy. */ if (old_reg->mem_type == TTM_PL_SYSTEM && !bo->ttm) { - BUG_ON(bo->mem.mm_node != NULL); - bo->mem = *new_reg; - new_reg->mm_node = NULL; + ttm_bo_move_null(bo, new_reg); goto out; } diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 19b18ea38c340..b19b9641470ce 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -158,16 +158,6 @@ static struct ttm_tt *qxl_ttm_tt_create(struct ttm_buffer_object *bo, return >t->ttm; } -static void qxl_move_null(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem) -{ - struct ttm_resource *old_mem = &bo->mem; - - BUG_ON(old_mem->mm_node != NULL); - *old_mem = *new_mem; - new_mem->mm_node = NULL; -} - static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_operation_ctx *ctx, struct ttm_resource *new_mem) @@ -180,7 +170,7 @@ static int qxl_bo_move(struct ttm_buffer_object *bo, bool evict, return ret; if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { - qxl_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } return ttm_bo_move_memcpy(bo, ctx, new_mem); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 375ffd4a56abf..155e7b971afa8 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -148,16 +148,6 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) filp->private_data); } -static void radeon_move_null(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem) -{ - struct ttm_resource *old_mem = &bo->mem; - - BUG_ON(old_mem->mm_node != NULL); - *old_mem = *new_mem; - new_mem->mm_node = NULL; -} - static int radeon_move_blit(struct ttm_buffer_object *bo, bool evict, bool no_wait_gpu, struct ttm_resource *new_mem, @@ -316,7 +306,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, rdev = radeon_get_rdev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { - radeon_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } if ((old_mem->mem_type == TTM_PL_TT && @@ -324,7 +314,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict, (old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_TT)) { /* bind is enough */ - radeon_move_null(bo, new_mem); + ttm_bo_move_null(bo, new_mem); return 0; } if (!rdev->ring[radeon_copy_ring_index(rdev)].ready || diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index a694388f7b13c..ebba282667ba6 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -520,6 +520,23 @@ static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo spin_unlock(&ttm_bo_glob.lru_lock); } +/** + * ttm_bo_move_null = assign memory for a buffer object. + * @bo: The bo to assign the memory to + * @new_mem: The memory to be assigned. + * + * Assign the memory from new_mem to the memory of the buffer object bo. + */ +static inline void ttm_bo_move_null(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + struct ttm_resource *old_mem = &bo->mem; + + WARN_ON(old_mem->mm_node != NULL); + *old_mem = *new_mem; + new_mem->mm_node = NULL; +} + /** * ttm_bo_unreserve * -- GitLab From 86008a7553e6c57268e4a4f71e3a43e73b1b3ef1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:19 +1000 Subject: [PATCH 0967/1494] drm/ttm: add optional bind/unbind via driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I want to remove the backend funcs Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-3-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_tt.c | 15 +++++++++++--- include/drm/ttm/ttm_bo_driver.h | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 50a8991040220..73c97dcfa512e 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -222,7 +222,10 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) fput(ttm->swap_storage); ttm->swap_storage = NULL; - ttm->func->destroy(bdev, ttm); + if (bdev->driver->ttm_tt_destroy) + bdev->driver->ttm_tt_destroy(bdev, ttm); + else + ttm->func->destroy(bdev, ttm); } static void ttm_tt_init_fields(struct ttm_tt *ttm, @@ -310,7 +313,10 @@ EXPORT_SYMBOL(ttm_dma_tt_fini); void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { if (ttm->state == tt_bound) { - ttm->func->unbind(bdev, ttm); + if (bdev->driver->ttm_tt_unbind) + bdev->driver->ttm_tt_unbind(bdev, ttm); + else + ttm->func->unbind(bdev, ttm); ttm->state = tt_unbound; } } @@ -331,7 +337,10 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, if (ret) return ret; - ret = ttm->func->bind(bdev, ttm, bo_mem); + if (bdev->driver->ttm_tt_bind) + ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem); + else + ret = ttm->func->bind(bdev, ttm, bo_mem); if (unlikely(ret != 0)) return ret; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ebba282667ba6..32c0651cc0fd6 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -90,6 +90,42 @@ struct ttm_bo_driver { */ void (*ttm_tt_unpopulate)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); + /** + * ttm_tt_bind + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * @bo_mem: Pointer to a struct ttm_resource describing the + * memory type and location for binding. + * + * Bind the backend pages into the aperture in the location + * indicated by @bo_mem. This function should be able to handle + * differences between aperture and system page sizes. + */ + int (*ttm_tt_bind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); + + /** + * ttm_tt_unbind + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * + * Unbind previously bound backend pages. This function should be + * able to handle differences between aperture and system page sizes. + */ + void (*ttm_tt_unbind)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); + + /** + * ttm_tt_destroy + * + * @bdev: Pointer to a ttm device + * @ttm: Pointer to a struct ttm_tt. + * + * Destroy the backend. This will be call back from ttm_tt_destroy so + * don't call ttm_tt_destroy from the callback or infinite loop. + */ + void (*ttm_tt_destroy)(struct ttm_bo_device *bdev, struct ttm_tt *ttm); + /** * struct ttm_bo_driver member eviction_valuable * -- GitLab From dc2caa305a6fc5db2b9c1b24ecef8038cd957d07 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:20 +1000 Subject: [PATCH 0968/1494] drm/qxl: move bind/unbind/destroy to the driver function table. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-4-airlied@gmail.com --- drivers/gpu/drm/qxl/qxl_ttm.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index b19b9641470ce..0b8f12e6dd6a8 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -133,12 +133,6 @@ static void qxl_ttm_backend_destroy(struct ttm_bo_device *bdev, kfree(gtt); } -static struct ttm_backend_func qxl_backend_func = { - .bind = &qxl_ttm_backend_bind, - .unbind = &qxl_ttm_backend_unbind, - .destroy = &qxl_ttm_backend_destroy, -}; - static struct ttm_tt *qxl_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) { @@ -149,7 +143,6 @@ static struct ttm_tt *qxl_ttm_tt_create(struct ttm_buffer_object *bo, gtt = kzalloc(sizeof(struct qxl_ttm_tt), GFP_KERNEL); if (gtt == NULL) return NULL; - gtt->ttm.func = &qxl_backend_func; gtt->qdev = qdev; if (ttm_tt_init(>t->ttm, bo, page_flags)) { kfree(gtt); @@ -194,6 +187,9 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo, static struct ttm_bo_driver qxl_bo_driver = { .ttm_tt_create = &qxl_ttm_tt_create, + .ttm_tt_bind = &qxl_ttm_backend_bind, + .ttm_tt_destroy = &qxl_ttm_backend_destroy, + .ttm_tt_unbind = &qxl_ttm_backend_unbind, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &qxl_evict_flags, .move = &qxl_bo_move, -- GitLab From 738edc0adb388f75aec67011f6e8f225b9f29783 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:21 +1000 Subject: [PATCH 0969/1494] drm/ttm/agp: export bind/unbind/destroy for drivers to use. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-5-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_agp_backend.c | 15 +++++++++------ include/drm/ttm/ttm_tt.h | 6 ++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 934a694915478..fbf98cd1a3e58 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -48,8 +48,8 @@ struct ttm_agp_backend { struct agp_bridge_data *bridge; }; -static int ttm_agp_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem) +int ttm_agp_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); struct page *dummy_read_page = ttm_bo_glob.dummy_read_page; @@ -82,9 +82,10 @@ static int ttm_agp_bind(struct ttm_bo_device *bdev, return ret; } +EXPORT_SYMBOL(ttm_agp_bind); -static void ttm_agp_unbind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm) +void ttm_agp_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); @@ -97,9 +98,10 @@ static void ttm_agp_unbind(struct ttm_bo_device *bdev, agp_be->mem = NULL; } } +EXPORT_SYMBOL(ttm_agp_unbind); -static void ttm_agp_destroy(struct ttm_bo_device *bdev, - struct ttm_tt *ttm) +void ttm_agp_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); @@ -108,6 +110,7 @@ static void ttm_agp_destroy(struct ttm_bo_device *bdev, ttm_tt_fini(ttm); kfree(agp_be); } +EXPORT_SYMBOL(ttm_agp_destroy); static struct ttm_backend_func ttm_agp_func = { .bind = ttm_agp_bind, diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 6bda88f8da46a..5a34f16408655 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -266,6 +266,12 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags); int ttm_agp_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); +int ttm_agp_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, struct ttm_resource *bo_mem); +void ttm_agp_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm); +void ttm_agp_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm); #endif #endif -- GitLab From a68bb1938b518c53ba3733be6be767305ae2f2c9 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:22 +1000 Subject: [PATCH 0970/1494] drm/radeon/ttm: move to driver binding/destroy functions. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do agp decision in the driver, instead of special binding funcs v2: use container_of, drop some {}. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-6-airlied@gmail.com --- drivers/gpu/drm/radeon/radeon.h | 7 +- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- drivers/gpu/drm/radeon/radeon_gem.c | 6 +- drivers/gpu/drm/radeon/radeon_object.c | 2 +- drivers/gpu/drm/radeon/radeon_prime.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 92 +++++++++++++++++++------- drivers/gpu/drm/radeon/radeon_vm.c | 2 +- 7 files changed, 80 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index cc4f58d165896..df6f0b49836b7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2815,10 +2815,11 @@ extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enabl extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); -extern int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, +extern int radeon_ttm_tt_set_userptr(struct radeon_device *rdev, + struct ttm_tt *ttm, uint64_t addr, uint32_t flags); -extern bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm); -extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm); +extern bool radeon_ttm_tt_has_userptr(struct radeon_device *rdev, struct ttm_tt *ttm); +extern bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, struct ttm_tt *ttm); extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 33ae1b8832689..21ce2f9502c09 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -160,7 +160,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) p->relocs[i].allowed_domains = domain; } - if (radeon_ttm_tt_has_userptr(p->relocs[i].robj->tbo.ttm)) { + if (radeon_ttm_tt_has_userptr(p->rdev, p->relocs[i].robj->tbo.ttm)) { uint32_t domain = p->relocs[i].preferred_domains; if (!(domain & RADEON_GEM_DOMAIN_GTT)) { DRM_ERROR("Only RADEON_GEM_DOMAIN_GTT is " diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 7f5dfe04789ea..e5c4271e64ede 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -331,7 +331,7 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data, goto handle_lockup; bo = gem_to_radeon_bo(gobj); - r = radeon_ttm_tt_set_userptr(bo->tbo.ttm, args->addr, args->flags); + r = radeon_ttm_tt_set_userptr(rdev, bo->tbo.ttm, args->addr, args->flags); if (r) goto release_object; @@ -420,7 +420,7 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, return -ENOENT; } robj = gem_to_radeon_bo(gobj); - if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) { + if (radeon_ttm_tt_has_userptr(robj->rdev, robj->tbo.ttm)) { drm_gem_object_put(gobj); return -EPERM; } @@ -721,7 +721,7 @@ int radeon_gem_op_ioctl(struct drm_device *dev, void *data, robj = gem_to_radeon_bo(gobj); r = -EPERM; - if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) + if (radeon_ttm_tt_has_userptr(robj->rdev, robj->tbo.ttm)) goto out; r = radeon_bo_reserve(robj, false); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bb7582afd803e..3fcd15d21ddcc 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -331,7 +331,7 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, struct ttm_operation_ctx ctx = { false, false }; int r, i; - if (radeon_ttm_tt_has_userptr(bo->tbo.ttm)) + if (radeon_ttm_tt_has_userptr(bo->rdev, bo->tbo.ttm)) return -EPERM; if (bo->pin_count) { diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index b906e8fbd5f3a..d6d9c8b46ab46 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -121,7 +121,7 @@ struct dma_buf *radeon_gem_prime_export(struct drm_gem_object *gobj, int flags) { struct radeon_bo *bo = gem_to_radeon_bo(gobj); - if (radeon_ttm_tt_has_userptr(bo->tbo.ttm)) + if (radeon_ttm_tt_has_userptr(bo->rdev, bo->tbo.ttm)) return ERR_PTR(-EPERM); return drm_gem_prime_export(gobj, flags); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 155e7b971afa8..3045eece33406 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -141,8 +141,9 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) { struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo); + struct radeon_device *rdev = radeon_get_rdev(bo->bdev); - if (radeon_ttm_tt_has_userptr(bo->ttm)) + if (radeon_ttm_tt_has_userptr(rdev, bo->ttm)) return -EPERM; return drm_vma_node_verify_access(&rbo->tbo.base.vma_node, filp->private_data); @@ -559,12 +560,6 @@ static void radeon_ttm_backend_destroy(struct ttm_bo_device *bdev, struct ttm_tt kfree(gtt); } -static struct ttm_backend_func radeon_backend_func = { - .bind = &radeon_ttm_backend_bind, - .unbind = &radeon_ttm_backend_unbind, - .destroy = &radeon_ttm_backend_destroy, -}; - static struct ttm_tt *radeon_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) { @@ -583,7 +578,6 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_buffer_object *bo, if (gtt == NULL) { return NULL; } - gtt->ttm.ttm.func = &radeon_backend_func; if (ttm_dma_tt_init(>t->ttm, bo, page_flags)) { kfree(gtt); return NULL; @@ -591,19 +585,25 @@ static struct ttm_tt *radeon_ttm_tt_create(struct ttm_buffer_object *bo, return >t->ttm.ttm; } -static struct radeon_ttm_tt *radeon_ttm_tt_to_gtt(struct ttm_tt *ttm) +static struct radeon_ttm_tt *radeon_ttm_tt_to_gtt(struct radeon_device *rdev, + struct ttm_tt *ttm) { - if (!ttm || ttm->func != &radeon_backend_func) +#if IS_ENABLED(CONFIG_AGP) + if (rdev->flags & RADEON_IS_AGP) + return NULL; +#endif + + if (!ttm) return NULL; - return (struct radeon_ttm_tt *)ttm; + return container_of(ttm, struct radeon_ttm_tt, ttm.ttm); } static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { - struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); - struct radeon_device *rdev; + struct radeon_device *rdev = radeon_get_rdev(bdev); + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm); bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (gtt && gtt->userptr) { @@ -623,7 +623,6 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, return 0; } - rdev = radeon_get_rdev(bdev); #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { return ttm_agp_tt_populate(bdev, ttm, ctx); @@ -641,8 +640,8 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - struct radeon_device *rdev; - struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); + struct radeon_device *rdev = radeon_get_rdev(bdev); + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm); bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); if (gtt && gtt->userptr) { @@ -654,7 +653,6 @@ static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt * if (slave) return; - rdev = radeon_get_rdev(bdev); #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { ttm_agp_tt_unpopulate(bdev, ttm); @@ -672,10 +670,11 @@ static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt * ttm_unmap_and_unpopulate_pages(rdev->dev, >t->ttm); } -int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, +int radeon_ttm_tt_set_userptr(struct radeon_device *rdev, + struct ttm_tt *ttm, uint64_t addr, uint32_t flags) { - struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm); if (gtt == NULL) return -EINVAL; @@ -686,9 +685,52 @@ int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, return 0; } -bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm) +static int radeon_ttm_tt_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_resource *bo_mem) +{ + struct radeon_device *rdev = radeon_get_rdev(bdev); + +#if IS_ENABLED(CONFIG_AGP) + if (rdev->flags & RADEON_IS_AGP) + return ttm_agp_bind(bdev, ttm, bo_mem); +#endif + + return radeon_ttm_backend_bind(bdev, ttm, bo_mem); +} + +static void radeon_ttm_tt_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) +{ +#if IS_ENABLED(CONFIG_AGP) + struct radeon_device *rdev = radeon_get_rdev(bdev); + + if (rdev->flags & RADEON_IS_AGP) { + ttm_agp_unbind(bdev, ttm); + return; + } +#endif + radeon_ttm_backend_unbind(bdev, ttm); +} + +static void radeon_ttm_tt_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) +{ +#if IS_ENABLED(CONFIG_AGP) + struct radeon_device *rdev = radeon_get_rdev(bdev); + + if (rdev->flags & RADEON_IS_AGP) { + ttm_agp_destroy(bdev, ttm); + return; + } +#endif + radeon_ttm_backend_destroy(bdev, ttm); +} + +bool radeon_ttm_tt_has_userptr(struct radeon_device *rdev, + struct ttm_tt *ttm) { - struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm); if (gtt == NULL) return false; @@ -696,9 +738,10 @@ bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm) return !!gtt->userptr; } -bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm) +bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, + struct ttm_tt *ttm) { - struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(ttm); + struct radeon_ttm_tt *gtt = radeon_ttm_tt_to_gtt(rdev, ttm); if (gtt == NULL) return false; @@ -710,6 +753,9 @@ static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_create = &radeon_ttm_tt_create, .ttm_tt_populate = &radeon_ttm_tt_populate, .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, + .ttm_tt_bind = &radeon_ttm_tt_bind, + .ttm_tt_unbind = &radeon_ttm_tt_unbind, + .ttm_tt_destroy = &radeon_ttm_tt_destroy, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move, diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 71e2c3785ab9d..ebad27c91a0d2 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -942,7 +942,7 @@ int radeon_vm_bo_update(struct radeon_device *rdev, bo_va->flags &= ~RADEON_VM_PAGE_VALID; bo_va->flags &= ~RADEON_VM_PAGE_SYSTEM; bo_va->flags &= ~RADEON_VM_PAGE_SNOOPED; - if (bo_va->bo && radeon_ttm_tt_is_readonly(bo_va->bo->tbo.ttm)) + if (bo_va->bo && radeon_ttm_tt_is_readonly(rdev, bo_va->bo->tbo.ttm)) bo_va->flags &= ~RADEON_VM_PAGE_WRITEABLE; if (mem) { -- GitLab From 8635784a8733e307d18ad3422c897432db93ead0 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:23 +1000 Subject: [PATCH 0971/1494] drm/nouveau/ttm: use driver bind/unbind/destroy functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-7-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 44 ++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_sgdma.c | 54 ++++++------------------- drivers/gpu/drm/nouveau/nouveau_ttm.h | 3 ++ 3 files changed, 59 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 2c230e0b34dac..2825ffae76ec9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -668,6 +668,33 @@ nouveau_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) return nouveau_sgdma_create_ttm(bo, page_flags); } +static int +nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, + struct ttm_resource *reg) +{ +#if IS_ENABLED(CONFIG_AGP) + struct nouveau_drm *drm = nouveau_bdev(bdev); + + if (drm->agp.bridge) + return ttm_agp_bind(bdev, ttm, reg); +#endif + return nouveau_sgdma_bind(bdev, ttm, reg); +} + +static void +nouveau_ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) +{ +#if IS_ENABLED(CONFIG_AGP) + struct nouveau_drm *drm = nouveau_bdev(bdev); + + if (drm->agp.bridge) { + ttm_agp_unbind(bdev, ttm); + return; + } +#endif + nouveau_sgdma_unbind(bdev, ttm); +} + static void nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) { @@ -1284,6 +1311,20 @@ nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev, ttm_unmap_and_unpopulate_pages(dev, ttm_dma); } +static void +nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) +{ +#if IS_ENABLED(CONFIG_AGP) + struct nouveau_drm *drm = nouveau_bdev(bdev); + if (drm->agp.bridge) { + ttm_agp_destroy(bdev, ttm); + return; + } +#endif + nouveau_sgdma_destroy(bdev, ttm); +} + void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive) { @@ -1299,6 +1340,9 @@ struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = &nouveau_ttm_tt_create, .ttm_tt_populate = &nouveau_ttm_tt_populate, .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate, + .ttm_tt_bind = &nouveau_ttm_tt_bind, + .ttm_tt_unbind = &nouveau_ttm_tt_unbind, + .ttm_tt_destroy = &nouveau_ttm_tt_destroy, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = nouveau_bo_evict_flags, .move_notify = nouveau_bo_move_ntfy, diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 6000c650b1058..05e542254e1f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -14,7 +14,7 @@ struct nouveau_sgdma_be { struct nouveau_mem *mem; }; -static void +void nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; @@ -25,10 +25,11 @@ nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) } } -static int -nv04_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) +int +nouveau_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; + struct nouveau_drm *drm = nouveau_bdev(bdev); struct nouveau_mem *mem = nouveau_mem(reg); int ret; @@ -36,65 +37,34 @@ nv04_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resou if (ret) return ret; - ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]); - if (ret) { - nouveau_mem_fini(mem); - return ret; + if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { + ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]); + if (ret) { + nouveau_mem_fini(mem); + return ret; + } } nvbe->mem = mem; return 0; } -static void -nv04_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) +void +nouveau_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; nouveau_mem_fini(nvbe->mem); } -static struct ttm_backend_func nv04_sgdma_backend = { - .bind = nv04_sgdma_bind, - .unbind = nv04_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - -static int -nv50_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct nouveau_mem *mem = nouveau_mem(reg); - int ret; - - ret = nouveau_mem_host(reg, &nvbe->ttm); - if (ret) - return ret; - - nvbe->mem = mem; - return 0; -} - -static struct ttm_backend_func nv50_sgdma_backend = { - .bind = nv50_sgdma_bind, - .unbind = nv04_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - struct ttm_tt * nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags) { - struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_sgdma_be *nvbe; nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); if (!nvbe) return NULL; - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) - nvbe->ttm.ttm.func = &nv04_sgdma_backend; - else - nvbe->ttm.ttm.func = &nv50_sgdma_backend; - if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) { kfree(nvbe); return NULL; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.h b/drivers/gpu/drm/nouveau/nouveau_ttm.h index eaf25461cd917..69552049bb96d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.h +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.h @@ -22,4 +22,7 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); int nouveau_ttm_global_init(struct nouveau_drm *); void nouveau_ttm_global_release(struct nouveau_drm *); +int nouveau_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg); +void nouveau_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm); +void nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm); #endif -- GitLab From debf8ab9f8a17f86d99f03f0886f38adcacfc209 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:24 +1000 Subject: [PATCH 0972/1494] drm/vmwgfx: move to driver binding functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-8-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index fdd2a5985616c..9d62e57fcb8de 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -668,12 +668,6 @@ static void vmw_ttm_unpopulate(struct ttm_bo_device *bdev, ttm_pool_unpopulate(ttm); } -static struct ttm_backend_func vmw_ttm_func = { - .bind = vmw_ttm_bind, - .unbind = vmw_ttm_unbind, - .destroy = vmw_ttm_destroy, -}; - static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) { @@ -684,7 +678,6 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, if (!vmw_be) return NULL; - vmw_be->dma_ttm.ttm.func = &vmw_ttm_func; vmw_be->dev_priv = container_of(bo->bdev, struct vmw_private, bdev); vmw_be->mob = NULL; @@ -770,6 +763,9 @@ struct ttm_bo_driver vmw_bo_driver = { .ttm_tt_create = &vmw_ttm_tt_create, .ttm_tt_populate = &vmw_ttm_populate, .ttm_tt_unpopulate = &vmw_ttm_unpopulate, + .ttm_tt_bind = &vmw_ttm_bind, + .ttm_tt_unbind = &vmw_ttm_unbind, + .ttm_tt_destroy = &vmw_ttm_destroy, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = NULL, -- GitLab From 5d26eba988296a786442824297c7fc66a4f03ff9 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:25 +1000 Subject: [PATCH 0973/1494] drm/amdgpu/ttm: move to driver backend binding funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-9-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5f7a8e23ed9d4..4ffbe4f666081 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1256,12 +1256,6 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, kfree(gtt); } -static struct ttm_backend_func amdgpu_backend_func = { - .bind = &amdgpu_ttm_backend_bind, - .unbind = &amdgpu_ttm_backend_unbind, - .destroy = &amdgpu_ttm_backend_destroy, -}; - /** * amdgpu_ttm_tt_create - Create a ttm_tt object for a given BO * @@ -1278,7 +1272,6 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, if (gtt == NULL) { return NULL; } - gtt->ttm.ttm.func = &amdgpu_backend_func; gtt->gobj = &bo->base; /* allocate space for the uninitialized page entries */ @@ -1680,6 +1673,9 @@ static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_create = &amdgpu_ttm_tt_create, .ttm_tt_populate = &amdgpu_ttm_tt_populate, .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, + .ttm_tt_bind = &amdgpu_ttm_backend_bind, + .ttm_tt_unbind = &amdgpu_ttm_backend_unbind, + .ttm_tt_destroy = &amdgpu_ttm_backend_destroy, .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, -- GitLab From 84693830aade229cfec88a8bd0a4374ae1103afd Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:26 +1000 Subject: [PATCH 0974/1494] drm/gem_vram/ttm: move to driver backend destroy function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Christian König <christian.koenig@amd.com> Acked-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-10-airlied@gmail.com --- drivers/gpu/drm/drm_gem_vram_helper.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 6a7e0788d8f04..07447abb41341 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -967,16 +967,12 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { * TTM TT */ -static void backend_func_destroy(struct ttm_bo_device *bdev, struct ttm_tt *tt) +static void bo_driver_ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *tt) { ttm_tt_fini(tt); kfree(tt); } -static struct ttm_backend_func backend_func = { - .destroy = backend_func_destroy -}; - /* * TTM BO device */ @@ -991,8 +987,6 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, if (!tt) return NULL; - tt->func = &backend_func; - ret = ttm_tt_init(tt, bo, page_flags); if (ret < 0) goto err_ttm_tt_init; @@ -1054,6 +1048,7 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, static struct ttm_bo_driver bo_driver = { .ttm_tt_create = bo_driver_ttm_tt_create, + .ttm_tt_destroy = bo_driver_ttm_tt_destroy, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bo_driver_evict_flags, .move_notify = bo_driver_move_notify, -- GitLab From 0e59e772e3bdc422d4e888db006778b20af74ae8 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:27 +1000 Subject: [PATCH 0975/1494] drm/ttm/agp: drop back end bindings from agp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These aren't used anymore. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-11-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_agp_backend.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index fbf98cd1a3e58..8072fb7c5bc84 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -112,12 +112,6 @@ void ttm_agp_destroy(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_agp_destroy); -static struct ttm_backend_func ttm_agp_func = { - .bind = ttm_agp_bind, - .unbind = ttm_agp_unbind, - .destroy = ttm_agp_destroy, -}; - struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, struct agp_bridge_data *bridge, uint32_t page_flags) @@ -130,7 +124,6 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, agp_be->mem = NULL; agp_be->bridge = bridge; - agp_be->ttm.func = &ttm_agp_func; if (ttm_tt_init(&agp_be->ttm, bo, page_flags)) { kfree(agp_be); -- GitLab From 434825546e458325d8bdd3be08390d8cc214c64f Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:28 +1000 Subject: [PATCH 0976/1494] drm/ttm: get rid of agp specific populate/unpopulate paths. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-12-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 ++-- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++-- drivers/gpu/drm/ttm/ttm_agp_backend.c | 17 ----------------- include/drm/ttm/ttm_tt.h | 2 -- 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 2825ffae76ec9..8f5b5322589db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1267,7 +1267,7 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { - return ttm_agp_tt_populate(bdev, ttm, ctx); + return ttm_pool_populate(ttm, ctx); } #endif @@ -1296,7 +1296,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { - ttm_agp_tt_unpopulate(bdev, ttm); + ttm_pool_unpopulate(ttm); return; } #endif diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 3045eece33406..b2e58af3bd67d 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -625,7 +625,7 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { - return ttm_agp_tt_populate(bdev, ttm, ctx); + return ttm_pool_populate(ttm, ctx); } #endif @@ -655,7 +655,7 @@ static void radeon_ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt * #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) { - ttm_agp_tt_unpopulate(bdev, ttm); + ttm_pool_unpopulate(ttm); return; } #endif diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 8072fb7c5bc84..3d0a5e9f4c5f3 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -133,20 +133,3 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, return &agp_be->ttm; } EXPORT_SYMBOL(ttm_agp_tt_create); - -int ttm_agp_tt_populate(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) -{ - if (ttm->state != tt_unpopulated) - return 0; - - return ttm_pool_populate(ttm, ctx); -} -EXPORT_SYMBOL(ttm_agp_tt_populate); - -void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, - struct ttm_tt *ttm) -{ - ttm_pool_unpopulate(ttm); -} -EXPORT_SYMBOL(ttm_agp_tt_unpopulate); diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 5a34f16408655..591d4927d501c 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -264,8 +264,6 @@ void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, struct agp_bridge_data *bridge, uint32_t page_flags); -int ttm_agp_tt_populate(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx); -void ttm_agp_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); int ttm_agp_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); void ttm_agp_unbind(struct ttm_bo_device *bdev, -- GitLab From 48efa57e4f1b5c9ecb240f58f790d9872533f953 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:29 +1000 Subject: [PATCH 0977/1494] drm/ttm/agp: remove bdev from agp helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the agp bind/unbind/destroy are now getting called from drivers rather than via the func table, drop the bdev parameter. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-13-airlied@gmail.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +++--- drivers/gpu/drm/radeon/radeon_ttm.c | 6 +++--- drivers/gpu/drm/ttm/ttm_agp_backend.c | 11 ++++------- include/drm/ttm/ttm_tt.h | 9 +++------ 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 8f5b5322589db..a9ad27d86a3cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -676,7 +676,7 @@ nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct nouveau_drm *drm = nouveau_bdev(bdev); if (drm->agp.bridge) - return ttm_agp_bind(bdev, ttm, reg); + return ttm_agp_bind(ttm, reg); #endif return nouveau_sgdma_bind(bdev, ttm, reg); } @@ -688,7 +688,7 @@ nouveau_ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) struct nouveau_drm *drm = nouveau_bdev(bdev); if (drm->agp.bridge) { - ttm_agp_unbind(bdev, ttm); + ttm_agp_unbind(ttm); return; } #endif @@ -1318,7 +1318,7 @@ nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) struct nouveau_drm *drm = nouveau_bdev(bdev); if (drm->agp.bridge) { - ttm_agp_destroy(bdev, ttm); + ttm_agp_destroy(ttm); return; } #endif diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b2e58af3bd67d..0612d3b311ad3 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -693,7 +693,7 @@ static int radeon_ttm_tt_bind(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) - return ttm_agp_bind(bdev, ttm, bo_mem); + return ttm_agp_bind(ttm, bo_mem); #endif return radeon_ttm_backend_bind(bdev, ttm, bo_mem); @@ -706,7 +706,7 @@ static void radeon_ttm_tt_unbind(struct ttm_bo_device *bdev, struct radeon_device *rdev = radeon_get_rdev(bdev); if (rdev->flags & RADEON_IS_AGP) { - ttm_agp_unbind(bdev, ttm); + ttm_agp_unbind(ttm); return; } #endif @@ -720,7 +720,7 @@ static void radeon_ttm_tt_destroy(struct ttm_bo_device *bdev, struct radeon_device *rdev = radeon_get_rdev(bdev); if (rdev->flags & RADEON_IS_AGP) { - ttm_agp_destroy(bdev, ttm); + ttm_agp_destroy(ttm); return; } #endif diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 3d0a5e9f4c5f3..7b36fdaab7667 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -48,8 +48,7 @@ struct ttm_agp_backend { struct agp_bridge_data *bridge; }; -int ttm_agp_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem) +int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); struct page *dummy_read_page = ttm_bo_glob.dummy_read_page; @@ -84,8 +83,7 @@ int ttm_agp_bind(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_agp_bind); -void ttm_agp_unbind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm) +void ttm_agp_unbind(struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); @@ -100,13 +98,12 @@ void ttm_agp_unbind(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_agp_unbind); -void ttm_agp_destroy(struct ttm_bo_device *bdev, - struct ttm_tt *ttm) +void ttm_agp_destroy(struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); if (agp_be->mem) - ttm_agp_unbind(bdev, ttm); + ttm_agp_unbind(ttm); ttm_tt_fini(ttm); kfree(agp_be); } diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 591d4927d501c..bdc8aadf3246b 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -264,12 +264,9 @@ void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm); struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, struct agp_bridge_data *bridge, uint32_t page_flags); -int ttm_agp_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem); -void ttm_agp_unbind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm); -void ttm_agp_destroy(struct ttm_bo_device *bdev, - struct ttm_tt *ttm); +int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem); +void ttm_agp_unbind(struct ttm_tt *ttm); +void ttm_agp_destroy(struct ttm_tt *ttm); #endif #endif -- GitLab From 04e89ff364dec3dc261243c2f0780635448bc466 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 8 Sep 2020 06:46:30 +1000 Subject: [PATCH 0978/1494] drm/ttm: drop the tt backend function paths. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are now driver side. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907204630.1406528-14-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_tt.c | 15 +++----------- include/drm/ttm/ttm_tt.h | 39 ------------------------------------ 2 files changed, 3 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 73c97dcfa512e..67aa7fe39432d 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -222,10 +222,7 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) fput(ttm->swap_storage); ttm->swap_storage = NULL; - if (bdev->driver->ttm_tt_destroy) - bdev->driver->ttm_tt_destroy(bdev, ttm); - else - ttm->func->destroy(bdev, ttm); + bdev->driver->ttm_tt_destroy(bdev, ttm); } static void ttm_tt_init_fields(struct ttm_tt *ttm, @@ -313,10 +310,7 @@ EXPORT_SYMBOL(ttm_dma_tt_fini); void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { if (ttm->state == tt_bound) { - if (bdev->driver->ttm_tt_unbind) - bdev->driver->ttm_tt_unbind(bdev, ttm); - else - ttm->func->unbind(bdev, ttm); + bdev->driver->ttm_tt_unbind(bdev, ttm); ttm->state = tt_unbound; } } @@ -337,10 +331,7 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, if (ret) return ret; - if (bdev->driver->ttm_tt_bind) - ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem); - else - ret = ttm->func->bind(bdev, ttm, bo_mem); + ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem); if (unlikely(ret != 0)) return ret; diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index bdc8aadf3246b..146544ba1c100 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -48,47 +48,9 @@ enum ttm_caching_state { tt_cached }; -struct ttm_backend_func { - /** - * struct ttm_backend_func member bind - * - * @ttm: Pointer to a struct ttm_tt. - * @bo_mem: Pointer to a struct ttm_resource describing the - * memory type and location for binding. - * - * Bind the backend pages into the aperture in the location - * indicated by @bo_mem. This function should be able to handle - * differences between aperture and system page sizes. - */ - int (*bind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); - - /** - * struct ttm_backend_func member unbind - * - * @ttm: Pointer to a struct ttm_tt. - * - * Unbind previously bound backend pages. This function should be - * able to handle differences between aperture and system page sizes. - */ - void (*unbind) (struct ttm_bo_device *bdev, struct ttm_tt *ttm); - - /** - * struct ttm_backend_func member destroy - * - * @ttm: Pointer to a struct ttm_tt. - * - * Destroy the backend. This will be call back from ttm_tt_destroy so - * don't call ttm_tt_destroy from the callback or infinite loop. - */ - void (*destroy) (struct ttm_bo_device *bdev, struct ttm_tt *ttm); -}; - /** * struct ttm_tt * - * @func: Pointer to a struct ttm_backend_func that describes - * the backend methods. - * pointer. * @pages: Array of pages backing the data. * @num_pages: Number of pages in the page array. * @bdev: Pointer to the current struct ttm_bo_device. @@ -102,7 +64,6 @@ struct ttm_backend_func { * memory. */ struct ttm_tt { - struct ttm_backend_func *func; struct page **pages; uint32_t page_flags; unsigned long num_pages; -- GitLab From 707d561f77b5e2a6f90c9786bee44ee7a8dedc7e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Mon, 7 Sep 2020 13:24:25 +0200 Subject: [PATCH 0979/1494] drm: allow limiting the scatter list size. Add drm_device argument to drm_prime_pages_to_sg(), so we can call dma_max_mapping_size() to figure the segment size limit and call into __sg_alloc_table_from_pages() with the correct limit. This fixes virtio-gpu with sev. Possibly it'll fix other bugs too given that drm seems to totaly ignore segment size limits so far ... v2: place max_segment in drm driver not gem object. v3: move max_segment next to the other gem fields. v4: just use dma_max_mapping_size(). Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20200907112425.15610-2-kraxel@redhat.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 3 ++- drivers/gpu/drm/drm_gem_shmem_helper.c | 2 +- drivers/gpu/drm/drm_prime.c | 13 ++++++++++--- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 3 ++- drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 2 +- drivers/gpu/drm/msm/msm_gem_prime.c | 2 +- drivers/gpu/drm/nouveau/nouveau_prime.c | 2 +- drivers/gpu/drm/radeon/radeon_prime.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 5 +++-- drivers/gpu/drm/tegra/gem.c | 2 +- drivers/gpu/drm/vgem/vgem_drv.c | 2 +- drivers/gpu/drm/xen/xen_drm_front_gem.c | 3 ++- include/drm/drm_prime.h | 3 ++- 14 files changed, 29 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 519ce4427fced..d7050ab95946c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -302,7 +302,8 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, switch (bo->tbo.mem.mem_type) { case TTM_PL_TT: - sgt = drm_prime_pages_to_sg(bo->tbo.ttm->pages, + sgt = drm_prime_pages_to_sg(obj->dev, + bo->tbo.ttm->pages, bo->tbo.num_pages); if (IS_ERR(sgt)) return sgt; diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 4b7cfbac4daae..0a952f27c1846 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -656,7 +656,7 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_object *obj) WARN_ON(shmem->base.import_attach); - return drm_prime_pages_to_sg(shmem->pages, obj->size >> PAGE_SHIFT); + return drm_prime_pages_to_sg(obj->dev, shmem->pages, obj->size >> PAGE_SHIFT); } EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 1693aa7c14b5f..8a6a3c99b7d8a 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -802,9 +802,11 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { * * This is useful for implementing &drm_gem_object_funcs.get_sg_table. */ -struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages) +struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev, + struct page **pages, unsigned int nr_pages) { struct sg_table *sg = NULL; + size_t max_segment = 0; int ret; sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); @@ -813,8 +815,13 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_page goto out; } - ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0, - nr_pages << PAGE_SHIFT, GFP_KERNEL); + if (dev) + max_segment = dma_max_mapping_size(dev->dev); + if (max_segment == 0 || max_segment > SCATTERLIST_MAX_SEGMENT) + max_segment = SCATTERLIST_MAX_SEGMENT; + ret = __sg_alloc_table_from_pages(sg, pages, nr_pages, 0, + nr_pages << PAGE_SHIFT, + max_segment, GFP_KERNEL); if (ret) goto out; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index f06e19e7be04a..ea19f1d272756 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -103,7 +103,8 @@ struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *etnaviv_obj) int npages = etnaviv_obj->base.size >> PAGE_SHIFT; struct sg_table *sgt; - sgt = drm_prime_pages_to_sg(etnaviv_obj->pages, npages); + sgt = drm_prime_pages_to_sg(etnaviv_obj->base.dev, + etnaviv_obj->pages, npages); if (IS_ERR(sgt)) { dev_err(dev->dev, "failed to allocate sgt: %ld\n", PTR_ERR(sgt)); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 6d9e5c3c4dd57..4aa3426a9ba4b 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -19,7 +19,7 @@ struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */ return ERR_PTR(-EINVAL); - return drm_prime_pages_to_sg(etnaviv_obj->pages, npages); + return drm_prime_pages_to_sg(obj->dev, etnaviv_obj->pages, npages); } void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b2f49152b4d4c..b4553caaa196b 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -126,7 +126,7 @@ static struct page **get_pages(struct drm_gem_object *obj) msm_obj->pages = p; - msm_obj->sgt = drm_prime_pages_to_sg(p, npages); + msm_obj->sgt = drm_prime_pages_to_sg(obj->dev, p, npages); if (IS_ERR(msm_obj->sgt)) { void *ptr = ERR_CAST(msm_obj->sgt); diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index d7c8948427fe0..515ef80816a0d 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -19,7 +19,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj) if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */ return NULL; - return drm_prime_pages_to_sg(msm_obj->pages, npages); + return drm_prime_pages_to_sg(obj->dev, msm_obj->pages, npages); } void *msm_gem_prime_vmap(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index bae6a3eccee0b..7766b810653f5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -32,7 +32,7 @@ struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj) struct nouveau_bo *nvbo = nouveau_gem_object(obj); int npages = nvbo->bo.num_pages; - return drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages); + return drm_prime_pages_to_sg(obj->dev, nvbo->bo.ttm->pages, npages); } void *nouveau_gem_prime_vmap(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index d6d9c8b46ab46..b9de0e51c0be9 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -36,7 +36,7 @@ struct sg_table *radeon_gem_prime_get_sg_table(struct drm_gem_object *obj) struct radeon_bo *bo = gem_to_radeon_bo(obj); int npages = bo->tbo.num_pages; - return drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages); + return drm_prime_pages_to_sg(obj->dev, bo->tbo.ttm->pages, npages); } void *radeon_gem_prime_vmap(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index b9275ba7c5a53..0055d86576f79 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -85,7 +85,8 @@ static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj) rk_obj->num_pages = rk_obj->base.size >> PAGE_SHIFT; - rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->pages, rk_obj->num_pages); + rk_obj->sgt = drm_prime_pages_to_sg(rk_obj->base.dev, + rk_obj->pages, rk_obj->num_pages); if (IS_ERR(rk_obj->sgt)) { ret = PTR_ERR(rk_obj->sgt); goto err_put_pages; @@ -442,7 +443,7 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj) int ret; if (rk_obj->pages) - return drm_prime_pages_to_sg(rk_obj->pages, rk_obj->num_pages); + return drm_prime_pages_to_sg(obj->dev, rk_obj->pages, rk_obj->num_pages); sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 723df142a9818..47e2935b8c681 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -284,7 +284,7 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) bo->num_pages = bo->gem.size >> PAGE_SHIFT; - bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); + bo->sgt = drm_prime_pages_to_sg(bo->gem.dev, bo->pages, bo->num_pages); if (IS_ERR(bo->sgt)) { err = PTR_ERR(bo->sgt); goto put_pages; diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 313339bbff901..15dd41e67de3b 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -321,7 +321,7 @@ static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj) { struct drm_vgem_gem_object *bo = to_vgem_bo(obj); - return drm_prime_pages_to_sg(bo->pages, bo->base.size >> PAGE_SHIFT); + return drm_prime_pages_to_sg(obj->dev, bo->pages, bo->base.size >> PAGE_SHIFT); } static struct drm_gem_object* vgem_prime_import(struct drm_device *dev, diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index 39ff95b75357d..aed7510e27108 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -179,7 +179,8 @@ struct sg_table *xen_drm_front_gem_get_sg_table(struct drm_gem_object *gem_obj) if (!xen_obj->pages) return ERR_PTR(-ENOMEM); - return drm_prime_pages_to_sg(xen_obj->pages, xen_obj->num_pages); + return drm_prime_pages_to_sg(gem_obj->dev, + xen_obj->pages, xen_obj->num_pages); } struct drm_gem_object * diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h index 9af7422b44cf0..bf141e74a1c22 100644 --- a/include/drm/drm_prime.h +++ b/include/drm/drm_prime.h @@ -88,7 +88,8 @@ void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr); int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma); -struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages); +struct sg_table *drm_prime_pages_to_sg(struct drm_device *dev, + struct page **pages, unsigned int nr_pages); struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj, int flags); -- GitLab From e219688fc5c3d0d9136f8d29d7e0498388f01440 Mon Sep 17 00:00:00 2001 From: Doug Horn <doughorn@google.com> Date: Wed, 2 Sep 2020 14:08:25 -0700 Subject: [PATCH 0980/1494] Fix use after free in get_capset_info callback. If a response to virtio_gpu_cmd_get_capset_info takes longer than five seconds to return, the callback will access freed kernel memory in vg->capsets. Signed-off-by: Doug Horn <doughorn@google.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200902210847.2689-2-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 ++ drivers/gpu/drm/virtio/virtgpu_vq.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 75d0dc2f6d285..5ba389e0a02fb 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -80,8 +80,10 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev, vgdev->capsets[i].id > 0, 5 * HZ); if (ret == 0) { DRM_ERROR("timed out waiting for cap set %d\n", i); + spin_lock(&vgdev->display_info_lock); kfree(vgdev->capsets); vgdev->capsets = NULL; + spin_unlock(&vgdev->display_info_lock); return; } DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n", diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index c93c2db35aaf3..7436705ba5a22 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -684,9 +684,13 @@ static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev, int i = le32_to_cpu(cmd->capset_index); spin_lock(&vgdev->display_info_lock); - vgdev->capsets[i].id = le32_to_cpu(resp->capset_id); - vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version); - vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size); + if (vgdev->capsets) { + vgdev->capsets[i].id = le32_to_cpu(resp->capset_id); + vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version); + vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size); + } else { + DRM_ERROR("invalid capset memory."); + } spin_unlock(&vgdev->display_info_lock); wake_up(&vgdev->resp_wq); } -- GitLab From 1fb97413a3f754f28e24a136a49107e81e12f3fd Mon Sep 17 00:00:00 2001 From: Gurchetan Singh <gurchetansingh@chromium.org> Date: Wed, 2 Sep 2020 14:08:26 -0700 Subject: [PATCH 0981/1494] drm/virtio: fix uninitialized variable smatch reported this with the blob series: drivers/gpu/drm/virtio/virtgpu_kms.c:227 virtio_gpu_init() error: uninitialized symbol 'ret'. Signed-off-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200902210847.2689-3-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 5ba389e0a02fb..06af537b0091d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -105,7 +105,7 @@ int virtio_gpu_init(struct drm_device *dev) /* this will expand later */ struct virtqueue *vqs[2]; u32 num_scanouts, num_capsets; - int ret; + int ret = 0; if (!virtio_has_feature(dev_to_virtio(dev->dev), VIRTIO_F_VERSION_1)) return -ENODEV; -- GitLab From deb2464e4c6dca2c933a53e2cb8c78a75ad5131c Mon Sep 17 00:00:00 2001 From: Gurchetan Singh <gurchetansingh@chromium.org> Date: Wed, 2 Sep 2020 14:08:27 -0700 Subject: [PATCH 0982/1494] drm/virtio: report uuid in debugfs In keeping with other features, report this in the debugfs. Signed-off-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200902210847.2689-4-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c index 3221520f61f0c..d5b0c543bd6d7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c +++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c @@ -48,6 +48,7 @@ static int virtio_gpu_features(struct seq_file *m, void *data) virtio_add_bool(m, "virgl", vgdev->has_virgl_3d); virtio_add_bool(m, "edid", vgdev->has_edid); virtio_add_bool(m, "indirect", vgdev->has_indirect); + virtio_add_bool(m, "resource uuid", vgdev->has_resource_assign_uuid); virtio_add_int(m, "cap sets", vgdev->num_capsets); virtio_add_int(m, "scanouts", vgdev->num_scanouts); return 0; -- GitLab From bbd9caa02c70e4719f82f205d38c916f53ae8408 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Mon, 7 Sep 2020 05:31:29 -0700 Subject: [PATCH 0983/1494] gpu/drm: cleanup coding style a bit Remove first assignment to info which is meaningless. Put the width and higth check first. This change is to make the code a bit readable. Signed-off-by: Bernard Zhao <bernard@vivo.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200907123129.27905-1-bernard@vivo.com --- drivers/gpu/drm/drm_framebuffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index df656366a5302..2f5b0c2bb0fe3 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -176,8 +176,7 @@ static int framebuffer_check(struct drm_device *dev, int i; /* check if the format is supported at all */ - info = __drm_format_info(r->pixel_format); - if (!info) { + if (!__drm_format_info(r->pixel_format)) { struct drm_format_name_buf format_name; DRM_DEBUG_KMS("bad framebuffer format %s\n", @@ -186,9 +185,6 @@ static int framebuffer_check(struct drm_device *dev, return -EINVAL; } - /* now let the driver pick its own format info */ - info = drm_get_format_info(dev, r); - if (r->width == 0) { DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); return -EINVAL; @@ -199,6 +195,9 @@ static int framebuffer_check(struct drm_device *dev, return -EINVAL; } + /* now let the driver pick its own format info */ + info = drm_get_format_info(dev, r); + for (i = 0; i < info->num_planes; i++) { unsigned int width = fb_plane_width(r->width, info, i); unsigned int height = fb_plane_height(r->height, info, i); -- GitLab From ce625f45670c90241e06d406cd1b0dbd19ed1044 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Fri, 31 Jul 2020 11:18:29 +0300 Subject: [PATCH 0984/1494] drm/imx: compile imx directory by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the drm/imx/ directory is compiled only if DRM_IMX is set. Adding a new IMX related IP in the same directory would need DRM_IMX to be set, which would bring in also IPUv3 core driver... The current patch would allow adding new IPs in the imx/ directory without needing to set DRM_IMX. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200731081836.3048-2-laurentiu.palcu@oss.nxp.com --- drivers/gpu/drm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 2f31579f91d42..81569009f8848 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_DRM_MSM) += msm/ obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-$(CONFIG_DRM_STM) += stm/ obj-$(CONFIG_DRM_STI) += sti/ -obj-$(CONFIG_DRM_IMX) += imx/ +obj-y += imx/ obj-$(CONFIG_DRM_INGENIC) += ingenic/ obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ obj-$(CONFIG_DRM_MESON) += meson/ -- GitLab From 9021c317b77024fb2642af7e84ad944769ae0949 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Fri, 31 Jul 2020 11:18:30 +0300 Subject: [PATCH 0985/1494] drm/imx: Add initial support for DCSS on iMX8MQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds initial support for iMX8MQ's Display Controller Subsystem (DCSS). Some of its capabilities include: * 4K@60fps; * HDR10; * one graphics and 2 video pipelines; * on-the-fly decompression of compressed video and graphics; The reference manual can be found here: https://www.nxp.com/webapp/Download?colCode=IMX8MDQLQRM The current patch adds only basic functionality: one primary plane for graphics, linear, tiled and super-tiled buffers support (no graphics decompression yet), no HDR10 and no video planes. Video planes support and HDR10 will be added in subsequent patches once per-plane de-gamma/CSC/gamma support is in. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Acked-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200731081836.3048-3-laurentiu.palcu@oss.nxp.com --- drivers/gpu/drm/imx/Kconfig | 2 + drivers/gpu/drm/imx/Makefile | 1 + drivers/gpu/drm/imx/dcss/Kconfig | 9 + drivers/gpu/drm/imx/dcss/Makefile | 6 + drivers/gpu/drm/imx/dcss/dcss-blkctl.c | 70 +++ drivers/gpu/drm/imx/dcss/dcss-crtc.c | 219 +++++++ drivers/gpu/drm/imx/dcss/dcss-ctxld.c | 424 +++++++++++++ drivers/gpu/drm/imx/dcss/dcss-dev.c | 314 ++++++++++ drivers/gpu/drm/imx/dcss/dcss-dev.h | 177 ++++++ drivers/gpu/drm/imx/dcss/dcss-dpr.c | 562 +++++++++++++++++ drivers/gpu/drm/imx/dcss/dcss-drv.c | 138 +++++ drivers/gpu/drm/imx/dcss/dcss-dtg.c | 409 ++++++++++++ drivers/gpu/drm/imx/dcss/dcss-kms.c | 177 ++++++ drivers/gpu/drm/imx/dcss/dcss-kms.h | 43 ++ drivers/gpu/drm/imx/dcss/dcss-plane.c | 405 ++++++++++++ drivers/gpu/drm/imx/dcss/dcss-scaler.c | 826 +++++++++++++++++++++++++ drivers/gpu/drm/imx/dcss/dcss-ss.c | 180 ++++++ 17 files changed, 3962 insertions(+) create mode 100644 drivers/gpu/drm/imx/dcss/Kconfig create mode 100644 drivers/gpu/drm/imx/dcss/Makefile create mode 100644 drivers/gpu/drm/imx/dcss/dcss-blkctl.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-crtc.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-ctxld.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-dev.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-dev.h create mode 100644 drivers/gpu/drm/imx/dcss/dcss-dpr.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-drv.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-dtg.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-kms.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-kms.h create mode 100644 drivers/gpu/drm/imx/dcss/dcss-plane.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-scaler.c create mode 100644 drivers/gpu/drm/imx/dcss/dcss-ss.c diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig index 207bf7409dfba..6231048aa5aaa 100644 --- a/drivers/gpu/drm/imx/Kconfig +++ b/drivers/gpu/drm/imx/Kconfig @@ -39,3 +39,5 @@ config DRM_IMX_HDMI depends on DRM_IMX help Choose this if you want to use HDMI on i.MX6. + +source "drivers/gpu/drm/imx/dcss/Kconfig" diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile index 21cdcc2faabc8..b644deffe948b 100644 --- a/drivers/gpu/drm/imx/Makefile +++ b/drivers/gpu/drm/imx/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o obj-$(CONFIG_DRM_IMX_HDMI) += dw_hdmi-imx.o +obj-$(CONFIG_DRM_IMX_DCSS) += dcss/ diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig new file mode 100644 index 0000000000000..69860de8861f4 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -0,0 +1,9 @@ +config DRM_IMX_DCSS + tristate "i.MX8MQ DCSS" + select IMX_IRQSTEER + select DRM_KMS_CMA_HELPER + select VIDEOMODE_HELPERS + depends on DRM && ARCH_MXC + help + Choose this if you have a NXP i.MX8MQ based system and want to use the + Display Controller Subsystem. This option enables DCSS support. diff --git a/drivers/gpu/drm/imx/dcss/Makefile b/drivers/gpu/drm/imx/dcss/Makefile new file mode 100644 index 0000000000000..8c7c8da427922 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/Makefile @@ -0,0 +1,6 @@ +imx-dcss-objs := dcss-drv.o dcss-dev.o dcss-blkctl.o dcss-ctxld.o dcss-dtg.o \ + dcss-ss.o dcss-dpr.o dcss-scaler.o dcss-kms.o dcss-crtc.o \ + dcss-plane.o + +obj-$(CONFIG_DRM_IMX_DCSS) += imx-dcss.o + diff --git a/drivers/gpu/drm/imx/dcss/dcss-blkctl.c b/drivers/gpu/drm/imx/dcss/dcss-blkctl.c new file mode 100644 index 0000000000000..c9b54bb2692d7 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-blkctl.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/device.h> +#include <linux/of.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_BLKCTL_RESET_CTRL 0x00 +#define B_CLK_RESETN BIT(0) +#define APB_CLK_RESETN BIT(1) +#define P_CLK_RESETN BIT(2) +#define RTR_CLK_RESETN BIT(4) +#define DCSS_BLKCTL_CONTROL0 0x10 +#define HDMI_MIPI_CLK_SEL BIT(0) +#define DISPMIX_REFCLK_SEL_POS 4 +#define DISPMIX_REFCLK_SEL_MASK GENMASK(5, 4) +#define DISPMIX_PIXCLK_SEL BIT(8) +#define HDMI_SRC_SECURE_EN BIT(16) + +struct dcss_blkctl { + struct dcss_dev *dcss; + void __iomem *base_reg; +}; + +void dcss_blkctl_cfg(struct dcss_blkctl *blkctl) +{ + if (blkctl->dcss->hdmi_output) + dcss_writel(0, blkctl->base_reg + DCSS_BLKCTL_CONTROL0); + else + dcss_writel(DISPMIX_PIXCLK_SEL, + blkctl->base_reg + DCSS_BLKCTL_CONTROL0); + + dcss_set(B_CLK_RESETN | APB_CLK_RESETN | P_CLK_RESETN | RTR_CLK_RESETN, + blkctl->base_reg + DCSS_BLKCTL_RESET_CTRL); +} + +int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base) +{ + struct dcss_blkctl *blkctl; + + blkctl = kzalloc(sizeof(*blkctl), GFP_KERNEL); + if (!blkctl) + return -ENOMEM; + + blkctl->base_reg = ioremap(blkctl_base, SZ_4K); + if (!blkctl->base_reg) { + dev_err(dcss->dev, "unable to remap BLK CTRL base\n"); + kfree(blkctl); + return -ENOMEM; + } + + dcss->blkctl = blkctl; + blkctl->dcss = dcss; + + dcss_blkctl_cfg(blkctl); + + return 0; +} + +void dcss_blkctl_exit(struct dcss_blkctl *blkctl) +{ + if (blkctl->base_reg) + iounmap(blkctl->base_reg); + + kfree(blkctl); +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-crtc.c b/drivers/gpu/drm/imx/dcss/dcss-crtc.c new file mode 100644 index 0000000000000..36abff0890b28 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-crtc.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_vblank.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +#include "dcss-dev.h" +#include "dcss-kms.h" + +static int dcss_enable_vblank(struct drm_crtc *crtc) +{ + struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc, + base); + struct dcss_dev *dcss = crtc->dev->dev_private; + + dcss_dtg_vblank_irq_enable(dcss->dtg, true); + + dcss_dtg_ctxld_kick_irq_enable(dcss->dtg, true); + + enable_irq(dcss_crtc->irq); + + return 0; +} + +static void dcss_disable_vblank(struct drm_crtc *crtc) +{ + struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc, + base); + struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; + + disable_irq_nosync(dcss_crtc->irq); + + dcss_dtg_vblank_irq_enable(dcss->dtg, false); + + if (dcss_crtc->disable_ctxld_kick_irq) + dcss_dtg_ctxld_kick_irq_enable(dcss->dtg, false); +} + +static const struct drm_crtc_funcs dcss_crtc_funcs = { + .set_config = drm_atomic_helper_set_config, + .destroy = drm_crtc_cleanup, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = dcss_enable_vblank, + .disable_vblank = dcss_disable_vblank, +}; + +static void dcss_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + drm_crtc_vblank_on(crtc); +} + +static void dcss_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc, + base); + struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; + + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->event) { + WARN_ON(drm_crtc_vblank_get(crtc)); + drm_crtc_arm_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); + + if (dcss_dtg_is_enabled(dcss->dtg)) + dcss_ctxld_enable(dcss->ctxld); +} + +static void dcss_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc, + base); + struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; + struct drm_display_mode *mode = &crtc->state->adjusted_mode; + struct drm_display_mode *old_mode = &old_crtc_state->adjusted_mode; + struct videomode vm; + + drm_display_mode_to_videomode(mode, &vm); + + pm_runtime_get_sync(dcss->dev); + + vm.pixelclock = mode->crtc_clock * 1000; + + dcss_ss_subsam_set(dcss->ss); + dcss_dtg_css_set(dcss->dtg); + + if (!drm_mode_equal(mode, old_mode) || !old_crtc_state->active) { + dcss_dtg_sync_set(dcss->dtg, &vm); + dcss_ss_sync_set(dcss->ss, &vm, + mode->flags & DRM_MODE_FLAG_PHSYNC, + mode->flags & DRM_MODE_FLAG_PVSYNC); + } + + dcss_enable_dtg_and_ss(dcss); + + dcss_ctxld_enable(dcss->ctxld); + + /* Allow CTXLD kick interrupt to be disabled when VBLANK is disabled. */ + dcss_crtc->disable_ctxld_kick_irq = true; +} + +static void dcss_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) +{ + struct dcss_crtc *dcss_crtc = container_of(crtc, struct dcss_crtc, + base); + struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; + struct drm_display_mode *mode = &crtc->state->adjusted_mode; + struct drm_display_mode *old_mode = &old_crtc_state->adjusted_mode; + + drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); + + spin_lock_irq(&crtc->dev->event_lock); + if (crtc->state->event) { + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + } + spin_unlock_irq(&crtc->dev->event_lock); + + dcss_dtg_ctxld_kick_irq_enable(dcss->dtg, true); + + reinit_completion(&dcss->disable_completion); + + dcss_disable_dtg_and_ss(dcss); + + dcss_ctxld_enable(dcss->ctxld); + + if (!drm_mode_equal(mode, old_mode) || !crtc->state->active) + if (!wait_for_completion_timeout(&dcss->disable_completion, + msecs_to_jiffies(100))) + dev_err(dcss->dev, "Shutting off DTG timed out.\n"); + + /* + * Do not shut off CTXLD kick interrupt when shutting VBLANK off. It + * will be needed to commit the last changes, before going to suspend. + */ + dcss_crtc->disable_ctxld_kick_irq = false; + + drm_crtc_vblank_off(crtc); + + pm_runtime_mark_last_busy(dcss->dev); + pm_runtime_put_autosuspend(dcss->dev); +} + +static const struct drm_crtc_helper_funcs dcss_helper_funcs = { + .atomic_begin = dcss_crtc_atomic_begin, + .atomic_flush = dcss_crtc_atomic_flush, + .atomic_enable = dcss_crtc_atomic_enable, + .atomic_disable = dcss_crtc_atomic_disable, +}; + +static irqreturn_t dcss_crtc_irq_handler(int irq, void *dev_id) +{ + struct dcss_crtc *dcss_crtc = dev_id; + struct dcss_dev *dcss = dcss_crtc->base.dev->dev_private; + + if (!dcss_dtg_vblank_irq_valid(dcss->dtg)) + return IRQ_NONE; + + if (dcss_ctxld_is_flushed(dcss->ctxld)) + drm_crtc_handle_vblank(&dcss_crtc->base); + + dcss_dtg_vblank_irq_clear(dcss->dtg); + + return IRQ_HANDLED; +} + +int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm) +{ + struct dcss_dev *dcss = drm->dev_private; + struct platform_device *pdev = to_platform_device(dcss->dev); + int ret; + + crtc->plane[0] = dcss_plane_init(drm, drm_crtc_mask(&crtc->base), + DRM_PLANE_TYPE_PRIMARY, 0); + if (IS_ERR(crtc->plane[0])) + return PTR_ERR(crtc->plane[0]); + + crtc->base.port = dcss->of_port; + + drm_crtc_helper_add(&crtc->base, &dcss_helper_funcs); + ret = drm_crtc_init_with_planes(drm, &crtc->base, &crtc->plane[0]->base, + NULL, &dcss_crtc_funcs, NULL); + if (ret) { + dev_err(dcss->dev, "failed to init crtc\n"); + return ret; + } + + crtc->irq = platform_get_irq_byname(pdev, "vblank"); + if (crtc->irq < 0) + return crtc->irq; + + ret = request_irq(crtc->irq, dcss_crtc_irq_handler, + 0, "dcss_drm", crtc); + if (ret) { + dev_err(dcss->dev, "irq request failed with %d.\n", ret); + return ret; + } + + disable_irq(crtc->irq); + + return 0; +} + +void dcss_crtc_deinit(struct dcss_crtc *crtc, struct drm_device *drm) +{ + free_irq(crtc->irq, crtc); +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-ctxld.c b/drivers/gpu/drm/imx/dcss/dcss-ctxld.c new file mode 100644 index 0000000000000..3a84cb3209c4a --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-ctxld.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_CTXLD_CONTROL_STATUS 0x0 +#define CTXLD_ENABLE BIT(0) +#define ARB_SEL BIT(1) +#define RD_ERR_EN BIT(2) +#define DB_COMP_EN BIT(3) +#define SB_HP_COMP_EN BIT(4) +#define SB_LP_COMP_EN BIT(5) +#define DB_PEND_SB_REC_EN BIT(6) +#define SB_PEND_DISP_ACTIVE_EN BIT(7) +#define AHB_ERR_EN BIT(8) +#define RD_ERR BIT(16) +#define DB_COMP BIT(17) +#define SB_HP_COMP BIT(18) +#define SB_LP_COMP BIT(19) +#define DB_PEND_SB_REC BIT(20) +#define SB_PEND_DISP_ACTIVE BIT(21) +#define AHB_ERR BIT(22) +#define DCSS_CTXLD_DB_BASE_ADDR 0x10 +#define DCSS_CTXLD_DB_COUNT 0x14 +#define DCSS_CTXLD_SB_BASE_ADDR 0x18 +#define DCSS_CTXLD_SB_COUNT 0x1C +#define SB_HP_COUNT_POS 0 +#define SB_HP_COUNT_MASK 0xffff +#define SB_LP_COUNT_POS 16 +#define SB_LP_COUNT_MASK 0xffff0000 +#define DCSS_AHB_ERR_ADDR 0x20 + +#define CTXLD_IRQ_COMPLETION (DB_COMP | SB_HP_COMP | SB_LP_COMP) +#define CTXLD_IRQ_ERROR (RD_ERR | DB_PEND_SB_REC | AHB_ERR) + +/* The following sizes are in context loader entries, 8 bytes each. */ +#define CTXLD_DB_CTX_ENTRIES 1024 /* max 65536 */ +#define CTXLD_SB_LP_CTX_ENTRIES 10240 /* max 65536 */ +#define CTXLD_SB_HP_CTX_ENTRIES 20000 /* max 65536 */ +#define CTXLD_SB_CTX_ENTRIES (CTXLD_SB_LP_CTX_ENTRIES + \ + CTXLD_SB_HP_CTX_ENTRIES) + +/* Sizes, in entries, of the DB, SB_HP and SB_LP context regions. */ +static u16 dcss_ctxld_ctx_size[3] = { + CTXLD_DB_CTX_ENTRIES, + CTXLD_SB_HP_CTX_ENTRIES, + CTXLD_SB_LP_CTX_ENTRIES +}; + +/* this represents an entry in the context loader map */ +struct dcss_ctxld_item { + u32 val; + u32 ofs; +}; + +#define CTX_ITEM_SIZE sizeof(struct dcss_ctxld_item) + +struct dcss_ctxld { + struct device *dev; + void __iomem *ctxld_reg; + int irq; + bool irq_en; + + struct dcss_ctxld_item *db[2]; + struct dcss_ctxld_item *sb_hp[2]; + struct dcss_ctxld_item *sb_lp[2]; + + dma_addr_t db_paddr[2]; + dma_addr_t sb_paddr[2]; + + u16 ctx_size[2][3]; /* holds the sizes of DB, SB_HP and SB_LP ctx */ + u8 current_ctx; + + bool in_use; + bool armed; + + spinlock_t lock; /* protects concurent access to private data */ +}; + +static irqreturn_t dcss_ctxld_irq_handler(int irq, void *data) +{ + struct dcss_ctxld *ctxld = data; + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(ctxld->dev); + u32 irq_status; + + irq_status = dcss_readl(ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS); + + if (irq_status & CTXLD_IRQ_COMPLETION && + !(irq_status & CTXLD_ENABLE) && ctxld->in_use) { + ctxld->in_use = false; + + if (dcss && dcss->disable_callback) + dcss->disable_callback(dcss); + } else if (irq_status & CTXLD_IRQ_ERROR) { + /* + * Except for throwing an error message and clearing the status + * register, there's not much we can do here. + */ + dev_err(ctxld->dev, "ctxld: error encountered: %08x\n", + irq_status); + dev_err(ctxld->dev, "ctxld: db=%d, sb_hp=%d, sb_lp=%d\n", + ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_DB], + ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_SB_HP], + ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_SB_LP]); + } + + dcss_clr(irq_status & (CTXLD_IRQ_ERROR | CTXLD_IRQ_COMPLETION), + ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS); + + return IRQ_HANDLED; +} + +static int dcss_ctxld_irq_config(struct dcss_ctxld *ctxld, + struct platform_device *pdev) +{ + int ret; + + ctxld->irq = platform_get_irq_byname(pdev, "ctxld"); + if (ctxld->irq < 0) + return ctxld->irq; + + ret = request_irq(ctxld->irq, dcss_ctxld_irq_handler, + 0, "dcss_ctxld", ctxld); + if (ret) { + dev_err(ctxld->dev, "ctxld: irq request failed.\n"); + return ret; + } + + ctxld->irq_en = true; + + return 0; +} + +static void dcss_ctxld_hw_cfg(struct dcss_ctxld *ctxld) +{ + dcss_writel(RD_ERR_EN | SB_HP_COMP_EN | + DB_PEND_SB_REC_EN | AHB_ERR_EN | RD_ERR | AHB_ERR, + ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS); +} + +static void dcss_ctxld_free_ctx(struct dcss_ctxld *ctxld) +{ + struct dcss_ctxld_item *ctx; + int i; + + for (i = 0; i < 2; i++) { + if (ctxld->db[i]) { + dma_free_coherent(ctxld->dev, + CTXLD_DB_CTX_ENTRIES * sizeof(*ctx), + ctxld->db[i], ctxld->db_paddr[i]); + ctxld->db[i] = NULL; + ctxld->db_paddr[i] = 0; + } + + if (ctxld->sb_hp[i]) { + dma_free_coherent(ctxld->dev, + CTXLD_SB_CTX_ENTRIES * sizeof(*ctx), + ctxld->sb_hp[i], ctxld->sb_paddr[i]); + ctxld->sb_hp[i] = NULL; + ctxld->sb_paddr[i] = 0; + } + } +} + +static int dcss_ctxld_alloc_ctx(struct dcss_ctxld *ctxld) +{ + struct dcss_ctxld_item *ctx; + int i; + + for (i = 0; i < 2; i++) { + ctx = dma_alloc_coherent(ctxld->dev, + CTXLD_DB_CTX_ENTRIES * sizeof(*ctx), + &ctxld->db_paddr[i], GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctxld->db[i] = ctx; + + ctx = dma_alloc_coherent(ctxld->dev, + CTXLD_SB_CTX_ENTRIES * sizeof(*ctx), + &ctxld->sb_paddr[i], GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctxld->sb_hp[i] = ctx; + ctxld->sb_lp[i] = ctx + CTXLD_SB_HP_CTX_ENTRIES; + } + + return 0; +} + +int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base) +{ + struct dcss_ctxld *ctxld; + int ret; + + ctxld = kzalloc(sizeof(*ctxld), GFP_KERNEL); + if (!ctxld) + return -ENOMEM; + + dcss->ctxld = ctxld; + ctxld->dev = dcss->dev; + + spin_lock_init(&ctxld->lock); + + ret = dcss_ctxld_alloc_ctx(ctxld); + if (ret) { + dev_err(dcss->dev, "ctxld: cannot allocate context memory.\n"); + goto err; + } + + ctxld->ctxld_reg = ioremap(ctxld_base, SZ_4K); + if (!ctxld->ctxld_reg) { + dev_err(dcss->dev, "ctxld: unable to remap ctxld base\n"); + ret = -ENOMEM; + goto err; + } + + ret = dcss_ctxld_irq_config(ctxld, to_platform_device(dcss->dev)); + if (ret) + goto err_irq; + + dcss_ctxld_hw_cfg(ctxld); + + return 0; + +err_irq: + iounmap(ctxld->ctxld_reg); + +err: + dcss_ctxld_free_ctx(ctxld); + kfree(ctxld); + + return ret; +} + +void dcss_ctxld_exit(struct dcss_ctxld *ctxld) +{ + free_irq(ctxld->irq, ctxld); + + if (ctxld->ctxld_reg) + iounmap(ctxld->ctxld_reg); + + dcss_ctxld_free_ctx(ctxld); + kfree(ctxld); +} + +static int dcss_ctxld_enable_locked(struct dcss_ctxld *ctxld) +{ + int curr_ctx = ctxld->current_ctx; + u32 db_base, sb_base, sb_count; + u32 sb_hp_cnt, sb_lp_cnt, db_cnt; + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(ctxld->dev); + + if (!dcss) + return 0; + + dcss_dpr_write_sysctrl(dcss->dpr); + + dcss_scaler_write_sclctrl(dcss->scaler); + + sb_hp_cnt = ctxld->ctx_size[curr_ctx][CTX_SB_HP]; + sb_lp_cnt = ctxld->ctx_size[curr_ctx][CTX_SB_LP]; + db_cnt = ctxld->ctx_size[curr_ctx][CTX_DB]; + + /* make sure SB_LP context area comes after SB_HP */ + if (sb_lp_cnt && + ctxld->sb_lp[curr_ctx] != ctxld->sb_hp[curr_ctx] + sb_hp_cnt) { + struct dcss_ctxld_item *sb_lp_adjusted; + + sb_lp_adjusted = ctxld->sb_hp[curr_ctx] + sb_hp_cnt; + + memcpy(sb_lp_adjusted, ctxld->sb_lp[curr_ctx], + sb_lp_cnt * CTX_ITEM_SIZE); + } + + db_base = db_cnt ? ctxld->db_paddr[curr_ctx] : 0; + + dcss_writel(db_base, ctxld->ctxld_reg + DCSS_CTXLD_DB_BASE_ADDR); + dcss_writel(db_cnt, ctxld->ctxld_reg + DCSS_CTXLD_DB_COUNT); + + if (sb_hp_cnt) + sb_count = ((sb_hp_cnt << SB_HP_COUNT_POS) & SB_HP_COUNT_MASK) | + ((sb_lp_cnt << SB_LP_COUNT_POS) & SB_LP_COUNT_MASK); + else + sb_count = (sb_lp_cnt << SB_HP_COUNT_POS) & SB_HP_COUNT_MASK; + + sb_base = sb_count ? ctxld->sb_paddr[curr_ctx] : 0; + + dcss_writel(sb_base, ctxld->ctxld_reg + DCSS_CTXLD_SB_BASE_ADDR); + dcss_writel(sb_count, ctxld->ctxld_reg + DCSS_CTXLD_SB_COUNT); + + /* enable the context loader */ + dcss_set(CTXLD_ENABLE, ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS); + + ctxld->in_use = true; + + /* + * Toggle the current context to the alternate one so that any updates + * in the modules' settings take place there. + */ + ctxld->current_ctx ^= 1; + + ctxld->ctx_size[ctxld->current_ctx][CTX_DB] = 0; + ctxld->ctx_size[ctxld->current_ctx][CTX_SB_HP] = 0; + ctxld->ctx_size[ctxld->current_ctx][CTX_SB_LP] = 0; + + return 0; +} + +int dcss_ctxld_enable(struct dcss_ctxld *ctxld) +{ + spin_lock_irq(&ctxld->lock); + ctxld->armed = true; + spin_unlock_irq(&ctxld->lock); + + return 0; +} + +void dcss_ctxld_kick(struct dcss_ctxld *ctxld) +{ + unsigned long flags; + + spin_lock_irqsave(&ctxld->lock, flags); + if (ctxld->armed && !ctxld->in_use) { + ctxld->armed = false; + dcss_ctxld_enable_locked(ctxld); + } + spin_unlock_irqrestore(&ctxld->lock, flags); +} + +void dcss_ctxld_write_irqsafe(struct dcss_ctxld *ctxld, u32 ctx_id, u32 val, + u32 reg_ofs) +{ + int curr_ctx = ctxld->current_ctx; + struct dcss_ctxld_item *ctx[] = { + [CTX_DB] = ctxld->db[curr_ctx], + [CTX_SB_HP] = ctxld->sb_hp[curr_ctx], + [CTX_SB_LP] = ctxld->sb_lp[curr_ctx] + }; + int item_idx = ctxld->ctx_size[curr_ctx][ctx_id]; + + if (item_idx + 1 > dcss_ctxld_ctx_size[ctx_id]) { + WARN_ON(1); + return; + } + + ctx[ctx_id][item_idx].val = val; + ctx[ctx_id][item_idx].ofs = reg_ofs; + ctxld->ctx_size[curr_ctx][ctx_id] += 1; +} + +void dcss_ctxld_write(struct dcss_ctxld *ctxld, u32 ctx_id, + u32 val, u32 reg_ofs) +{ + spin_lock_irq(&ctxld->lock); + dcss_ctxld_write_irqsafe(ctxld, ctx_id, val, reg_ofs); + spin_unlock_irq(&ctxld->lock); +} + +bool dcss_ctxld_is_flushed(struct dcss_ctxld *ctxld) +{ + return ctxld->ctx_size[ctxld->current_ctx][CTX_DB] == 0 && + ctxld->ctx_size[ctxld->current_ctx][CTX_SB_HP] == 0 && + ctxld->ctx_size[ctxld->current_ctx][CTX_SB_LP] == 0; +} + +int dcss_ctxld_resume(struct dcss_ctxld *ctxld) +{ + dcss_ctxld_hw_cfg(ctxld); + + if (!ctxld->irq_en) { + enable_irq(ctxld->irq); + ctxld->irq_en = true; + } + + return 0; +} + +int dcss_ctxld_suspend(struct dcss_ctxld *ctxld) +{ + int ret = 0; + unsigned long timeout = jiffies + msecs_to_jiffies(500); + + if (!dcss_ctxld_is_flushed(ctxld)) { + dcss_ctxld_kick(ctxld); + + while (!time_after(jiffies, timeout) && ctxld->in_use) + msleep(20); + + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + } + + spin_lock_irq(&ctxld->lock); + + if (ctxld->irq_en) { + disable_irq_nosync(ctxld->irq); + ctxld->irq_en = false; + } + + /* reset context region and sizes */ + ctxld->current_ctx = 0; + ctxld->ctx_size[0][CTX_DB] = 0; + ctxld->ctx_size[0][CTX_SB_HP] = 0; + ctxld->ctx_size[0][CTX_SB_LP] = 0; + + spin_unlock_irq(&ctxld->lock); + + return ret; +} + +void dcss_ctxld_assert_locked(struct dcss_ctxld *ctxld) +{ + lockdep_assert_held(&ctxld->lock); +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c new file mode 100644 index 0000000000000..83a4840435cfb --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/clk.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> +#include <drm/drm_modeset_helper.h> + +#include "dcss-dev.h" + +static void dcss_clocks_enable(struct dcss_dev *dcss) +{ + clk_prepare_enable(dcss->axi_clk); + clk_prepare_enable(dcss->apb_clk); + clk_prepare_enable(dcss->rtrm_clk); + clk_prepare_enable(dcss->dtrc_clk); + clk_prepare_enable(dcss->pix_clk); +} + +static void dcss_clocks_disable(struct dcss_dev *dcss) +{ + clk_disable_unprepare(dcss->pix_clk); + clk_disable_unprepare(dcss->dtrc_clk); + clk_disable_unprepare(dcss->rtrm_clk); + clk_disable_unprepare(dcss->apb_clk); + clk_disable_unprepare(dcss->axi_clk); +} + +static void dcss_disable_dtg_and_ss_cb(void *data) +{ + struct dcss_dev *dcss = data; + + dcss->disable_callback = NULL; + + dcss_ss_shutoff(dcss->ss); + dcss_dtg_shutoff(dcss->dtg); + + complete(&dcss->disable_completion); +} + +void dcss_disable_dtg_and_ss(struct dcss_dev *dcss) +{ + dcss->disable_callback = dcss_disable_dtg_and_ss_cb; +} + +void dcss_enable_dtg_and_ss(struct dcss_dev *dcss) +{ + if (dcss->disable_callback) + dcss->disable_callback = NULL; + + dcss_dtg_enable(dcss->dtg); + dcss_ss_enable(dcss->ss); +} + +static int dcss_submodules_init(struct dcss_dev *dcss) +{ + int ret = 0; + u32 base_addr = dcss->start_addr; + const struct dcss_type_data *devtype = dcss->devtype; + + dcss_clocks_enable(dcss); + + ret = dcss_blkctl_init(dcss, base_addr + devtype->blkctl_ofs); + if (ret) + return ret; + + ret = dcss_ctxld_init(dcss, base_addr + devtype->ctxld_ofs); + if (ret) + goto ctxld_err; + + ret = dcss_dtg_init(dcss, base_addr + devtype->dtg_ofs); + if (ret) + goto dtg_err; + + ret = dcss_ss_init(dcss, base_addr + devtype->ss_ofs); + if (ret) + goto ss_err; + + ret = dcss_dpr_init(dcss, base_addr + devtype->dpr_ofs); + if (ret) + goto dpr_err; + + ret = dcss_scaler_init(dcss, base_addr + devtype->scaler_ofs); + if (ret) + goto scaler_err; + + dcss_clocks_disable(dcss); + + return 0; + +scaler_err: + dcss_dpr_exit(dcss->dpr); + +dpr_err: + dcss_ss_exit(dcss->ss); + +ss_err: + dcss_dtg_exit(dcss->dtg); + +dtg_err: + dcss_ctxld_exit(dcss->ctxld); + +ctxld_err: + dcss_blkctl_exit(dcss->blkctl); + + dcss_clocks_disable(dcss); + + return ret; +} + +static void dcss_submodules_stop(struct dcss_dev *dcss) +{ + dcss_clocks_enable(dcss); + dcss_scaler_exit(dcss->scaler); + dcss_dpr_exit(dcss->dpr); + dcss_ss_exit(dcss->ss); + dcss_dtg_exit(dcss->dtg); + dcss_ctxld_exit(dcss->ctxld); + dcss_blkctl_exit(dcss->blkctl); + dcss_clocks_disable(dcss); +} + +static int dcss_clks_init(struct dcss_dev *dcss) +{ + int i; + struct { + const char *id; + struct clk **clk; + } clks[] = { + {"apb", &dcss->apb_clk}, + {"axi", &dcss->axi_clk}, + {"pix", &dcss->pix_clk}, + {"rtrm", &dcss->rtrm_clk}, + {"dtrc", &dcss->dtrc_clk}, + }; + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + *clks[i].clk = devm_clk_get(dcss->dev, clks[i].id); + if (IS_ERR(*clks[i].clk)) { + dev_err(dcss->dev, "failed to get %s clock\n", + clks[i].id); + return PTR_ERR(*clks[i].clk); + } + } + + return 0; +} + +static void dcss_clks_release(struct dcss_dev *dcss) +{ + devm_clk_put(dcss->dev, dcss->dtrc_clk); + devm_clk_put(dcss->dev, dcss->rtrm_clk); + devm_clk_put(dcss->dev, dcss->pix_clk); + devm_clk_put(dcss->dev, dcss->axi_clk); + devm_clk_put(dcss->dev, dcss->apb_clk); +} + +struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output) +{ + struct platform_device *pdev = to_platform_device(dev); + int ret; + struct resource *res; + struct dcss_dev *dcss; + const struct dcss_type_data *devtype; + + devtype = of_device_get_match_data(dev); + if (!devtype) { + dev_err(dev, "no device match found\n"); + return ERR_PTR(-ENODEV); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "cannot get memory resource\n"); + return ERR_PTR(-EINVAL); + } + + dcss = kzalloc(sizeof(*dcss), GFP_KERNEL); + if (!dcss) + return ERR_PTR(-ENOMEM); + + dcss->dev = dev; + dcss->devtype = devtype; + dcss->hdmi_output = hdmi_output; + + ret = dcss_clks_init(dcss); + if (ret) { + dev_err(dev, "clocks initialization failed\n"); + goto err; + } + + dcss->of_port = of_graph_get_port_by_id(dev->of_node, 0); + if (!dcss->of_port) { + dev_err(dev, "no port@0 node in %s\n", dev->of_node->full_name); + ret = -ENODEV; + goto clks_err; + } + + dcss->start_addr = res->start; + + ret = dcss_submodules_init(dcss); + if (ret) { + dev_err(dev, "submodules initialization failed\n"); + goto clks_err; + } + + init_completion(&dcss->disable_completion); + + pm_runtime_set_autosuspend_delay(dev, 100); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_suspended(dev); + pm_runtime_allow(dev); + pm_runtime_enable(dev); + + return dcss; + +clks_err: + dcss_clks_release(dcss); + +err: + kfree(dcss); + + return ERR_PTR(ret); +} + +void dcss_dev_destroy(struct dcss_dev *dcss) +{ + if (!pm_runtime_suspended(dcss->dev)) { + dcss_ctxld_suspend(dcss->ctxld); + dcss_clocks_disable(dcss); + } + + pm_runtime_disable(dcss->dev); + + dcss_submodules_stop(dcss); + + dcss_clks_release(dcss); + + kfree(dcss); +} + +#ifdef CONFIG_PM_SLEEP +int dcss_dev_suspend(struct device *dev) +{ + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + int ret; + + drm_mode_config_helper_suspend(dcss_drv_dev_to_drm(dev)); + + if (pm_runtime_suspended(dev)) + return 0; + + ret = dcss_ctxld_suspend(dcss->ctxld); + if (ret) + return ret; + + dcss_clocks_disable(dcss); + + return 0; +} + +int dcss_dev_resume(struct device *dev) +{ + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + + if (pm_runtime_suspended(dev)) { + drm_mode_config_helper_resume(dcss_drv_dev_to_drm(dev)); + return 0; + } + + dcss_clocks_enable(dcss); + + dcss_blkctl_cfg(dcss->blkctl); + + dcss_ctxld_resume(dcss->ctxld); + + drm_mode_config_helper_resume(dcss_drv_dev_to_drm(dev)); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +#ifdef CONFIG_PM +int dcss_dev_runtime_suspend(struct device *dev) +{ + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + int ret; + + ret = dcss_ctxld_suspend(dcss->ctxld); + if (ret) + return ret; + + dcss_clocks_disable(dcss); + + return 0; +} + +int dcss_dev_runtime_resume(struct device *dev) +{ + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + + dcss_clocks_enable(dcss); + + dcss_blkctl_cfg(dcss->blkctl); + + dcss_ctxld_resume(dcss->ctxld); + + return 0; +} +#endif /* CONFIG_PM */ diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.h b/drivers/gpu/drm/imx/dcss/dcss-dev.h new file mode 100644 index 0000000000000..c642ae17837f6 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-dev.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 NXP. + */ + +#ifndef __DCSS_PRV_H__ +#define __DCSS_PRV_H__ + +#include <drm/drm_fourcc.h> +#include <linux/io.h> +#include <video/videomode.h> + +#define SET 0x04 +#define CLR 0x08 +#define TGL 0x0C + +#define dcss_writel(v, c) writel((v), (c)) +#define dcss_readl(c) readl(c) +#define dcss_set(v, c) writel((v), (c) + SET) +#define dcss_clr(v, c) writel((v), (c) + CLR) +#define dcss_toggle(v, c) writel((v), (c) + TGL) + +static inline void dcss_update(u32 v, u32 m, void __iomem *c) +{ + writel((readl(c) & ~(m)) | (v), (c)); +} + +#define DCSS_DBG_REG(reg) {.name = #reg, .ofs = reg} + +enum { + DCSS_IMX8MQ = 0, +}; + +struct dcss_type_data { + const char *name; + u32 blkctl_ofs; + u32 ctxld_ofs; + u32 rdsrc_ofs; + u32 wrscl_ofs; + u32 dtg_ofs; + u32 scaler_ofs; + u32 ss_ofs; + u32 dpr_ofs; + u32 dtrc_ofs; + u32 dec400d_ofs; + u32 hdr10_ofs; +}; + +struct dcss_debug_reg { + char *name; + u32 ofs; +}; + +enum dcss_ctxld_ctx_type { + CTX_DB, + CTX_SB_HP, /* high-priority */ + CTX_SB_LP, /* low-priority */ +}; + +struct dcss_dev { + struct device *dev; + const struct dcss_type_data *devtype; + struct device_node *of_port; + + u32 start_addr; + + struct dcss_blkctl *blkctl; + struct dcss_ctxld *ctxld; + struct dcss_dpr *dpr; + struct dcss_dtg *dtg; + struct dcss_ss *ss; + struct dcss_hdr10 *hdr10; + struct dcss_scaler *scaler; + struct dcss_dtrc *dtrc; + struct dcss_dec400d *dec400d; + struct dcss_wrscl *wrscl; + struct dcss_rdsrc *rdsrc; + + struct clk *apb_clk; + struct clk *axi_clk; + struct clk *pix_clk; + struct clk *rtrm_clk; + struct clk *dtrc_clk; + struct clk *pll_src_clk; + struct clk *pll_phy_ref_clk; + + bool hdmi_output; + + void (*disable_callback)(void *data); + struct completion disable_completion; +}; + +struct dcss_dev *dcss_drv_dev_to_dcss(struct device *dev); +struct drm_device *dcss_drv_dev_to_drm(struct device *dev); +struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output); +void dcss_dev_destroy(struct dcss_dev *dcss); +int dcss_dev_runtime_suspend(struct device *dev); +int dcss_dev_runtime_resume(struct device *dev); +int dcss_dev_suspend(struct device *dev); +int dcss_dev_resume(struct device *dev); +void dcss_enable_dtg_and_ss(struct dcss_dev *dcss); +void dcss_disable_dtg_and_ss(struct dcss_dev *dcss); + +/* BLKCTL */ +int dcss_blkctl_init(struct dcss_dev *dcss, unsigned long blkctl_base); +void dcss_blkctl_cfg(struct dcss_blkctl *blkctl); +void dcss_blkctl_exit(struct dcss_blkctl *blkctl); + +/* CTXLD */ +int dcss_ctxld_init(struct dcss_dev *dcss, unsigned long ctxld_base); +void dcss_ctxld_exit(struct dcss_ctxld *ctxld); +void dcss_ctxld_write(struct dcss_ctxld *ctxld, u32 ctx_id, + u32 val, u32 reg_idx); +int dcss_ctxld_resume(struct dcss_ctxld *dcss_ctxld); +int dcss_ctxld_suspend(struct dcss_ctxld *dcss_ctxld); +void dcss_ctxld_write_irqsafe(struct dcss_ctxld *ctlxd, u32 ctx_id, u32 val, + u32 reg_ofs); +void dcss_ctxld_kick(struct dcss_ctxld *ctxld); +bool dcss_ctxld_is_flushed(struct dcss_ctxld *ctxld); +int dcss_ctxld_enable(struct dcss_ctxld *ctxld); +void dcss_ctxld_register_completion(struct dcss_ctxld *ctxld, + struct completion *dis_completion); +void dcss_ctxld_assert_locked(struct dcss_ctxld *ctxld); + +/* DPR */ +int dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base); +void dcss_dpr_exit(struct dcss_dpr *dpr); +void dcss_dpr_write_sysctrl(struct dcss_dpr *dpr); +void dcss_dpr_set_res(struct dcss_dpr *dpr, int ch_num, u32 xres, u32 yres); +void dcss_dpr_addr_set(struct dcss_dpr *dpr, int ch_num, u32 luma_base_addr, + u32 chroma_base_addr, u16 pitch); +void dcss_dpr_enable(struct dcss_dpr *dpr, int ch_num, bool en); +void dcss_dpr_format_set(struct dcss_dpr *dpr, int ch_num, + const struct drm_format_info *format, u64 modifier); +void dcss_dpr_set_rotation(struct dcss_dpr *dpr, int ch_num, u32 rotation); + +/* DTG */ +int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base); +void dcss_dtg_exit(struct dcss_dtg *dtg); +bool dcss_dtg_vblank_irq_valid(struct dcss_dtg *dtg); +void dcss_dtg_vblank_irq_enable(struct dcss_dtg *dtg, bool en); +void dcss_dtg_vblank_irq_clear(struct dcss_dtg *dtg); +void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm); +void dcss_dtg_css_set(struct dcss_dtg *dtg); +void dcss_dtg_enable(struct dcss_dtg *dtg); +void dcss_dtg_shutoff(struct dcss_dtg *dtg); +bool dcss_dtg_is_enabled(struct dcss_dtg *dtg); +void dcss_dtg_ctxld_kick_irq_enable(struct dcss_dtg *dtg, bool en); +bool dcss_dtg_global_alpha_changed(struct dcss_dtg *dtg, int ch_num, int alpha); +void dcss_dtg_plane_alpha_set(struct dcss_dtg *dtg, int ch_num, + const struct drm_format_info *format, int alpha); +void dcss_dtg_plane_pos_set(struct dcss_dtg *dtg, int ch_num, + int px, int py, int pw, int ph); +void dcss_dtg_ch_enable(struct dcss_dtg *dtg, int ch_num, bool en); + +/* SUBSAM */ +int dcss_ss_init(struct dcss_dev *dcss, unsigned long subsam_base); +void dcss_ss_exit(struct dcss_ss *ss); +void dcss_ss_enable(struct dcss_ss *ss); +void dcss_ss_shutoff(struct dcss_ss *ss); +void dcss_ss_subsam_set(struct dcss_ss *ss); +void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm, + bool phsync, bool pvsync); + +/* SCALER */ +int dcss_scaler_init(struct dcss_dev *dcss, unsigned long scaler_base); +void dcss_scaler_exit(struct dcss_scaler *scl); +void dcss_scaler_setup(struct dcss_scaler *scl, int ch_num, + const struct drm_format_info *format, + int src_xres, int src_yres, int dst_xres, int dst_yres, + u32 vrefresh_hz); +void dcss_scaler_ch_enable(struct dcss_scaler *scl, int ch_num, bool en); +int dcss_scaler_get_min_max_ratios(struct dcss_scaler *scl, int ch_num, + int *min, int *max); +void dcss_scaler_write_sclctrl(struct dcss_scaler *scl); + +#endif /* __DCSS_PRV_H__ */ diff --git a/drivers/gpu/drm/imx/dcss/dcss-dpr.c b/drivers/gpu/drm/imx/dcss/dcss-dpr.c new file mode 100644 index 0000000000000..df9dab949bf2b --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-dpr.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/device.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_DPR_SYSTEM_CTRL0 0x000 +#define RUN_EN BIT(0) +#define SOFT_RESET BIT(1) +#define REPEAT_EN BIT(2) +#define SHADOW_LOAD_EN BIT(3) +#define SW_SHADOW_LOAD_SEL BIT(4) +#define BCMD2AXI_MSTR_ID_CTRL BIT(16) +#define DCSS_DPR_IRQ_MASK 0x020 +#define DCSS_DPR_IRQ_MASK_STATUS 0x030 +#define DCSS_DPR_IRQ_NONMASK_STATUS 0x040 +#define IRQ_DPR_CTRL_DONE BIT(0) +#define IRQ_DPR_RUN BIT(1) +#define IRQ_DPR_SHADOW_LOADED BIT(2) +#define IRQ_AXI_READ_ERR BIT(3) +#define DPR2RTR_YRGB_FIFO_OVFL BIT(4) +#define DPR2RTR_UV_FIFO_OVFL BIT(5) +#define DPR2RTR_FIFO_LD_BUF_RDY_YRGB_ERR BIT(6) +#define DPR2RTR_FIFO_LD_BUF_RDY_UV_ERR BIT(7) +#define DCSS_DPR_MODE_CTRL0 0x050 +#define RTR_3BUF_EN BIT(0) +#define RTR_4LINE_BUF_EN BIT(1) +#define TILE_TYPE_POS 2 +#define TILE_TYPE_MASK GENMASK(4, 2) +#define YUV_EN BIT(6) +#define COMP_2PLANE_EN BIT(7) +#define PIX_SIZE_POS 8 +#define PIX_SIZE_MASK GENMASK(9, 8) +#define PIX_LUMA_UV_SWAP BIT(10) +#define PIX_UV_SWAP BIT(11) +#define B_COMP_SEL_POS 12 +#define B_COMP_SEL_MASK GENMASK(13, 12) +#define G_COMP_SEL_POS 14 +#define G_COMP_SEL_MASK GENMASK(15, 14) +#define R_COMP_SEL_POS 16 +#define R_COMP_SEL_MASK GENMASK(17, 16) +#define A_COMP_SEL_POS 18 +#define A_COMP_SEL_MASK GENMASK(19, 18) +#define DCSS_DPR_FRAME_CTRL0 0x070 +#define HFLIP_EN BIT(0) +#define VFLIP_EN BIT(1) +#define ROT_ENC_POS 2 +#define ROT_ENC_MASK GENMASK(3, 2) +#define ROT_FLIP_ORDER_EN BIT(4) +#define PITCH_POS 16 +#define PITCH_MASK GENMASK(31, 16) +#define DCSS_DPR_FRAME_1P_CTRL0 0x090 +#define DCSS_DPR_FRAME_1P_PIX_X_CTRL 0x0A0 +#define DCSS_DPR_FRAME_1P_PIX_Y_CTRL 0x0B0 +#define DCSS_DPR_FRAME_1P_BASE_ADDR 0x0C0 +#define DCSS_DPR_FRAME_2P_CTRL0 0x0E0 +#define DCSS_DPR_FRAME_2P_PIX_X_CTRL 0x0F0 +#define DCSS_DPR_FRAME_2P_PIX_Y_CTRL 0x100 +#define DCSS_DPR_FRAME_2P_BASE_ADDR 0x110 +#define DCSS_DPR_STATUS_CTRL0 0x130 +#define STATUS_MUX_SEL_MASK GENMASK(2, 0) +#define STATUS_SRC_SEL_POS 16 +#define STATUS_SRC_SEL_MASK GENMASK(18, 16) +#define DCSS_DPR_STATUS_CTRL1 0x140 +#define DCSS_DPR_RTRAM_CTRL0 0x200 +#define NUM_ROWS_ACTIVE BIT(0) +#define THRES_HIGH_POS 1 +#define THRES_HIGH_MASK GENMASK(3, 1) +#define THRES_LOW_POS 4 +#define THRES_LOW_MASK GENMASK(6, 4) +#define ABORT_SEL BIT(7) + +enum dcss_tile_type { + TILE_LINEAR = 0, + TILE_GPU_STANDARD, + TILE_GPU_SUPER, + TILE_VPU_YUV420, + TILE_VPU_VP9, +}; + +enum dcss_pix_size { + PIX_SIZE_8, + PIX_SIZE_16, + PIX_SIZE_32, +}; + +struct dcss_dpr_ch { + struct dcss_dpr *dpr; + void __iomem *base_reg; + u32 base_ofs; + + struct drm_format_info format; + enum dcss_pix_size pix_size; + enum dcss_tile_type tile; + bool rtram_4line_en; + bool rtram_3buf_en; + + u32 frame_ctrl; + u32 mode_ctrl; + u32 sys_ctrl; + u32 rtram_ctrl; + + bool sys_ctrl_chgd; + + int ch_num; + int irq; +}; + +struct dcss_dpr { + struct device *dev; + struct dcss_ctxld *ctxld; + u32 ctx_id; + + struct dcss_dpr_ch ch[3]; +}; + +static void dcss_dpr_write(struct dcss_dpr_ch *ch, u32 val, u32 ofs) +{ + struct dcss_dpr *dpr = ch->dpr; + + dcss_ctxld_write(dpr->ctxld, dpr->ctx_id, val, ch->base_ofs + ofs); +} + +static int dcss_dpr_ch_init_all(struct dcss_dpr *dpr, unsigned long dpr_base) +{ + struct dcss_dpr_ch *ch; + int i; + + for (i = 0; i < 3; i++) { + ch = &dpr->ch[i]; + + ch->base_ofs = dpr_base + i * 0x1000; + + ch->base_reg = ioremap(ch->base_ofs, SZ_4K); + if (!ch->base_reg) { + dev_err(dpr->dev, "dpr: unable to remap ch %d base\n", + i); + return -ENOMEM; + } + + ch->dpr = dpr; + ch->ch_num = i; + + dcss_writel(0xff, ch->base_reg + DCSS_DPR_IRQ_MASK); + } + + return 0; +} + +int dcss_dpr_init(struct dcss_dev *dcss, unsigned long dpr_base) +{ + struct dcss_dpr *dpr; + + dpr = kzalloc(sizeof(*dpr), GFP_KERNEL); + if (!dpr) + return -ENOMEM; + + dcss->dpr = dpr; + dpr->dev = dcss->dev; + dpr->ctxld = dcss->ctxld; + dpr->ctx_id = CTX_SB_HP; + + if (dcss_dpr_ch_init_all(dpr, dpr_base)) { + int i; + + for (i = 0; i < 3; i++) { + if (dpr->ch[i].base_reg) + iounmap(dpr->ch[i].base_reg); + } + + kfree(dpr); + + return -ENOMEM; + } + + return 0; +} + +void dcss_dpr_exit(struct dcss_dpr *dpr) +{ + int ch_no; + + /* stop DPR on all channels */ + for (ch_no = 0; ch_no < 3; ch_no++) { + struct dcss_dpr_ch *ch = &dpr->ch[ch_no]; + + dcss_writel(0, ch->base_reg + DCSS_DPR_SYSTEM_CTRL0); + + if (ch->base_reg) + iounmap(ch->base_reg); + } + + kfree(dpr); +} + +static u32 dcss_dpr_x_pix_wide_adjust(struct dcss_dpr_ch *ch, u32 pix_wide, + u32 pix_format) +{ + u8 pix_in_64byte_map[3][5] = { + /* LIN, GPU_STD, GPU_SUP, VPU_YUV420, VPU_VP9 */ + { 64, 8, 8, 8, 16}, /* PIX_SIZE_8 */ + { 32, 8, 8, 8, 8}, /* PIX_SIZE_16 */ + { 16, 4, 4, 8, 8}, /* PIX_SIZE_32 */ + }; + u32 offset; + u32 div_64byte_mod, pix_in_64byte; + + pix_in_64byte = pix_in_64byte_map[ch->pix_size][ch->tile]; + + div_64byte_mod = pix_wide % pix_in_64byte; + offset = (div_64byte_mod == 0) ? 0 : (pix_in_64byte - div_64byte_mod); + + return pix_wide + offset; +} + +static u32 dcss_dpr_y_pix_high_adjust(struct dcss_dpr_ch *ch, u32 pix_high, + u32 pix_format) +{ + u8 num_rows_buf = ch->rtram_4line_en ? 4 : 8; + u32 offset, pix_y_mod; + + pix_y_mod = pix_high % num_rows_buf; + offset = pix_y_mod ? (num_rows_buf - pix_y_mod) : 0; + + return pix_high + offset; +} + +void dcss_dpr_set_res(struct dcss_dpr *dpr, int ch_num, u32 xres, u32 yres) +{ + struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; + u32 pix_format = ch->format.format; + u32 gap = DCSS_DPR_FRAME_2P_BASE_ADDR - DCSS_DPR_FRAME_1P_BASE_ADDR; + int plane, max_planes = 1; + u32 pix_x_wide, pix_y_high; + + if (pix_format == DRM_FORMAT_NV12 || + pix_format == DRM_FORMAT_NV21) + max_planes = 2; + + for (plane = 0; plane < max_planes; plane++) { + yres = plane == 1 ? yres >> 1 : yres; + + pix_x_wide = dcss_dpr_x_pix_wide_adjust(ch, xres, pix_format); + pix_y_high = dcss_dpr_y_pix_high_adjust(ch, yres, pix_format); + + dcss_dpr_write(ch, pix_x_wide, + DCSS_DPR_FRAME_1P_PIX_X_CTRL + plane * gap); + dcss_dpr_write(ch, pix_y_high, + DCSS_DPR_FRAME_1P_PIX_Y_CTRL + plane * gap); + + dcss_dpr_write(ch, 2, DCSS_DPR_FRAME_1P_CTRL0 + plane * gap); + } +} + +void dcss_dpr_addr_set(struct dcss_dpr *dpr, int ch_num, u32 luma_base_addr, + u32 chroma_base_addr, u16 pitch) +{ + struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; + + dcss_dpr_write(ch, luma_base_addr, DCSS_DPR_FRAME_1P_BASE_ADDR); + + dcss_dpr_write(ch, chroma_base_addr, DCSS_DPR_FRAME_2P_BASE_ADDR); + + ch->frame_ctrl &= ~PITCH_MASK; + ch->frame_ctrl |= (((u32)pitch << PITCH_POS) & PITCH_MASK); +} + +static void dcss_dpr_argb_comp_sel(struct dcss_dpr_ch *ch, int a_sel, int r_sel, + int g_sel, int b_sel) +{ + u32 sel; + + sel = ((a_sel << A_COMP_SEL_POS) & A_COMP_SEL_MASK) | + ((r_sel << R_COMP_SEL_POS) & R_COMP_SEL_MASK) | + ((g_sel << G_COMP_SEL_POS) & G_COMP_SEL_MASK) | + ((b_sel << B_COMP_SEL_POS) & B_COMP_SEL_MASK); + + ch->mode_ctrl &= ~(A_COMP_SEL_MASK | R_COMP_SEL_MASK | + G_COMP_SEL_MASK | B_COMP_SEL_MASK); + ch->mode_ctrl |= sel; +} + +static void dcss_dpr_pix_size_set(struct dcss_dpr_ch *ch, + const struct drm_format_info *format) +{ + u32 val; + + switch (format->format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + val = PIX_SIZE_8; + break; + + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + val = PIX_SIZE_16; + break; + + default: + val = PIX_SIZE_32; + break; + } + + ch->pix_size = val; + + ch->mode_ctrl &= ~PIX_SIZE_MASK; + ch->mode_ctrl |= ((val << PIX_SIZE_POS) & PIX_SIZE_MASK); +} + +static void dcss_dpr_uv_swap(struct dcss_dpr_ch *ch, bool swap) +{ + ch->mode_ctrl &= ~PIX_UV_SWAP; + ch->mode_ctrl |= (swap ? PIX_UV_SWAP : 0); +} + +static void dcss_dpr_y_uv_swap(struct dcss_dpr_ch *ch, bool swap) +{ + ch->mode_ctrl &= ~PIX_LUMA_UV_SWAP; + ch->mode_ctrl |= (swap ? PIX_LUMA_UV_SWAP : 0); +} + +static void dcss_dpr_2plane_en(struct dcss_dpr_ch *ch, bool en) +{ + ch->mode_ctrl &= ~COMP_2PLANE_EN; + ch->mode_ctrl |= (en ? COMP_2PLANE_EN : 0); +} + +static void dcss_dpr_yuv_en(struct dcss_dpr_ch *ch, bool en) +{ + ch->mode_ctrl &= ~YUV_EN; + ch->mode_ctrl |= (en ? YUV_EN : 0); +} + +void dcss_dpr_enable(struct dcss_dpr *dpr, int ch_num, bool en) +{ + struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; + u32 sys_ctrl; + + sys_ctrl = (en ? REPEAT_EN | RUN_EN : 0); + + if (en) { + dcss_dpr_write(ch, ch->mode_ctrl, DCSS_DPR_MODE_CTRL0); + dcss_dpr_write(ch, ch->frame_ctrl, DCSS_DPR_FRAME_CTRL0); + dcss_dpr_write(ch, ch->rtram_ctrl, DCSS_DPR_RTRAM_CTRL0); + } + + if (ch->sys_ctrl != sys_ctrl) + ch->sys_ctrl_chgd = true; + + ch->sys_ctrl = sys_ctrl; +} + +struct rgb_comp_sel { + u32 drm_format; + int a_sel; + int r_sel; + int g_sel; + int b_sel; +}; + +static struct rgb_comp_sel comp_sel_map[] = { + {DRM_FORMAT_ARGB8888, 3, 2, 1, 0}, + {DRM_FORMAT_XRGB8888, 3, 2, 1, 0}, + {DRM_FORMAT_ABGR8888, 3, 0, 1, 2}, + {DRM_FORMAT_XBGR8888, 3, 0, 1, 2}, + {DRM_FORMAT_RGBA8888, 0, 3, 2, 1}, + {DRM_FORMAT_RGBX8888, 0, 3, 2, 1}, + {DRM_FORMAT_BGRA8888, 0, 1, 2, 3}, + {DRM_FORMAT_BGRX8888, 0, 1, 2, 3}, +}; + +static int to_comp_sel(u32 pix_fmt, int *a_sel, int *r_sel, int *g_sel, + int *b_sel) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(comp_sel_map); i++) { + if (comp_sel_map[i].drm_format == pix_fmt) { + *a_sel = comp_sel_map[i].a_sel; + *r_sel = comp_sel_map[i].r_sel; + *g_sel = comp_sel_map[i].g_sel; + *b_sel = comp_sel_map[i].b_sel; + + return 0; + } + } + + return -1; +} + +static void dcss_dpr_rtram_set(struct dcss_dpr_ch *ch, u32 pix_format) +{ + u32 val, mask; + + switch (pix_format) { + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV12: + ch->rtram_3buf_en = true; + ch->rtram_4line_en = false; + break; + + default: + ch->rtram_3buf_en = true; + ch->rtram_4line_en = true; + break; + } + + val = (ch->rtram_4line_en ? RTR_4LINE_BUF_EN : 0); + val |= (ch->rtram_3buf_en ? RTR_3BUF_EN : 0); + mask = RTR_4LINE_BUF_EN | RTR_3BUF_EN; + + ch->mode_ctrl &= ~mask; + ch->mode_ctrl |= (val & mask); + + val = (ch->rtram_4line_en ? 0 : NUM_ROWS_ACTIVE); + val |= (3 << THRES_LOW_POS) & THRES_LOW_MASK; + val |= (4 << THRES_HIGH_POS) & THRES_HIGH_MASK; + mask = THRES_LOW_MASK | THRES_HIGH_MASK | NUM_ROWS_ACTIVE; + + ch->rtram_ctrl &= ~mask; + ch->rtram_ctrl |= (val & mask); +} + +static void dcss_dpr_setup_components(struct dcss_dpr_ch *ch, + const struct drm_format_info *format) +{ + int a_sel, r_sel, g_sel, b_sel; + bool uv_swap, y_uv_swap; + + switch (format->format) { + case DRM_FORMAT_YVYU: + uv_swap = true; + y_uv_swap = true; + break; + + case DRM_FORMAT_VYUY: + case DRM_FORMAT_NV21: + uv_swap = true; + y_uv_swap = false; + break; + + case DRM_FORMAT_YUYV: + uv_swap = false; + y_uv_swap = true; + break; + + default: + uv_swap = false; + y_uv_swap = false; + break; + } + + dcss_dpr_uv_swap(ch, uv_swap); + + dcss_dpr_y_uv_swap(ch, y_uv_swap); + + if (!format->is_yuv) { + if (!to_comp_sel(format->format, &a_sel, &r_sel, + &g_sel, &b_sel)) { + dcss_dpr_argb_comp_sel(ch, a_sel, r_sel, g_sel, b_sel); + } else { + dcss_dpr_argb_comp_sel(ch, 3, 2, 1, 0); + } + } else { + dcss_dpr_argb_comp_sel(ch, 0, 0, 0, 0); + } +} + +static void dcss_dpr_tile_set(struct dcss_dpr_ch *ch, uint64_t modifier) +{ + switch (ch->ch_num) { + case 0: + switch (modifier) { + case DRM_FORMAT_MOD_LINEAR: + ch->tile = TILE_LINEAR; + break; + case DRM_FORMAT_MOD_VIVANTE_TILED: + ch->tile = TILE_GPU_STANDARD; + break; + case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: + ch->tile = TILE_GPU_SUPER; + break; + default: + WARN_ON(1); + break; + } + break; + case 1: + case 2: + ch->tile = TILE_LINEAR; + break; + default: + WARN_ON(1); + return; + } + + ch->mode_ctrl &= ~TILE_TYPE_MASK; + ch->mode_ctrl |= ((ch->tile << TILE_TYPE_POS) & TILE_TYPE_MASK); +} + +void dcss_dpr_format_set(struct dcss_dpr *dpr, int ch_num, + const struct drm_format_info *format, u64 modifier) +{ + struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; + + ch->format = *format; + + dcss_dpr_yuv_en(ch, format->is_yuv); + + dcss_dpr_pix_size_set(ch, format); + + dcss_dpr_setup_components(ch, format); + + dcss_dpr_2plane_en(ch, format->num_planes == 2); + + dcss_dpr_rtram_set(ch, format->format); + + dcss_dpr_tile_set(ch, modifier); +} + +/* This function will be called from interrupt context. */ +void dcss_dpr_write_sysctrl(struct dcss_dpr *dpr) +{ + int chnum; + + dcss_ctxld_assert_locked(dpr->ctxld); + + for (chnum = 0; chnum < 3; chnum++) { + struct dcss_dpr_ch *ch = &dpr->ch[chnum]; + + if (ch->sys_ctrl_chgd) { + dcss_ctxld_write_irqsafe(dpr->ctxld, dpr->ctx_id, + ch->sys_ctrl, + ch->base_ofs + + DCSS_DPR_SYSTEM_CTRL0); + ch->sys_ctrl_chgd = false; + } + } +} + +void dcss_dpr_set_rotation(struct dcss_dpr *dpr, int ch_num, u32 rotation) +{ + struct dcss_dpr_ch *ch = &dpr->ch[ch_num]; + + ch->frame_ctrl &= ~(HFLIP_EN | VFLIP_EN | ROT_ENC_MASK); + + ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_X ? HFLIP_EN : 0; + ch->frame_ctrl |= rotation & DRM_MODE_REFLECT_Y ? VFLIP_EN : 0; + + if (rotation & DRM_MODE_ROTATE_90) + ch->frame_ctrl |= 1 << ROT_ENC_POS; + else if (rotation & DRM_MODE_ROTATE_180) + ch->frame_ctrl |= 2 << ROT_ENC_POS; + else if (rotation & DRM_MODE_ROTATE_270) + ch->frame_ctrl |= 3 << ROT_ENC_POS; +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-drv.c b/drivers/gpu/drm/imx/dcss/dcss-drv.c new file mode 100644 index 0000000000000..8dc2f85c514b0 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-drv.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <drm/drm_of.h> + +#include "dcss-dev.h" +#include "dcss-kms.h" + +struct dcss_drv { + struct dcss_dev *dcss; + struct dcss_kms_dev *kms; +}; + +struct dcss_dev *dcss_drv_dev_to_dcss(struct device *dev) +{ + struct dcss_drv *mdrv = dev_get_drvdata(dev); + + return mdrv ? mdrv->dcss : NULL; +} + +struct drm_device *dcss_drv_dev_to_drm(struct device *dev) +{ + struct dcss_drv *mdrv = dev_get_drvdata(dev); + + return mdrv ? &mdrv->kms->base : NULL; +} + +static int dcss_drv_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *remote; + struct dcss_drv *mdrv; + int err = 0; + bool hdmi_output = true; + + if (!dev->of_node) + return -ENODEV; + + remote = of_graph_get_remote_node(dev->of_node, 0, 0); + if (!remote) + return -ENODEV; + + hdmi_output = !of_device_is_compatible(remote, "fsl,imx8mq-nwl-dsi"); + + of_node_put(remote); + + mdrv = kzalloc(sizeof(*mdrv), GFP_KERNEL); + if (!mdrv) + return -ENOMEM; + + mdrv->dcss = dcss_dev_create(dev, hdmi_output); + if (IS_ERR(mdrv->dcss)) { + err = PTR_ERR(mdrv->dcss); + goto err; + } + + dev_set_drvdata(dev, mdrv); + + mdrv->kms = dcss_kms_attach(mdrv->dcss); + if (IS_ERR(mdrv->kms)) { + err = PTR_ERR(mdrv->kms); + goto dcss_shutoff; + } + + return 0; + +dcss_shutoff: + dcss_dev_destroy(mdrv->dcss); + + dev_set_drvdata(dev, NULL); + +err: + kfree(mdrv); + return err; +} + +static int dcss_drv_platform_remove(struct platform_device *pdev) +{ + struct dcss_drv *mdrv = dev_get_drvdata(&pdev->dev); + + if (!mdrv) + return 0; + + dcss_kms_detach(mdrv->kms); + dcss_dev_destroy(mdrv->dcss); + + dev_set_drvdata(&pdev->dev, NULL); + + kfree(mdrv); + + return 0; +} + +static struct dcss_type_data dcss_types[] = { + [DCSS_IMX8MQ] = { + .name = "DCSS_IMX8MQ", + .blkctl_ofs = 0x2F000, + .ctxld_ofs = 0x23000, + .dtg_ofs = 0x20000, + .scaler_ofs = 0x1C000, + .ss_ofs = 0x1B000, + .dpr_ofs = 0x18000, + }, +}; + +static const struct of_device_id dcss_of_match[] = { + { .compatible = "nxp,imx8mq-dcss", .data = &dcss_types[DCSS_IMX8MQ], }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dcss_of_match); + +static const struct dev_pm_ops dcss_dev_pm = { + SET_SYSTEM_SLEEP_PM_OPS(dcss_dev_suspend, dcss_dev_resume) + SET_RUNTIME_PM_OPS(dcss_dev_runtime_suspend, + dcss_dev_runtime_resume, NULL) +}; + +static struct platform_driver dcss_platform_driver = { + .probe = dcss_drv_platform_probe, + .remove = dcss_drv_platform_remove, + .driver = { + .name = "imx-dcss", + .of_match_table = dcss_of_match, + .pm = &dcss_dev_pm, + }, +}; + +module_platform_driver(dcss_platform_driver); + +MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@nxp.com>"); +MODULE_DESCRIPTION("DCSS driver for i.MX8MQ"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/imx/dcss/dcss-dtg.c b/drivers/gpu/drm/imx/dcss/dcss-dtg.c new file mode 100644 index 0000000000000..30de00540f63a --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-dtg.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_DTG_TC_CONTROL_STATUS 0x00 +#define CH3_EN BIT(0) +#define CH2_EN BIT(1) +#define CH1_EN BIT(2) +#define OVL_DATA_MODE BIT(3) +#define BLENDER_VIDEO_ALPHA_SEL BIT(7) +#define DTG_START BIT(8) +#define DBY_MODE_EN BIT(9) +#define CH1_ALPHA_SEL BIT(10) +#define CSS_PIX_COMP_SWAP_POS 12 +#define CSS_PIX_COMP_SWAP_MASK GENMASK(14, 12) +#define DEFAULT_FG_ALPHA_POS 24 +#define DEFAULT_FG_ALPHA_MASK GENMASK(31, 24) +#define DCSS_DTG_TC_DTG 0x04 +#define DCSS_DTG_TC_DISP_TOP 0x08 +#define DCSS_DTG_TC_DISP_BOT 0x0C +#define DCSS_DTG_TC_CH1_TOP 0x10 +#define DCSS_DTG_TC_CH1_BOT 0x14 +#define DCSS_DTG_TC_CH2_TOP 0x18 +#define DCSS_DTG_TC_CH2_BOT 0x1C +#define DCSS_DTG_TC_CH3_TOP 0x20 +#define DCSS_DTG_TC_CH3_BOT 0x24 +#define TC_X_POS 0 +#define TC_X_MASK GENMASK(12, 0) +#define TC_Y_POS 16 +#define TC_Y_MASK GENMASK(28, 16) +#define DCSS_DTG_TC_CTXLD 0x28 +#define TC_CTXLD_DB_Y_POS 0 +#define TC_CTXLD_DB_Y_MASK GENMASK(12, 0) +#define TC_CTXLD_SB_Y_POS 16 +#define TC_CTXLD_SB_Y_MASK GENMASK(28, 16) +#define DCSS_DTG_TC_CH1_BKRND 0x2C +#define DCSS_DTG_TC_CH2_BKRND 0x30 +#define BKRND_R_Y_COMP_POS 20 +#define BKRND_R_Y_COMP_MASK GENMASK(29, 20) +#define BKRND_G_U_COMP_POS 10 +#define BKRND_G_U_COMP_MASK GENMASK(19, 10) +#define BKRND_B_V_COMP_POS 0 +#define BKRND_B_V_COMP_MASK GENMASK(9, 0) +#define DCSS_DTG_BLENDER_DBY_RANGEINV 0x38 +#define DCSS_DTG_BLENDER_DBY_RANGEMIN 0x3C +#define DCSS_DTG_BLENDER_DBY_BDP 0x40 +#define DCSS_DTG_BLENDER_BKRND_I 0x44 +#define DCSS_DTG_BLENDER_BKRND_P 0x48 +#define DCSS_DTG_BLENDER_BKRND_T 0x4C +#define DCSS_DTG_LINE0_INT 0x50 +#define DCSS_DTG_LINE1_INT 0x54 +#define DCSS_DTG_BG_ALPHA_DEFAULT 0x58 +#define DCSS_DTG_INT_STATUS 0x5C +#define DCSS_DTG_INT_CONTROL 0x60 +#define DCSS_DTG_TC_CH3_BKRND 0x64 +#define DCSS_DTG_INT_MASK 0x68 +#define LINE0_IRQ BIT(0) +#define LINE1_IRQ BIT(1) +#define LINE2_IRQ BIT(2) +#define LINE3_IRQ BIT(3) +#define DCSS_DTG_LINE2_INT 0x6C +#define DCSS_DTG_LINE3_INT 0x70 +#define DCSS_DTG_DBY_OL 0x74 +#define DCSS_DTG_DBY_BL 0x78 +#define DCSS_DTG_DBY_EL 0x7C + +struct dcss_dtg { + struct device *dev; + struct dcss_ctxld *ctxld; + void __iomem *base_reg; + u32 base_ofs; + + u32 ctx_id; + + bool in_use; + + u32 dis_ulc_x; + u32 dis_ulc_y; + + u32 control_status; + u32 alpha; + u32 alpha_cfg; + + int ctxld_kick_irq; + bool ctxld_kick_irq_en; +}; + +static void dcss_dtg_write(struct dcss_dtg *dtg, u32 val, u32 ofs) +{ + if (!dtg->in_use) + dcss_writel(val, dtg->base_reg + ofs); + + dcss_ctxld_write(dtg->ctxld, dtg->ctx_id, + val, dtg->base_ofs + ofs); +} + +static irqreturn_t dcss_dtg_irq_handler(int irq, void *data) +{ + struct dcss_dtg *dtg = data; + u32 status; + + status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); + + if (!(status & LINE0_IRQ)) + return IRQ_NONE; + + dcss_ctxld_kick(dtg->ctxld); + + dcss_writel(status & LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL); + + return IRQ_HANDLED; +} + +static int dcss_dtg_irq_config(struct dcss_dtg *dtg, + struct platform_device *pdev) +{ + int ret; + + dtg->ctxld_kick_irq = platform_get_irq_byname(pdev, "ctxld_kick"); + if (dtg->ctxld_kick_irq < 0) + return dtg->ctxld_kick_irq; + + dcss_update(0, LINE0_IRQ | LINE1_IRQ, + dtg->base_reg + DCSS_DTG_INT_MASK); + + ret = request_irq(dtg->ctxld_kick_irq, dcss_dtg_irq_handler, + 0, "dcss_ctxld_kick", dtg); + if (ret) { + dev_err(dtg->dev, "dtg: irq request failed.\n"); + return ret; + } + + disable_irq(dtg->ctxld_kick_irq); + + dtg->ctxld_kick_irq_en = false; + + return 0; +} + +int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base) +{ + int ret = 0; + struct dcss_dtg *dtg; + + dtg = kzalloc(sizeof(*dtg), GFP_KERNEL); + if (!dtg) + return -ENOMEM; + + dcss->dtg = dtg; + dtg->dev = dcss->dev; + dtg->ctxld = dcss->ctxld; + + dtg->base_reg = ioremap(dtg_base, SZ_4K); + if (!dtg->base_reg) { + dev_err(dcss->dev, "dtg: unable to remap dtg base\n"); + ret = -ENOMEM; + goto err_ioremap; + } + + dtg->base_ofs = dtg_base; + dtg->ctx_id = CTX_DB; + + dtg->alpha = 255; + + dtg->control_status |= OVL_DATA_MODE | BLENDER_VIDEO_ALPHA_SEL | + ((dtg->alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK); + + ret = dcss_dtg_irq_config(dtg, to_platform_device(dcss->dev)); + if (ret) + goto err_irq; + + return 0; + +err_irq: + iounmap(dtg->base_reg); + +err_ioremap: + kfree(dtg); + + return ret; +} + +void dcss_dtg_exit(struct dcss_dtg *dtg) +{ + free_irq(dtg->ctxld_kick_irq, dtg); + + if (dtg->base_reg) + iounmap(dtg->base_reg); + + kfree(dtg); +} + +void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm) +{ + struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dtg->dev); + u16 dtg_lrc_x, dtg_lrc_y; + u16 dis_ulc_x, dis_ulc_y; + u16 dis_lrc_x, dis_lrc_y; + u32 sb_ctxld_trig, db_ctxld_trig; + u32 pixclock = vm->pixelclock; + u32 actual_clk; + + dtg_lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len + + vm->hactive - 1; + dtg_lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len + + vm->vactive - 1; + dis_ulc_x = vm->hsync_len + vm->hback_porch - 1; + dis_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch - 1; + dis_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1; + dis_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch + + vm->vactive - 1; + + clk_disable_unprepare(dcss->pix_clk); + clk_set_rate(dcss->pix_clk, vm->pixelclock); + clk_prepare_enable(dcss->pix_clk); + + actual_clk = clk_get_rate(dcss->pix_clk); + if (pixclock != actual_clk) { + dev_info(dtg->dev, + "Pixel clock set to %u kHz instead of %u kHz.\n", + (actual_clk / 1000), (pixclock / 1000)); + } + + dcss_dtg_write(dtg, ((dtg_lrc_y << TC_Y_POS) | dtg_lrc_x), + DCSS_DTG_TC_DTG); + dcss_dtg_write(dtg, ((dis_ulc_y << TC_Y_POS) | dis_ulc_x), + DCSS_DTG_TC_DISP_TOP); + dcss_dtg_write(dtg, ((dis_lrc_y << TC_Y_POS) | dis_lrc_x), + DCSS_DTG_TC_DISP_BOT); + + dtg->dis_ulc_x = dis_ulc_x; + dtg->dis_ulc_y = dis_ulc_y; + + sb_ctxld_trig = ((0 * dis_lrc_y / 100) << TC_CTXLD_SB_Y_POS) & + TC_CTXLD_SB_Y_MASK; + db_ctxld_trig = ((99 * dis_lrc_y / 100) << TC_CTXLD_DB_Y_POS) & + TC_CTXLD_DB_Y_MASK; + + dcss_dtg_write(dtg, sb_ctxld_trig | db_ctxld_trig, DCSS_DTG_TC_CTXLD); + + /* vblank trigger */ + dcss_dtg_write(dtg, 0, DCSS_DTG_LINE1_INT); + + /* CTXLD trigger */ + dcss_dtg_write(dtg, ((90 * dis_lrc_y) / 100) << 16, DCSS_DTG_LINE0_INT); +} + +void dcss_dtg_plane_pos_set(struct dcss_dtg *dtg, int ch_num, + int px, int py, int pw, int ph) +{ + u16 p_ulc_x, p_ulc_y; + u16 p_lrc_x, p_lrc_y; + + p_ulc_x = dtg->dis_ulc_x + px; + p_ulc_y = dtg->dis_ulc_y + py; + p_lrc_x = p_ulc_x + pw; + p_lrc_y = p_ulc_y + ph; + + if (!px && !py && !pw && !ph) { + dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num); + dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num); + } else { + dcss_dtg_write(dtg, ((p_ulc_y << TC_Y_POS) | p_ulc_x), + DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num); + dcss_dtg_write(dtg, ((p_lrc_y << TC_Y_POS) | p_lrc_x), + DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num); + } +} + +bool dcss_dtg_global_alpha_changed(struct dcss_dtg *dtg, int ch_num, int alpha) +{ + if (ch_num) + return false; + + return alpha != dtg->alpha; +} + +void dcss_dtg_plane_alpha_set(struct dcss_dtg *dtg, int ch_num, + const struct drm_format_info *format, int alpha) +{ + /* we care about alpha only when channel 0 is concerned */ + if (ch_num) + return; + + /* + * Use global alpha if pixel format does not have alpha channel or the + * user explicitly chose to use global alpha (i.e. alpha is not OPAQUE). + */ + if (!format->has_alpha || alpha != 255) + dtg->alpha_cfg = (alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK; + else /* use per-pixel alpha otherwise */ + dtg->alpha_cfg = CH1_ALPHA_SEL; + + dtg->alpha = alpha; +} + +void dcss_dtg_css_set(struct dcss_dtg *dtg) +{ + dtg->control_status |= + (0x5 << CSS_PIX_COMP_SWAP_POS) & CSS_PIX_COMP_SWAP_MASK; +} + +void dcss_dtg_enable(struct dcss_dtg *dtg) +{ + dtg->control_status |= DTG_START; + + dtg->control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK); + dtg->control_status |= dtg->alpha_cfg; + + dcss_dtg_write(dtg, dtg->control_status, DCSS_DTG_TC_CONTROL_STATUS); + + dtg->in_use = true; +} + +void dcss_dtg_shutoff(struct dcss_dtg *dtg) +{ + dtg->control_status &= ~DTG_START; + + dcss_writel(dtg->control_status, + dtg->base_reg + DCSS_DTG_TC_CONTROL_STATUS); + + dtg->in_use = false; +} + +bool dcss_dtg_is_enabled(struct dcss_dtg *dtg) +{ + return dtg->in_use; +} + +void dcss_dtg_ch_enable(struct dcss_dtg *dtg, int ch_num, bool en) +{ + u32 ch_en_map[] = {CH1_EN, CH2_EN, CH3_EN}; + u32 control_status; + + control_status = dtg->control_status & ~ch_en_map[ch_num]; + control_status |= en ? ch_en_map[ch_num] : 0; + + control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK); + control_status |= dtg->alpha_cfg; + + if (dtg->control_status != control_status) + dcss_dtg_write(dtg, control_status, DCSS_DTG_TC_CONTROL_STATUS); + + dtg->control_status = control_status; +} + +void dcss_dtg_vblank_irq_enable(struct dcss_dtg *dtg, bool en) +{ + u32 status; + u32 mask = en ? LINE1_IRQ : 0; + + if (en) { + status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); + dcss_writel(status & LINE1_IRQ, + dtg->base_reg + DCSS_DTG_INT_CONTROL); + } + + dcss_update(mask, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK); +} + +void dcss_dtg_ctxld_kick_irq_enable(struct dcss_dtg *dtg, bool en) +{ + u32 status; + u32 mask = en ? LINE0_IRQ : 0; + + if (en) { + status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS); + + if (!dtg->ctxld_kick_irq_en) { + dcss_writel(status & LINE0_IRQ, + dtg->base_reg + DCSS_DTG_INT_CONTROL); + enable_irq(dtg->ctxld_kick_irq); + dtg->ctxld_kick_irq_en = true; + dcss_update(mask, LINE0_IRQ, + dtg->base_reg + DCSS_DTG_INT_MASK); + } + + return; + } + + if (!dtg->ctxld_kick_irq_en) + return; + + disable_irq_nosync(dtg->ctxld_kick_irq); + dtg->ctxld_kick_irq_en = false; + + dcss_update(mask, LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK); +} + +void dcss_dtg_vblank_irq_clear(struct dcss_dtg *dtg) +{ + dcss_update(LINE1_IRQ, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL); +} + +bool dcss_dtg_vblank_irq_valid(struct dcss_dtg *dtg) +{ + return !!(dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS) & LINE1_IRQ); +} + diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c new file mode 100644 index 0000000000000..3ca49d0a3e61f --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + +#include "dcss-dev.h" +#include "dcss-kms.h" + +DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops); + +static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = { + .fb_create = drm_gem_fb_create, + .output_poll_changed = drm_fb_helper_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static struct drm_driver dcss_kms_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + .gem_free_object_unlocked = drm_gem_cma_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = drm_gem_cma_dumb_create, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, + .fops = &dcss_cma_fops, + .name = "imx-dcss", + .desc = "i.MX8MQ Display Subsystem", + .date = "20190917", + .major = 1, + .minor = 0, + .patchlevel = 0, +}; + +static const struct drm_mode_config_helper_funcs dcss_mode_config_helpers = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +}; + +static void dcss_kms_mode_config_init(struct dcss_kms_dev *kms) +{ + struct drm_mode_config *config = &kms->base.mode_config; + + drm_mode_config_init(&kms->base); + + config->min_width = 1; + config->min_height = 1; + config->max_width = 4096; + config->max_height = 4096; + config->allow_fb_modifiers = true; + config->normalize_zpos = true; + + config->funcs = &dcss_drm_mode_config_funcs; + config->helper_private = &dcss_mode_config_helpers; +} + +static const struct drm_encoder_funcs dcss_kms_simple_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static int dcss_kms_setup_encoder(struct dcss_kms_dev *kms) +{ + struct drm_device *ddev = &kms->base; + struct drm_encoder *encoder = &kms->encoder; + struct drm_crtc *crtc = (struct drm_crtc *)&kms->crtc; + struct drm_panel *panel; + struct drm_bridge *bridge; + int ret; + + ret = drm_of_find_panel_or_bridge(ddev->dev->of_node, 0, 0, + &panel, &bridge); + if (ret) + return ret; + + if (!bridge) { + dev_err(ddev->dev, "No bridge found %d.\n", ret); + return -ENODEV; + } + + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ret = drm_encoder_init(&kms->base, encoder, + &dcss_kms_simple_encoder_funcs, + DRM_MODE_ENCODER_NONE, NULL); + if (ret) { + dev_err(ddev->dev, "Failed initializing encoder %d.\n", ret); + return ret; + } + + return drm_bridge_attach(encoder, bridge, NULL, 0); +} + +struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) +{ + struct dcss_kms_dev *kms; + struct drm_device *drm; + struct dcss_crtc *crtc; + int ret; + + kms = devm_drm_dev_alloc(dcss->dev, &dcss_kms_driver, + struct dcss_kms_dev, base); + if (IS_ERR(kms)) + return kms; + + drm = &kms->base; + crtc = &kms->crtc; + + drm->dev_private = dcss; + + dcss_kms_mode_config_init(kms); + + ret = drm_vblank_init(drm, 1); + if (ret) + goto cleanup_mode_config; + + drm->irq_enabled = true; + + ret = dcss_crtc_init(crtc, drm); + if (ret) + goto cleanup_mode_config; + + ret = dcss_kms_setup_encoder(kms); + if (ret) + goto cleanup_crtc; + + drm_mode_config_reset(drm); + + drm_kms_helper_poll_init(drm); + + ret = drm_dev_register(drm, 0); + if (ret) + goto cleanup_crtc; + + drm_fbdev_generic_setup(drm, 32); + + return kms; + +cleanup_crtc: + drm_kms_helper_poll_fini(drm); + dcss_crtc_deinit(crtc, drm); + +cleanup_mode_config: + drm_mode_config_cleanup(drm); + drm->dev_private = NULL; + + return ERR_PTR(ret); +} + +void dcss_kms_detach(struct dcss_kms_dev *kms) +{ + struct drm_device *drm = &kms->base; + + drm_dev_unregister(drm); + drm_kms_helper_poll_fini(drm); + drm_atomic_helper_shutdown(drm); + drm_crtc_vblank_off(&kms->crtc.base); + drm->irq_enabled = false; + drm_mode_config_cleanup(drm); + dcss_crtc_deinit(&kms->crtc, drm); + drm->dev_private = NULL; +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.h b/drivers/gpu/drm/imx/dcss/dcss-kms.h new file mode 100644 index 0000000000000..1f51c86c69865 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 NXP. + */ + +#ifndef _DCSS_KMS_H_ +#define _DCSS_KMS_H_ + +#include <drm/drm_encoder.h> + +struct dcss_plane { + struct drm_plane base; + + int ch_num; +}; + +struct dcss_crtc { + struct drm_crtc base; + struct drm_crtc_state *state; + + struct dcss_plane *plane[3]; + + int irq; + + bool disable_ctxld_kick_irq; +}; + +struct dcss_kms_dev { + struct drm_device base; + struct dcss_crtc crtc; + struct drm_encoder encoder; +}; + +struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss); +void dcss_kms_detach(struct dcss_kms_dev *kms); +int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm); +void dcss_crtc_deinit(struct dcss_crtc *crtc, struct drm_device *drm); +struct dcss_plane *dcss_plane_init(struct drm_device *drm, + unsigned int possible_crtcs, + enum drm_plane_type type, + unsigned int zpos); + +#endif diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c new file mode 100644 index 0000000000000..961d671f171b4 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_cma_helper.h> + +#include "dcss-dev.h" +#include "dcss-kms.h" + +static const u32 dcss_common_formats[] = { + /* RGB */ + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, +}; + +static const u64 dcss_video_format_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + +static const u64 dcss_graphics_format_modifiers[] = { + DRM_FORMAT_MOD_VIVANTE_TILED, + DRM_FORMAT_MOD_VIVANTE_SUPER_TILED, + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID, +}; + +static inline struct dcss_plane *to_dcss_plane(struct drm_plane *p) +{ + return container_of(p, struct dcss_plane, base); +} + +static inline bool dcss_plane_fb_is_linear(const struct drm_framebuffer *fb) +{ + return ((fb->flags & DRM_MODE_FB_MODIFIERS) == 0) || + ((fb->flags & DRM_MODE_FB_MODIFIERS) != 0 && + fb->modifier == DRM_FORMAT_MOD_LINEAR); +} + +static void dcss_plane_destroy(struct drm_plane *plane) +{ + struct dcss_plane *dcss_plane = container_of(plane, struct dcss_plane, + base); + + drm_plane_cleanup(plane); + kfree(dcss_plane); +} + +static bool dcss_plane_format_mod_supported(struct drm_plane *plane, + u32 format, + u64 modifier) +{ + switch (plane->type) { + case DRM_PLANE_TYPE_PRIMARY: + switch (format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB2101010: + return modifier == DRM_FORMAT_MOD_LINEAR || + modifier == DRM_FORMAT_MOD_VIVANTE_TILED || + modifier == DRM_FORMAT_MOD_VIVANTE_SUPER_TILED; + default: + return modifier == DRM_FORMAT_MOD_LINEAR; + } + break; + case DRM_PLANE_TYPE_OVERLAY: + return modifier == DRM_FORMAT_MOD_LINEAR; + default: + return false; + } +} + +static const struct drm_plane_funcs dcss_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = dcss_plane_destroy, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, + .format_mod_supported = dcss_plane_format_mod_supported, +}; + +static bool dcss_plane_can_rotate(const struct drm_format_info *format, + bool mod_present, u64 modifier, + unsigned int rotation) +{ + bool linear_format = !mod_present || + (mod_present && modifier == DRM_FORMAT_MOD_LINEAR); + u32 supported_rotation = DRM_MODE_ROTATE_0; + + if (!format->is_yuv && linear_format) + supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | + DRM_MODE_REFLECT_MASK; + else if (!format->is_yuv && + modifier == DRM_FORMAT_MOD_VIVANTE_TILED) + supported_rotation = DRM_MODE_ROTATE_MASK | + DRM_MODE_REFLECT_MASK; + else if (format->is_yuv && linear_format && + (format->format == DRM_FORMAT_NV12 || + format->format == DRM_FORMAT_NV21)) + supported_rotation = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 | + DRM_MODE_REFLECT_MASK; + + return !!(rotation & supported_rotation); +} + +static bool dcss_plane_is_source_size_allowed(u16 src_w, u16 src_h, u32 pix_fmt) +{ + if (src_w < 64 && + (pix_fmt == DRM_FORMAT_NV12 || pix_fmt == DRM_FORMAT_NV21)) + return false; + else if (src_w < 32 && + (pix_fmt == DRM_FORMAT_UYVY || pix_fmt == DRM_FORMAT_VYUY || + pix_fmt == DRM_FORMAT_YUYV || pix_fmt == DRM_FORMAT_YVYU)) + return false; + + return src_w >= 16 && src_h >= 8; +} + +static int dcss_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct dcss_plane *dcss_plane = to_dcss_plane(plane); + struct dcss_dev *dcss = plane->dev->dev_private; + struct drm_framebuffer *fb = state->fb; + bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY; + struct drm_gem_cma_object *cma_obj; + struct drm_crtc_state *crtc_state; + int hdisplay, vdisplay; + int min, max; + int ret; + + if (!fb || !state->crtc) + return 0; + + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + WARN_ON(!cma_obj); + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + + hdisplay = crtc_state->adjusted_mode.hdisplay; + vdisplay = crtc_state->adjusted_mode.vdisplay; + + if (!dcss_plane_is_source_size_allowed(state->src_w >> 16, + state->src_h >> 16, + fb->format->format)) { + DRM_DEBUG_KMS("Source plane size is not allowed!\n"); + return -EINVAL; + } + + dcss_scaler_get_min_max_ratios(dcss->scaler, dcss_plane->ch_num, + &min, &max); + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, + min, max, !is_primary_plane, + false); + if (ret) + return ret; + + if (!state->visible) + return 0; + + if (!dcss_plane_can_rotate(fb->format, + !!(fb->flags & DRM_MODE_FB_MODIFIERS), + fb->modifier, + state->rotation)) { + DRM_DEBUG_KMS("requested rotation is not allowed!\n"); + return -EINVAL; + } + + if ((state->crtc_x < 0 || state->crtc_y < 0 || + state->crtc_x + state->crtc_w > hdisplay || + state->crtc_y + state->crtc_h > vdisplay) && + !dcss_plane_fb_is_linear(fb)) { + DRM_DEBUG_KMS("requested cropping operation is not allowed!\n"); + return -EINVAL; + } + + if ((fb->flags & DRM_MODE_FB_MODIFIERS) && + !plane->funcs->format_mod_supported(plane, + fb->format->format, + fb->modifier)) { + DRM_DEBUG_KMS("Invalid modifier: %llx", fb->modifier); + return -EINVAL; + } + + return 0; +} + +static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane) +{ + struct drm_plane *plane = &dcss_plane->base; + struct drm_plane_state *state = plane->state; + struct dcss_dev *dcss = plane->dev->dev_private; + struct drm_framebuffer *fb = state->fb; + const struct drm_format_info *format = fb->format; + struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + unsigned long p1_ba = 0, p2_ba = 0; + + if (!format->is_yuv || + format->format == DRM_FORMAT_NV12 || + format->format == DRM_FORMAT_NV21) + p1_ba = cma_obj->paddr + fb->offsets[0] + + fb->pitches[0] * (state->src.y1 >> 16) + + format->char_per_block[0] * (state->src.x1 >> 16); + else if (format->format == DRM_FORMAT_UYVY || + format->format == DRM_FORMAT_VYUY || + format->format == DRM_FORMAT_YUYV || + format->format == DRM_FORMAT_YVYU) + p1_ba = cma_obj->paddr + fb->offsets[0] + + fb->pitches[0] * (state->src.y1 >> 16) + + 2 * format->char_per_block[0] * (state->src.x1 >> 17); + + if (format->format == DRM_FORMAT_NV12 || + format->format == DRM_FORMAT_NV21) + p2_ba = cma_obj->paddr + fb->offsets[1] + + (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) + + (state->src.x1 >> 17)) << 1); + + dcss_dpr_addr_set(dcss->dpr, dcss_plane->ch_num, p1_ba, p2_ba, + fb->pitches[0]); +} + +static bool dcss_plane_needs_setup(struct drm_plane_state *state, + struct drm_plane_state *old_state) +{ + struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *old_fb = old_state->fb; + + return state->crtc_x != old_state->crtc_x || + state->crtc_y != old_state->crtc_y || + state->crtc_w != old_state->crtc_w || + state->crtc_h != old_state->crtc_h || + state->src_x != old_state->src_x || + state->src_y != old_state->src_y || + state->src_w != old_state->src_w || + state->src_h != old_state->src_h || + fb->format->format != old_fb->format->format || + fb->modifier != old_fb->modifier || + state->rotation != old_state->rotation; +} + +static void dcss_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = plane->state; + struct dcss_plane *dcss_plane = to_dcss_plane(plane); + struct dcss_dev *dcss = plane->dev->dev_private; + struct drm_framebuffer *fb = state->fb; + u32 pixel_format; + struct drm_crtc_state *crtc_state; + bool modifiers_present; + u32 src_w, src_h, dst_w, dst_h; + struct drm_rect src, dst; + bool enable = true; + + if (!fb || !state->crtc || !state->visible) + return; + + pixel_format = state->fb->format->format; + crtc_state = state->crtc->state; + modifiers_present = !!(fb->flags & DRM_MODE_FB_MODIFIERS); + + if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state) && + !dcss_plane_needs_setup(state, old_state)) { + dcss_plane_atomic_set_base(dcss_plane); + return; + } + + src = plane->state->src; + dst = plane->state->dst; + + /* + * The width and height after clipping. + */ + src_w = drm_rect_width(&src) >> 16; + src_h = drm_rect_height(&src) >> 16; + dst_w = drm_rect_width(&dst); + dst_h = drm_rect_height(&dst); + + if (plane->type == DRM_PLANE_TYPE_OVERLAY && + modifiers_present && fb->modifier == DRM_FORMAT_MOD_LINEAR) + modifiers_present = false; + + dcss_dpr_format_set(dcss->dpr, dcss_plane->ch_num, state->fb->format, + modifiers_present ? fb->modifier : + DRM_FORMAT_MOD_LINEAR); + dcss_dpr_set_res(dcss->dpr, dcss_plane->ch_num, src_w, src_h); + dcss_dpr_set_rotation(dcss->dpr, dcss_plane->ch_num, + state->rotation); + + dcss_plane_atomic_set_base(dcss_plane); + + dcss_scaler_setup(dcss->scaler, dcss_plane->ch_num, + state->fb->format, src_w, src_h, + dst_w, dst_h, + drm_mode_vrefresh(&crtc_state->mode)); + + dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, + dst.x1, dst.y1, dst_w, dst_h); + dcss_dtg_plane_alpha_set(dcss->dtg, dcss_plane->ch_num, + fb->format, state->alpha >> 8); + + if (!dcss_plane->ch_num && (state->alpha >> 8) == 0) + enable = false; + + dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, enable); + dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, enable); + + if (!enable) + dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, + 0, 0, 0, 0); + + dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, enable); +} + +static void dcss_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct dcss_plane *dcss_plane = to_dcss_plane(plane); + struct dcss_dev *dcss = plane->dev->dev_private; + + dcss_dpr_enable(dcss->dpr, dcss_plane->ch_num, false); + dcss_scaler_ch_enable(dcss->scaler, dcss_plane->ch_num, false); + dcss_dtg_plane_pos_set(dcss->dtg, dcss_plane->ch_num, 0, 0, 0, 0); + dcss_dtg_ch_enable(dcss->dtg, dcss_plane->ch_num, false); +} + +static const struct drm_plane_helper_funcs dcss_plane_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, + .atomic_check = dcss_plane_atomic_check, + .atomic_update = dcss_plane_atomic_update, + .atomic_disable = dcss_plane_atomic_disable, +}; + +struct dcss_plane *dcss_plane_init(struct drm_device *drm, + unsigned int possible_crtcs, + enum drm_plane_type type, + unsigned int zpos) +{ + struct dcss_plane *dcss_plane; + const u64 *format_modifiers = dcss_video_format_modifiers; + int ret; + + if (zpos > 2) + return ERR_PTR(-EINVAL); + + dcss_plane = kzalloc(sizeof(*dcss_plane), GFP_KERNEL); + if (!dcss_plane) { + DRM_ERROR("failed to allocate plane\n"); + return ERR_PTR(-ENOMEM); + } + + if (type == DRM_PLANE_TYPE_PRIMARY) + format_modifiers = dcss_graphics_format_modifiers; + + ret = drm_universal_plane_init(drm, &dcss_plane->base, possible_crtcs, + &dcss_plane_funcs, dcss_common_formats, + ARRAY_SIZE(dcss_common_formats), + format_modifiers, type, NULL); + if (ret) { + DRM_ERROR("failed to initialize plane\n"); + kfree(dcss_plane); + return ERR_PTR(ret); + } + + drm_plane_helper_add(&dcss_plane->base, &dcss_plane_helper_funcs); + + ret = drm_plane_create_zpos_immutable_property(&dcss_plane->base, zpos); + if (ret) + return ERR_PTR(ret); + + drm_plane_create_rotation_property(&dcss_plane->base, + DRM_MODE_ROTATE_0, + DRM_MODE_ROTATE_0 | + DRM_MODE_ROTATE_90 | + DRM_MODE_ROTATE_180 | + DRM_MODE_ROTATE_270 | + DRM_MODE_REFLECT_X | + DRM_MODE_REFLECT_Y); + + dcss_plane->ch_num = zpos; + + return dcss_plane; +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-scaler.c b/drivers/gpu/drm/imx/dcss/dcss-scaler.c new file mode 100644 index 0000000000000..cd21905de580f --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-scaler.c @@ -0,0 +1,826 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + * + * Scaling algorithms were contributed by Dzung Hoang <dzung.hoang@nxp.com> + */ + +#include <linux/device.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_SCALER_CTRL 0x00 +#define SCALER_EN BIT(0) +#define REPEAT_EN BIT(4) +#define SCALE2MEM_EN BIT(8) +#define MEM2OFIFO_EN BIT(12) +#define DCSS_SCALER_OFIFO_CTRL 0x04 +#define OFIFO_LOW_THRES_POS 0 +#define OFIFO_LOW_THRES_MASK GENMASK(9, 0) +#define OFIFO_HIGH_THRES_POS 16 +#define OFIFO_HIGH_THRES_MASK GENMASK(25, 16) +#define UNDERRUN_DETECT_CLR BIT(26) +#define LOW_THRES_DETECT_CLR BIT(27) +#define HIGH_THRES_DETECT_CLR BIT(28) +#define UNDERRUN_DETECT_EN BIT(29) +#define LOW_THRES_DETECT_EN BIT(30) +#define HIGH_THRES_DETECT_EN BIT(31) +#define DCSS_SCALER_SDATA_CTRL 0x08 +#define YUV_EN BIT(0) +#define RTRAM_8LINES BIT(1) +#define Y_UV_BYTE_SWAP BIT(4) +#define A2R10G10B10_FORMAT_POS 8 +#define A2R10G10B10_FORMAT_MASK GENMASK(11, 8) +#define DCSS_SCALER_BIT_DEPTH 0x0C +#define LUM_BIT_DEPTH_POS 0 +#define LUM_BIT_DEPTH_MASK GENMASK(1, 0) +#define CHR_BIT_DEPTH_POS 4 +#define CHR_BIT_DEPTH_MASK GENMASK(5, 4) +#define DCSS_SCALER_SRC_FORMAT 0x10 +#define DCSS_SCALER_DST_FORMAT 0x14 +#define FORMAT_MASK GENMASK(1, 0) +#define DCSS_SCALER_SRC_LUM_RES 0x18 +#define DCSS_SCALER_SRC_CHR_RES 0x1C +#define DCSS_SCALER_DST_LUM_RES 0x20 +#define DCSS_SCALER_DST_CHR_RES 0x24 +#define WIDTH_POS 0 +#define WIDTH_MASK GENMASK(11, 0) +#define HEIGHT_POS 16 +#define HEIGHT_MASK GENMASK(27, 16) +#define DCSS_SCALER_V_LUM_START 0x48 +#define V_START_MASK GENMASK(15, 0) +#define DCSS_SCALER_V_LUM_INC 0x4C +#define V_INC_MASK GENMASK(15, 0) +#define DCSS_SCALER_H_LUM_START 0x50 +#define H_START_MASK GENMASK(18, 0) +#define DCSS_SCALER_H_LUM_INC 0x54 +#define H_INC_MASK GENMASK(15, 0) +#define DCSS_SCALER_V_CHR_START 0x58 +#define DCSS_SCALER_V_CHR_INC 0x5C +#define DCSS_SCALER_H_CHR_START 0x60 +#define DCSS_SCALER_H_CHR_INC 0x64 +#define DCSS_SCALER_COEF_VLUM 0x80 +#define DCSS_SCALER_COEF_HLUM 0x140 +#define DCSS_SCALER_COEF_VCHR 0x200 +#define DCSS_SCALER_COEF_HCHR 0x300 + +struct dcss_scaler_ch { + void __iomem *base_reg; + u32 base_ofs; + struct dcss_scaler *scl; + + u32 sdata_ctrl; + u32 scaler_ctrl; + + bool scaler_ctrl_chgd; + + u32 c_vstart; + u32 c_hstart; +}; + +struct dcss_scaler { + struct device *dev; + + struct dcss_ctxld *ctxld; + u32 ctx_id; + + struct dcss_scaler_ch ch[3]; +}; + +/* scaler coefficients generator */ +#define PSC_FRAC_BITS 30 +#define PSC_FRAC_SCALE BIT(PSC_FRAC_BITS) +#define PSC_BITS_FOR_PHASE 4 +#define PSC_NUM_PHASES 16 +#define PSC_STORED_PHASES (PSC_NUM_PHASES / 2 + 1) +#define PSC_NUM_TAPS 7 +#define PSC_NUM_TAPS_RGBA 5 +#define PSC_COEFF_PRECISION 10 +#define PSC_PHASE_FRACTION_BITS 13 +#define PSC_PHASE_MASK (PSC_NUM_PHASES - 1) +#define PSC_Q_FRACTION 19 +#define PSC_Q_ROUND_OFFSET (1 << (PSC_Q_FRACTION - 1)) + +/** + * mult_q() - Performs fixed-point multiplication. + * @A: multiplier + * @B: multiplicand + */ +static int mult_q(int A, int B) +{ + int result; + s64 temp; + + temp = (int64_t)A * (int64_t)B; + temp += PSC_Q_ROUND_OFFSET; + result = (int)(temp >> PSC_Q_FRACTION); + return result; +} + +/** + * div_q() - Performs fixed-point division. + * @A: dividend + * @B: divisor + */ +static int div_q(int A, int B) +{ + int result; + s64 temp; + + temp = (int64_t)A << PSC_Q_FRACTION; + if ((temp >= 0 && B >= 0) || (temp < 0 && B < 0)) + temp += B / 2; + else + temp -= B / 2; + + result = (int)(temp / B); + return result; +} + +/** + * exp_approx_q() - Compute approximation to exp(x) function using Taylor + * series. + * @x: fixed-point argument of exp function + */ +static int exp_approx_q(int x) +{ + int sum = 1 << PSC_Q_FRACTION; + int term = 1 << PSC_Q_FRACTION; + + term = mult_q(term, div_q(x, 1 << PSC_Q_FRACTION)); + sum += term; + term = mult_q(term, div_q(x, 2 << PSC_Q_FRACTION)); + sum += term; + term = mult_q(term, div_q(x, 3 << PSC_Q_FRACTION)); + sum += term; + term = mult_q(term, div_q(x, 4 << PSC_Q_FRACTION)); + sum += term; + + return sum; +} + +/** + * dcss_scaler_gaussian_filter() - Generate gaussian prototype filter. + * @fc_q: fixed-point cutoff frequency normalized to range [0, 1] + * @use_5_taps: indicates whether to use 5 taps or 7 taps + * @coef: output filter coefficients + */ +static void dcss_scaler_gaussian_filter(int fc_q, bool use_5_taps, + bool phase0_identity, + int coef[][PSC_NUM_TAPS]) +{ + int sigma_q, g0_q, g1_q, g2_q; + int tap_cnt1, tap_cnt2, tap_idx, phase_cnt; + int mid; + int phase; + int i; + int taps; + + if (use_5_taps) + for (phase = 0; phase < PSC_STORED_PHASES; phase++) { + coef[phase][0] = 0; + coef[phase][PSC_NUM_TAPS - 1] = 0; + } + + /* seed coefficient scanner */ + taps = use_5_taps ? PSC_NUM_TAPS_RGBA : PSC_NUM_TAPS; + mid = (PSC_NUM_PHASES * taps) / 2 - 1; + phase_cnt = (PSC_NUM_PHASES * (PSC_NUM_TAPS + 1)) / 2; + tap_cnt1 = (PSC_NUM_PHASES * PSC_NUM_TAPS) / 2; + tap_cnt2 = (PSC_NUM_PHASES * PSC_NUM_TAPS) / 2; + + /* seed gaussian filter generator */ + sigma_q = div_q(PSC_Q_ROUND_OFFSET, fc_q); + g0_q = 1 << PSC_Q_FRACTION; + g1_q = exp_approx_q(div_q(-PSC_Q_ROUND_OFFSET, + mult_q(sigma_q, sigma_q))); + g2_q = mult_q(g1_q, g1_q); + coef[phase_cnt & PSC_PHASE_MASK][tap_cnt1 >> PSC_BITS_FOR_PHASE] = g0_q; + + for (i = 0; i < mid; i++) { + phase_cnt++; + tap_cnt1--; + tap_cnt2++; + + g0_q = mult_q(g0_q, g1_q); + g1_q = mult_q(g1_q, g2_q); + + if ((phase_cnt & PSC_PHASE_MASK) <= 8) { + tap_idx = tap_cnt1 >> PSC_BITS_FOR_PHASE; + coef[phase_cnt & PSC_PHASE_MASK][tap_idx] = g0_q; + } + if (((-phase_cnt) & PSC_PHASE_MASK) <= 8) { + tap_idx = tap_cnt2 >> PSC_BITS_FOR_PHASE; + coef[(-phase_cnt) & PSC_PHASE_MASK][tap_idx] = g0_q; + } + } + + phase_cnt++; + tap_cnt1--; + coef[phase_cnt & PSC_PHASE_MASK][tap_cnt1 >> PSC_BITS_FOR_PHASE] = 0; + + /* override phase 0 with identity filter if specified */ + if (phase0_identity) + for (i = 0; i < PSC_NUM_TAPS; i++) + coef[0][i] = i == (PSC_NUM_TAPS >> 1) ? + (1 << PSC_COEFF_PRECISION) : 0; + + /* normalize coef */ + for (phase = 0; phase < PSC_STORED_PHASES; phase++) { + int sum = 0; + s64 ll_temp; + + for (i = 0; i < PSC_NUM_TAPS; i++) + sum += coef[phase][i]; + for (i = 0; i < PSC_NUM_TAPS; i++) { + ll_temp = coef[phase][i]; + ll_temp <<= PSC_COEFF_PRECISION; + ll_temp += sum >> 1; + ll_temp /= sum; + coef[phase][i] = (int)ll_temp; + } + } +} + +/** + * dcss_scaler_filter_design() - Compute filter coefficients using + * Gaussian filter. + * @src_length: length of input + * @dst_length: length of output + * @use_5_taps: 0 for 7 taps per phase, 1 for 5 taps + * @coef: output coefficients + */ +static void dcss_scaler_filter_design(int src_length, int dst_length, + bool use_5_taps, bool phase0_identity, + int coef[][PSC_NUM_TAPS]) +{ + int fc_q; + + /* compute cutoff frequency */ + if (dst_length >= src_length) + fc_q = div_q(1, PSC_NUM_PHASES); + else + fc_q = div_q(dst_length, src_length * PSC_NUM_PHASES); + + /* compute gaussian filter coefficients */ + dcss_scaler_gaussian_filter(fc_q, use_5_taps, phase0_identity, coef); +} + +static void dcss_scaler_write(struct dcss_scaler_ch *ch, u32 val, u32 ofs) +{ + struct dcss_scaler *scl = ch->scl; + + dcss_ctxld_write(scl->ctxld, scl->ctx_id, val, ch->base_ofs + ofs); +} + +static int dcss_scaler_ch_init_all(struct dcss_scaler *scl, + unsigned long scaler_base) +{ + struct dcss_scaler_ch *ch; + int i; + + for (i = 0; i < 3; i++) { + ch = &scl->ch[i]; + + ch->base_ofs = scaler_base + i * 0x400; + + ch->base_reg = ioremap(ch->base_ofs, SZ_4K); + if (!ch->base_reg) { + dev_err(scl->dev, "scaler: unable to remap ch base\n"); + return -ENOMEM; + } + + ch->scl = scl; + } + + return 0; +} + +int dcss_scaler_init(struct dcss_dev *dcss, unsigned long scaler_base) +{ + struct dcss_scaler *scaler; + + scaler = kzalloc(sizeof(*scaler), GFP_KERNEL); + if (!scaler) + return -ENOMEM; + + dcss->scaler = scaler; + scaler->dev = dcss->dev; + scaler->ctxld = dcss->ctxld; + scaler->ctx_id = CTX_SB_HP; + + if (dcss_scaler_ch_init_all(scaler, scaler_base)) { + int i; + + for (i = 0; i < 3; i++) { + if (scaler->ch[i].base_reg) + iounmap(scaler->ch[i].base_reg); + } + + kfree(scaler); + + return -ENOMEM; + } + + return 0; +} + +void dcss_scaler_exit(struct dcss_scaler *scl) +{ + int ch_no; + + for (ch_no = 0; ch_no < 3; ch_no++) { + struct dcss_scaler_ch *ch = &scl->ch[ch_no]; + + dcss_writel(0, ch->base_reg + DCSS_SCALER_CTRL); + + if (ch->base_reg) + iounmap(ch->base_reg); + } + + kfree(scl); +} + +void dcss_scaler_ch_enable(struct dcss_scaler *scl, int ch_num, bool en) +{ + struct dcss_scaler_ch *ch = &scl->ch[ch_num]; + u32 scaler_ctrl; + + scaler_ctrl = en ? SCALER_EN | REPEAT_EN : 0; + + if (en) + dcss_scaler_write(ch, ch->sdata_ctrl, DCSS_SCALER_SDATA_CTRL); + + if (ch->scaler_ctrl != scaler_ctrl) + ch->scaler_ctrl_chgd = true; + + ch->scaler_ctrl = scaler_ctrl; +} + +static void dcss_scaler_yuv_enable(struct dcss_scaler_ch *ch, bool en) +{ + ch->sdata_ctrl &= ~YUV_EN; + ch->sdata_ctrl |= en ? YUV_EN : 0; +} + +static void dcss_scaler_rtr_8lines_enable(struct dcss_scaler_ch *ch, bool en) +{ + ch->sdata_ctrl &= ~RTRAM_8LINES; + ch->sdata_ctrl |= en ? RTRAM_8LINES : 0; +} + +static void dcss_scaler_bit_depth_set(struct dcss_scaler_ch *ch, int depth) +{ + u32 val; + + val = depth == 30 ? 2 : 0; + + dcss_scaler_write(ch, + ((val << CHR_BIT_DEPTH_POS) & CHR_BIT_DEPTH_MASK) | + ((val << LUM_BIT_DEPTH_POS) & LUM_BIT_DEPTH_MASK), + DCSS_SCALER_BIT_DEPTH); +} + +enum buffer_format { + BUF_FMT_YUV420, + BUF_FMT_YUV422, + BUF_FMT_ARGB8888_YUV444, +}; + +enum chroma_location { + PSC_LOC_HORZ_0_VERT_1_OVER_4 = 0, + PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_4 = 1, + PSC_LOC_HORZ_0_VERT_0 = 2, + PSC_LOC_HORZ_1_OVER_4_VERT_0 = 3, + PSC_LOC_HORZ_0_VERT_1_OVER_2 = 4, + PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_2 = 5 +}; + +static void dcss_scaler_format_set(struct dcss_scaler_ch *ch, + enum buffer_format src_fmt, + enum buffer_format dst_fmt) +{ + dcss_scaler_write(ch, src_fmt, DCSS_SCALER_SRC_FORMAT); + dcss_scaler_write(ch, dst_fmt, DCSS_SCALER_DST_FORMAT); +} + +static void dcss_scaler_res_set(struct dcss_scaler_ch *ch, + int src_xres, int src_yres, + int dst_xres, int dst_yres, + u32 pix_format, enum buffer_format dst_format) +{ + u32 lsrc_xres, lsrc_yres, csrc_xres, csrc_yres; + u32 ldst_xres, ldst_yres, cdst_xres, cdst_yres; + bool src_is_444 = true; + + lsrc_xres = src_xres; + csrc_xres = src_xres; + lsrc_yres = src_yres; + csrc_yres = src_yres; + ldst_xres = dst_xres; + cdst_xres = dst_xres; + ldst_yres = dst_yres; + cdst_yres = dst_yres; + + if (pix_format == DRM_FORMAT_UYVY || pix_format == DRM_FORMAT_VYUY || + pix_format == DRM_FORMAT_YUYV || pix_format == DRM_FORMAT_YVYU) { + csrc_xres >>= 1; + src_is_444 = false; + } else if (pix_format == DRM_FORMAT_NV12 || + pix_format == DRM_FORMAT_NV21) { + csrc_xres >>= 1; + csrc_yres >>= 1; + src_is_444 = false; + } + + if (dst_format == BUF_FMT_YUV422) + cdst_xres >>= 1; + + /* for 4:4:4 to 4:2:2 conversion, source height should be 1 less */ + if (src_is_444 && dst_format == BUF_FMT_YUV422) { + lsrc_yres--; + csrc_yres--; + } + + dcss_scaler_write(ch, (((lsrc_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | + (((lsrc_xres - 1) << WIDTH_POS) & WIDTH_MASK), + DCSS_SCALER_SRC_LUM_RES); + dcss_scaler_write(ch, (((csrc_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | + (((csrc_xres - 1) << WIDTH_POS) & WIDTH_MASK), + DCSS_SCALER_SRC_CHR_RES); + dcss_scaler_write(ch, (((ldst_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | + (((ldst_xres - 1) << WIDTH_POS) & WIDTH_MASK), + DCSS_SCALER_DST_LUM_RES); + dcss_scaler_write(ch, (((cdst_yres - 1) << HEIGHT_POS) & HEIGHT_MASK) | + (((cdst_xres - 1) << WIDTH_POS) & WIDTH_MASK), + DCSS_SCALER_DST_CHR_RES); +} + +#define downscale_fp(factor, fp_pos) ((factor) << (fp_pos)) +#define upscale_fp(factor, fp_pos) ((1 << (fp_pos)) / (factor)) + +struct dcss_scaler_factors { + int downscale; + int upscale; +}; + +static const struct dcss_scaler_factors dcss_scaler_factors[] = { + {3, 8}, {5, 8}, {5, 8}, +}; + +static void dcss_scaler_fractions_set(struct dcss_scaler_ch *ch, + int src_xres, int src_yres, + int dst_xres, int dst_yres, + u32 src_format, u32 dst_format, + enum chroma_location src_chroma_loc) +{ + int src_c_xres, src_c_yres, dst_c_xres, dst_c_yres; + u32 l_vinc, l_hinc, c_vinc, c_hinc; + u32 c_vstart, c_hstart; + + src_c_xres = src_xres; + src_c_yres = src_yres; + dst_c_xres = dst_xres; + dst_c_yres = dst_yres; + + c_vstart = 0; + c_hstart = 0; + + /* adjustments for source chroma location */ + if (src_format == BUF_FMT_YUV420) { + /* vertical input chroma position adjustment */ + switch (src_chroma_loc) { + case PSC_LOC_HORZ_0_VERT_1_OVER_4: + case PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_4: + /* + * move chroma up to first luma line + * (1/4 chroma input line spacing) + */ + c_vstart -= (1 << (PSC_PHASE_FRACTION_BITS - 2)); + break; + case PSC_LOC_HORZ_0_VERT_1_OVER_2: + case PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_2: + /* + * move chroma up to first luma line + * (1/2 chroma input line spacing) + */ + c_vstart -= (1 << (PSC_PHASE_FRACTION_BITS - 1)); + break; + default: + break; + } + /* horizontal input chroma position adjustment */ + switch (src_chroma_loc) { + case PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_4: + case PSC_LOC_HORZ_1_OVER_4_VERT_0: + case PSC_LOC_HORZ_1_OVER_4_VERT_1_OVER_2: + /* move chroma left 1/4 chroma input sample spacing */ + c_hstart -= (1 << (PSC_PHASE_FRACTION_BITS - 2)); + break; + default: + break; + } + } + + /* adjustments to chroma resolution */ + if (src_format == BUF_FMT_YUV420) { + src_c_xres >>= 1; + src_c_yres >>= 1; + } else if (src_format == BUF_FMT_YUV422) { + src_c_xres >>= 1; + } + + if (dst_format == BUF_FMT_YUV422) + dst_c_xres >>= 1; + + l_vinc = ((src_yres << 13) + (dst_yres >> 1)) / dst_yres; + c_vinc = ((src_c_yres << 13) + (dst_c_yres >> 1)) / dst_c_yres; + l_hinc = ((src_xres << 13) + (dst_xres >> 1)) / dst_xres; + c_hinc = ((src_c_xres << 13) + (dst_c_xres >> 1)) / dst_c_xres; + + /* save chroma start phase */ + ch->c_vstart = c_vstart; + ch->c_hstart = c_hstart; + + dcss_scaler_write(ch, 0, DCSS_SCALER_V_LUM_START); + dcss_scaler_write(ch, l_vinc, DCSS_SCALER_V_LUM_INC); + + dcss_scaler_write(ch, 0, DCSS_SCALER_H_LUM_START); + dcss_scaler_write(ch, l_hinc, DCSS_SCALER_H_LUM_INC); + + dcss_scaler_write(ch, c_vstart, DCSS_SCALER_V_CHR_START); + dcss_scaler_write(ch, c_vinc, DCSS_SCALER_V_CHR_INC); + + dcss_scaler_write(ch, c_hstart, DCSS_SCALER_H_CHR_START); + dcss_scaler_write(ch, c_hinc, DCSS_SCALER_H_CHR_INC); +} + +int dcss_scaler_get_min_max_ratios(struct dcss_scaler *scl, int ch_num, + int *min, int *max) +{ + *min = upscale_fp(dcss_scaler_factors[ch_num].upscale, 16); + *max = downscale_fp(dcss_scaler_factors[ch_num].downscale, 16); + + return 0; +} + +static void dcss_scaler_program_5_coef_set(struct dcss_scaler_ch *ch, + int base_addr, + int coef[][PSC_NUM_TAPS]) +{ + int i, phase; + + for (i = 0; i < PSC_STORED_PHASES; i++) { + dcss_scaler_write(ch, ((coef[i][1] & 0xfff) << 16 | + (coef[i][2] & 0xfff) << 4 | + (coef[i][3] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[i][3] & 0x0ff) << 20 | + (coef[i][4] & 0xfff) << 8 | + (coef[i][5] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[i][5] & 0x00f) << 24), + base_addr + 0x80 + i * sizeof(u32)); + } + + /* reverse both phase and tap orderings */ + for (phase = (PSC_NUM_PHASES >> 1) - 1; + i < PSC_NUM_PHASES; i++, phase--) { + dcss_scaler_write(ch, ((coef[phase][5] & 0xfff) << 16 | + (coef[phase][4] & 0xfff) << 4 | + (coef[phase][3] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[phase][3] & 0x0ff) << 20 | + (coef[phase][2] & 0xfff) << 8 | + (coef[phase][1] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[phase][1] & 0x00f) << 24), + base_addr + 0x80 + i * sizeof(u32)); + } +} + +static void dcss_scaler_program_7_coef_set(struct dcss_scaler_ch *ch, + int base_addr, + int coef[][PSC_NUM_TAPS]) +{ + int i, phase; + + for (i = 0; i < PSC_STORED_PHASES; i++) { + dcss_scaler_write(ch, ((coef[i][0] & 0xfff) << 16 | + (coef[i][1] & 0xfff) << 4 | + (coef[i][2] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[i][2] & 0x0ff) << 20 | + (coef[i][3] & 0xfff) << 8 | + (coef[i][4] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[i][4] & 0x00f) << 24 | + (coef[i][5] & 0xfff) << 12 | + (coef[i][6] & 0xfff)), + base_addr + 0x80 + i * sizeof(u32)); + } + + /* reverse both phase and tap orderings */ + for (phase = (PSC_NUM_PHASES >> 1) - 1; + i < PSC_NUM_PHASES; i++, phase--) { + dcss_scaler_write(ch, ((coef[phase][6] & 0xfff) << 16 | + (coef[phase][5] & 0xfff) << 4 | + (coef[phase][4] & 0xf00) >> 8), + base_addr + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[phase][4] & 0x0ff) << 20 | + (coef[phase][3] & 0xfff) << 8 | + (coef[phase][2] & 0xff0) >> 4), + base_addr + 0x40 + i * sizeof(u32)); + dcss_scaler_write(ch, ((coef[phase][2] & 0x00f) << 24 | + (coef[phase][1] & 0xfff) << 12 | + (coef[phase][0] & 0xfff)), + base_addr + 0x80 + i * sizeof(u32)); + } +} + +static void dcss_scaler_yuv_coef_set(struct dcss_scaler_ch *ch, + enum buffer_format src_format, + enum buffer_format dst_format, + bool use_5_taps, + int src_xres, int src_yres, int dst_xres, + int dst_yres) +{ + int coef[PSC_STORED_PHASES][PSC_NUM_TAPS]; + bool program_5_taps = use_5_taps || + (dst_format == BUF_FMT_YUV422 && + src_format == BUF_FMT_ARGB8888_YUV444); + + /* horizontal luma */ + dcss_scaler_filter_design(src_xres, dst_xres, false, + src_xres == dst_xres, coef); + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HLUM, coef); + + /* vertical luma */ + dcss_scaler_filter_design(src_yres, dst_yres, program_5_taps, + src_yres == dst_yres, coef); + + if (program_5_taps) + dcss_scaler_program_5_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); + else + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); + + /* adjust chroma resolution */ + if (src_format != BUF_FMT_ARGB8888_YUV444) + src_xres >>= 1; + if (src_format == BUF_FMT_YUV420) + src_yres >>= 1; + if (dst_format != BUF_FMT_ARGB8888_YUV444) + dst_xres >>= 1; + if (dst_format == BUF_FMT_YUV420) /* should not happen */ + dst_yres >>= 1; + + /* horizontal chroma */ + dcss_scaler_filter_design(src_xres, dst_xres, false, + (src_xres == dst_xres) && (ch->c_hstart == 0), + coef); + + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HCHR, coef); + + /* vertical chroma */ + dcss_scaler_filter_design(src_yres, dst_yres, program_5_taps, + (src_yres == dst_yres) && (ch->c_vstart == 0), + coef); + if (program_5_taps) + dcss_scaler_program_5_coef_set(ch, DCSS_SCALER_COEF_VCHR, coef); + else + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VCHR, coef); +} + +static void dcss_scaler_rgb_coef_set(struct dcss_scaler_ch *ch, + int src_xres, int src_yres, int dst_xres, + int dst_yres) +{ + int coef[PSC_STORED_PHASES][PSC_NUM_TAPS]; + + /* horizontal RGB */ + dcss_scaler_filter_design(src_xres, dst_xres, false, + src_xres == dst_xres, coef); + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_HLUM, coef); + + /* vertical RGB */ + dcss_scaler_filter_design(src_yres, dst_yres, false, + src_yres == dst_yres, coef); + dcss_scaler_program_7_coef_set(ch, DCSS_SCALER_COEF_VLUM, coef); +} + +static void dcss_scaler_set_rgb10_order(struct dcss_scaler_ch *ch, + const struct drm_format_info *format) +{ + u32 a2r10g10b10_format; + + if (format->is_yuv) + return; + + ch->sdata_ctrl &= ~A2R10G10B10_FORMAT_MASK; + + if (format->depth != 30) + return; + + switch (format->format) { + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XRGB2101010: + a2r10g10b10_format = 0; + break; + + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XBGR2101010: + a2r10g10b10_format = 5; + break; + + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_RGBX1010102: + a2r10g10b10_format = 6; + break; + + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_BGRX1010102: + a2r10g10b10_format = 11; + break; + + default: + a2r10g10b10_format = 0; + break; + } + + ch->sdata_ctrl |= a2r10g10b10_format << A2R10G10B10_FORMAT_POS; +} + +void dcss_scaler_setup(struct dcss_scaler *scl, int ch_num, + const struct drm_format_info *format, + int src_xres, int src_yres, int dst_xres, int dst_yres, + u32 vrefresh_hz) +{ + struct dcss_scaler_ch *ch = &scl->ch[ch_num]; + unsigned int pixel_depth = 0; + bool rtr_8line_en = false; + bool use_5_taps = false; + enum buffer_format src_format = BUF_FMT_ARGB8888_YUV444; + enum buffer_format dst_format = BUF_FMT_ARGB8888_YUV444; + u32 pix_format = format->format; + + if (format->is_yuv) { + dcss_scaler_yuv_enable(ch, true); + + if (pix_format == DRM_FORMAT_NV12 || + pix_format == DRM_FORMAT_NV21) { + rtr_8line_en = true; + src_format = BUF_FMT_YUV420; + } else if (pix_format == DRM_FORMAT_UYVY || + pix_format == DRM_FORMAT_VYUY || + pix_format == DRM_FORMAT_YUYV || + pix_format == DRM_FORMAT_YVYU) { + src_format = BUF_FMT_YUV422; + } + + use_5_taps = !rtr_8line_en; + } else { + dcss_scaler_yuv_enable(ch, false); + + pixel_depth = format->depth; + } + + dcss_scaler_fractions_set(ch, src_xres, src_yres, dst_xres, + dst_yres, src_format, dst_format, + PSC_LOC_HORZ_0_VERT_1_OVER_4); + + if (format->is_yuv) + dcss_scaler_yuv_coef_set(ch, src_format, dst_format, + use_5_taps, src_xres, src_yres, + dst_xres, dst_yres); + else + dcss_scaler_rgb_coef_set(ch, src_xres, src_yres, + dst_xres, dst_yres); + + dcss_scaler_rtr_8lines_enable(ch, rtr_8line_en); + dcss_scaler_bit_depth_set(ch, pixel_depth); + dcss_scaler_set_rgb10_order(ch, format); + dcss_scaler_format_set(ch, src_format, dst_format); + dcss_scaler_res_set(ch, src_xres, src_yres, dst_xres, dst_yres, + pix_format, dst_format); +} + +/* This function will be called from interrupt context. */ +void dcss_scaler_write_sclctrl(struct dcss_scaler *scl) +{ + int chnum; + + dcss_ctxld_assert_locked(scl->ctxld); + + for (chnum = 0; chnum < 3; chnum++) { + struct dcss_scaler_ch *ch = &scl->ch[chnum]; + + if (ch->scaler_ctrl_chgd) { + dcss_ctxld_write_irqsafe(scl->ctxld, scl->ctx_id, + ch->scaler_ctrl, + ch->base_ofs + + DCSS_SCALER_CTRL); + ch->scaler_ctrl_chgd = false; + } + } +} diff --git a/drivers/gpu/drm/imx/dcss/dcss-ss.c b/drivers/gpu/drm/imx/dcss/dcss-ss.c new file mode 100644 index 0000000000000..8ddf08da911b7 --- /dev/null +++ b/drivers/gpu/drm/imx/dcss/dcss-ss.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2019 NXP. + */ + +#include <linux/device.h> +#include <linux/slab.h> + +#include "dcss-dev.h" + +#define DCSS_SS_SYS_CTRL 0x00 +#define RUN_EN BIT(0) +#define DCSS_SS_DISPLAY 0x10 +#define LRC_X_POS 0 +#define LRC_X_MASK GENMASK(12, 0) +#define LRC_Y_POS 16 +#define LRC_Y_MASK GENMASK(28, 16) +#define DCSS_SS_HSYNC 0x20 +#define DCSS_SS_VSYNC 0x30 +#define SYNC_START_POS 0 +#define SYNC_START_MASK GENMASK(12, 0) +#define SYNC_END_POS 16 +#define SYNC_END_MASK GENMASK(28, 16) +#define SYNC_POL BIT(31) +#define DCSS_SS_DE_ULC 0x40 +#define ULC_X_POS 0 +#define ULC_X_MASK GENMASK(12, 0) +#define ULC_Y_POS 16 +#define ULC_Y_MASK GENMASK(28, 16) +#define ULC_POL BIT(31) +#define DCSS_SS_DE_LRC 0x50 +#define DCSS_SS_MODE 0x60 +#define PIPE_MODE_POS 0 +#define PIPE_MODE_MASK GENMASK(1, 0) +#define DCSS_SS_COEFF 0x70 +#define HORIZ_A_POS 0 +#define HORIZ_A_MASK GENMASK(3, 0) +#define HORIZ_B_POS 4 +#define HORIZ_B_MASK GENMASK(7, 4) +#define HORIZ_C_POS 8 +#define HORIZ_C_MASK GENMASK(11, 8) +#define HORIZ_H_NORM_POS 12 +#define HORIZ_H_NORM_MASK GENMASK(14, 12) +#define VERT_A_POS 16 +#define VERT_A_MASK GENMASK(19, 16) +#define VERT_B_POS 20 +#define VERT_B_MASK GENMASK(23, 20) +#define VERT_C_POS 24 +#define VERT_C_MASK GENMASK(27, 24) +#define VERT_H_NORM_POS 28 +#define VERT_H_NORM_MASK GENMASK(30, 28) +#define DCSS_SS_CLIP_CB 0x80 +#define DCSS_SS_CLIP_CR 0x90 +#define CLIP_MIN_POS 0 +#define CLIP_MIN_MASK GENMASK(9, 0) +#define CLIP_MAX_POS 0 +#define CLIP_MAX_MASK GENMASK(23, 16) +#define DCSS_SS_INTER_MODE 0xA0 +#define INT_EN BIT(0) +#define VSYNC_SHIFT BIT(1) + +struct dcss_ss { + struct device *dev; + void __iomem *base_reg; + u32 base_ofs; + + struct dcss_ctxld *ctxld; + u32 ctx_id; + + bool in_use; +}; + +static void dcss_ss_write(struct dcss_ss *ss, u32 val, u32 ofs) +{ + if (!ss->in_use) + dcss_writel(val, ss->base_reg + ofs); + + dcss_ctxld_write(ss->ctxld, ss->ctx_id, val, + ss->base_ofs + ofs); +} + +int dcss_ss_init(struct dcss_dev *dcss, unsigned long ss_base) +{ + struct dcss_ss *ss; + + ss = kzalloc(sizeof(*ss), GFP_KERNEL); + if (!ss) + return -ENOMEM; + + dcss->ss = ss; + ss->dev = dcss->dev; + ss->ctxld = dcss->ctxld; + + ss->base_reg = ioremap(ss_base, SZ_4K); + if (!ss->base_reg) { + dev_err(dcss->dev, "ss: unable to remap ss base\n"); + kfree(ss); + return -ENOMEM; + } + + ss->base_ofs = ss_base; + ss->ctx_id = CTX_SB_HP; + + return 0; +} + +void dcss_ss_exit(struct dcss_ss *ss) +{ + /* stop SS */ + dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL); + + if (ss->base_reg) + iounmap(ss->base_reg); + + kfree(ss); +} + +void dcss_ss_subsam_set(struct dcss_ss *ss) +{ + dcss_ss_write(ss, 0x41614161, DCSS_SS_COEFF); + dcss_ss_write(ss, 0, DCSS_SS_MODE); + dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CB); + dcss_ss_write(ss, 0x03ff0000, DCSS_SS_CLIP_CR); +} + +void dcss_ss_sync_set(struct dcss_ss *ss, struct videomode *vm, + bool phsync, bool pvsync) +{ + u16 lrc_x, lrc_y; + u16 hsync_start, hsync_end; + u16 vsync_start, vsync_end; + u16 de_ulc_x, de_ulc_y; + u16 de_lrc_x, de_lrc_y; + + lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len + + vm->hactive - 1; + lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len + + vm->vactive - 1; + + dcss_ss_write(ss, (lrc_y << LRC_Y_POS) | lrc_x, DCSS_SS_DISPLAY); + + hsync_start = vm->hfront_porch + vm->hback_porch + vm->hsync_len + + vm->hactive - 1; + hsync_end = vm->hsync_len - 1; + + dcss_ss_write(ss, (phsync ? SYNC_POL : 0) | + ((u32)hsync_end << SYNC_END_POS) | hsync_start, + DCSS_SS_HSYNC); + + vsync_start = vm->vfront_porch - 1; + vsync_end = vm->vfront_porch + vm->vsync_len - 1; + + dcss_ss_write(ss, (pvsync ? SYNC_POL : 0) | + ((u32)vsync_end << SYNC_END_POS) | vsync_start, + DCSS_SS_VSYNC); + + de_ulc_x = vm->hsync_len + vm->hback_porch - 1; + de_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch; + + dcss_ss_write(ss, SYNC_POL | ((u32)de_ulc_y << ULC_Y_POS) | de_ulc_x, + DCSS_SS_DE_ULC); + + de_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1; + de_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch + + vm->vactive - 1; + + dcss_ss_write(ss, (de_lrc_y << LRC_Y_POS) | de_lrc_x, DCSS_SS_DE_LRC); +} + +void dcss_ss_enable(struct dcss_ss *ss) +{ + dcss_ss_write(ss, RUN_EN, DCSS_SS_SYS_CTRL); + ss->in_use = true; +} + +void dcss_ss_shutoff(struct dcss_ss *ss) +{ + dcss_writel(0, ss->base_reg + DCSS_SS_SYS_CTRL); + ss->in_use = false; +} -- GitLab From e7033bdfd43b85281b63d281b4dad3b9119f4427 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Fri, 31 Jul 2020 11:18:31 +0300 Subject: [PATCH 0986/1494] drm/imx/dcss: use drm_bridge_connector API Make use of drm_bridge_connector API to have the connector initialized by the display controller. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200731081836.3048-4-laurentiu.palcu@oss.nxp.com --- drivers/gpu/drm/imx/dcss/dcss-dev.c | 17 +++++++++++++--- drivers/gpu/drm/imx/dcss/dcss-kms.c | 31 ++++++++++++++++++++++++----- drivers/gpu/drm/imx/dcss/dcss-kms.h | 1 + 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c index 83a4840435cfb..c849533ca83e3 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-dev.c +++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c @@ -8,9 +8,12 @@ #include <linux/of_graph.h> #include <linux/pm_runtime.h> #include <linux/slab.h> +#include <drm/drm_bridge_connector.h> +#include <drm/drm_device.h> #include <drm/drm_modeset_helper.h> #include "dcss-dev.h" +#include "dcss-kms.h" static void dcss_clocks_enable(struct dcss_dev *dcss) { @@ -247,9 +250,13 @@ void dcss_dev_destroy(struct dcss_dev *dcss) int dcss_dev_suspend(struct device *dev) { struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + struct drm_device *ddev = dcss_drv_dev_to_drm(dev); + struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base); int ret; - drm_mode_config_helper_suspend(dcss_drv_dev_to_drm(dev)); + drm_bridge_connector_disable_hpd(kms->connector); + + drm_mode_config_helper_suspend(ddev); if (pm_runtime_suspended(dev)) return 0; @@ -266,9 +273,11 @@ int dcss_dev_suspend(struct device *dev) int dcss_dev_resume(struct device *dev) { struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dev); + struct drm_device *ddev = dcss_drv_dev_to_drm(dev); + struct dcss_kms_dev *kms = container_of(ddev, struct dcss_kms_dev, base); if (pm_runtime_suspended(dev)) { - drm_mode_config_helper_resume(dcss_drv_dev_to_drm(dev)); + drm_mode_config_helper_resume(ddev); return 0; } @@ -278,7 +287,9 @@ int dcss_dev_resume(struct device *dev) dcss_ctxld_resume(dcss->ctxld); - drm_mode_config_helper_resume(dcss_drv_dev_to_drm(dev)); + drm_mode_config_helper_resume(ddev); + + drm_bridge_connector_enable_hpd(kms->connector); return 0; } diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c index 3ca49d0a3e61f..135a62366ab8b 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.c +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c @@ -5,6 +5,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge_connector.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -74,7 +75,7 @@ static const struct drm_encoder_funcs dcss_kms_simple_encoder_funcs = { .destroy = drm_encoder_cleanup, }; -static int dcss_kms_setup_encoder(struct dcss_kms_dev *kms) +static int dcss_kms_bridge_connector_init(struct dcss_kms_dev *kms) { struct drm_device *ddev = &kms->base; struct drm_encoder *encoder = &kms->encoder; @@ -103,7 +104,23 @@ static int dcss_kms_setup_encoder(struct dcss_kms_dev *kms) return ret; } - return drm_bridge_attach(encoder, bridge, NULL, 0); + ret = drm_bridge_attach(encoder, bridge, NULL, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret < 0) { + dev_err(ddev->dev, "Unable to attach bridge %pOF\n", + bridge->of_node); + return ret; + } + + kms->connector = drm_bridge_connector_init(ddev, encoder); + if (IS_ERR(kms->connector)) { + dev_err(ddev->dev, "Unable to create bridge connector.\n"); + return PTR_ERR(kms->connector); + } + + drm_connector_attach_encoder(kms->connector, encoder); + + return 0; } struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) @@ -131,18 +148,20 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) drm->irq_enabled = true; - ret = dcss_crtc_init(crtc, drm); + ret = dcss_kms_bridge_connector_init(kms); if (ret) goto cleanup_mode_config; - ret = dcss_kms_setup_encoder(kms); + ret = dcss_crtc_init(crtc, drm); if (ret) - goto cleanup_crtc; + goto cleanup_mode_config; drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); + drm_bridge_connector_enable_hpd(kms->connector); + ret = drm_dev_register(drm, 0); if (ret) goto cleanup_crtc; @@ -152,6 +171,7 @@ struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss) return kms; cleanup_crtc: + drm_bridge_connector_disable_hpd(kms->connector); drm_kms_helper_poll_fini(drm); dcss_crtc_deinit(crtc, drm); @@ -167,6 +187,7 @@ void dcss_kms_detach(struct dcss_kms_dev *kms) struct drm_device *drm = &kms->base; drm_dev_unregister(drm); + drm_bridge_connector_disable_hpd(kms->connector); drm_kms_helper_poll_fini(drm); drm_atomic_helper_shutdown(drm); drm_crtc_vblank_off(&kms->crtc.base); diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.h b/drivers/gpu/drm/imx/dcss/dcss-kms.h index 1f51c86c69865..dfe5dd99eea3f 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-kms.h +++ b/drivers/gpu/drm/imx/dcss/dcss-kms.h @@ -29,6 +29,7 @@ struct dcss_kms_dev { struct drm_device base; struct dcss_crtc crtc; struct drm_encoder encoder; + struct drm_connector *connector; }; struct dcss_kms_dev *dcss_kms_attach(struct dcss_dev *dcss); -- GitLab From f61249dddecc6418285317bf5bc24b7cec84717e Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Fri, 31 Jul 2020 11:18:32 +0300 Subject: [PATCH 0987/1494] MAINTAINERS: Add entry for i.MX 8MQ DCSS driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver is part of DRM subsystem and is located in drivers/gpu/drm/imx/dcss. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> Reviewed-by: Guido Günther <agx@sigxcpu.org> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200731081836.3048-5-laurentiu.palcu@oss.nxp.com --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d4277824a01c8..557d79a5b9f13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12438,6 +12438,14 @@ F: drivers/iio/gyro/fxas21002c_core.c F: drivers/iio/gyro/fxas21002c_i2c.c F: drivers/iio/gyro/fxas21002c_spi.c +NXP i.MX 8MQ DCSS DRIVER +M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> +R: Lucas Stach <l.stach@pengutronix.de> +L: dri-devel@lists.freedesktop.org +S: Maintained +F: Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml +F: drivers/gpu/drm/imx/dcss/ + NXP SGTL5000 DRIVER M: Fabio Estevam <festevam@gmail.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) -- GitLab From 708ba1111525d84c7acc538c04bf190e3cda29b6 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@nxp.com> Date: Fri, 31 Jul 2020 11:18:33 +0300 Subject: [PATCH 0988/1494] dt-bindings: display: imx: add bindings for DCSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add bindings for iMX8MQ Display Controller Subsystem. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com> Reviewed-by: Guido Günther <agx@sigxcpu.org> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200731081836.3048-6-laurentiu.palcu@oss.nxp.com --- .../bindings/display/imx/nxp,imx8mq-dcss.yaml | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml diff --git a/Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml b/Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml new file mode 100644 index 0000000000000..f1f25aa794d93 --- /dev/null +++ b/Documentation/devicetree/bindings/display/imx/nxp,imx8mq-dcss.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 NXP +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/display/imx/nxp,imx8mq-dcss.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: iMX8MQ Display Controller Subsystem (DCSS) + +maintainers: + - Laurentiu Palcu <laurentiu.palcu@nxp.com> + +description: + + The DCSS (display controller sub system) is used to source up to three + display buffers, compose them, and drive a display using HDMI 2.0a(with HDCP + 2.2) or MIPI-DSI. The DCSS is intended to support up to 4kp60 displays. HDR10 + image processing capabilities are included to provide a solution capable of + driving next generation high dynamic range displays. + +properties: + compatible: + const: nxp,imx8mq-dcss + + reg: + items: + - description: DCSS base address and size, up to IRQ steer start + - description: DCSS BLKCTL base address and size + + interrupts: + items: + - description: Context loader completion and error interrupt + - description: DTG interrupt used to signal context loader trigger time + - description: DTG interrupt for Vblank + + interrupt-names: + items: + - const: ctxld + - const: ctxld_kick + - const: vblank + + clocks: + items: + - description: Display APB clock for all peripheral PIO access interfaces + - description: Display AXI clock needed by DPR, Scaler, RTRAM_CTRL + - description: RTRAM clock + - description: Pixel clock, can be driven either by HDMI phy clock or MIPI + - description: DTRC clock, needed by video decompressor + + clock-names: + items: + - const: apb + - const: axi + - const: rtrm + - const: pix + - const: dtrc + + assigned-clocks: + items: + - description: Phandle and clock specifier of IMX8MQ_CLK_DISP_AXI_ROOT + - description: Phandle and clock specifier of IMX8MQ_CLK_DISP_RTRM + - description: Phandle and clock specifier of either IMX8MQ_VIDEO2_PLL1_REF_SEL or + IMX8MQ_VIDEO_PLL1_REF_SEL + + assigned-clock-parents: + items: + - description: Phandle and clock specifier of IMX8MQ_SYS1_PLL_800M + - description: Phandle and clock specifier of IMX8MQ_SYS1_PLL_800M + - description: Phandle and clock specifier of IMX8MQ_CLK_27M + + assigned-clock-rates: + items: + - description: Must be 800 MHz + - description: Must be 400 MHz + + port: + type: object + description: + A port node pointing to the input port of a HDMI/DP or MIPI display bridge. + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imx8mq-clock.h> + dcss: display-controller@32e00000 { + compatible = "nxp,imx8mq-dcss"; + reg = <0x32e00000 0x2d000>, <0x32e2f000 0x1000>; + interrupts = <6>, <8>, <9>; + interrupt-names = "ctxld", "ctxld_kick", "vblank"; + interrupt-parent = <&irqsteer>; + clocks = <&clk IMX8MQ_CLK_DISP_APB_ROOT>, <&clk IMX8MQ_CLK_DISP_AXI_ROOT>, + <&clk IMX8MQ_CLK_DISP_RTRM_ROOT>, <&clk IMX8MQ_VIDEO2_PLL_OUT>, + <&clk IMX8MQ_CLK_DISP_DTRC>; + clock-names = "apb", "axi", "rtrm", "pix", "dtrc"; + assigned-clocks = <&clk IMX8MQ_CLK_DISP_AXI>, <&clk IMX8MQ_CLK_DISP_RTRM>, + <&clk IMX8MQ_VIDEO2_PLL1_REF_SEL>; + assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_800M>, <&clk IMX8MQ_SYS1_PLL_800M>, + <&clk IMX8MQ_CLK_27M>; + assigned-clock-rates = <800000000>, + <400000000>; + port { + dcss_out: endpoint { + remote-endpoint = <&hdmi_in>; + }; + }; + }; + -- GitLab From fd630ae9e27cfc2f6e3184b82288ba9ff9ff8bee Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 7 Sep 2020 09:41:41 -0700 Subject: [PATCH 0989/1494] drm/msm/dpu: move vblank events to complete_commit() We could get a vblank event racing with the current atomic commit, resulting in sending the pageflip event to userspace early, causing tearing. On the other hand, complete_commit() ensures that the pending flush is complete. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index c2729f71e2fa7..89c0245b5de50 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -297,7 +297,6 @@ void dpu_crtc_vblank_callback(struct drm_crtc *crtc) dpu_crtc->vblank_cb_time = ktime_get(); else dpu_crtc->vblank_cb_count++; - _dpu_crtc_complete_flip(crtc); drm_crtc_handle_vblank(crtc); trace_dpu_crtc_vblank_cb(DRMID(crtc)); } @@ -402,6 +401,7 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event) void dpu_crtc_complete_commit(struct drm_crtc *crtc) { trace_dpu_crtc_complete_commit(DRMID(crtc)); + _dpu_crtc_complete_flip(crtc); } static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, -- GitLab From e12e5263bf1d8dae2f1fd0a3163f88349404c277 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 7 Sep 2020 09:43:26 -0700 Subject: [PATCH 0990/1494] drm/msm/dpu: clean up some impossibilities Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 91 ++++-------------------- 1 file changed, 13 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 89c0245b5de50..999e3bfc7452f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -265,11 +265,6 @@ enum dpu_intf_mode dpu_crtc_get_intf_mode(struct drm_crtc *crtc) { struct drm_encoder *encoder; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return INTF_MODE_NONE; - } - /* * TODO: This function is called from dpu debugfs and as part of atomic * check. When called from debugfs, the crtc->mutex must be held to @@ -457,7 +452,6 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) struct dpu_crtc_mixer *mixer = cstate->mixers; struct dpu_hw_pcc_cfg cfg; struct dpu_hw_ctl *ctl; - struct dpu_hw_mixer *lm; struct dpu_hw_dspp *dspp; int i; @@ -467,7 +461,6 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) for (i = 0; i < cstate->num_mixers; i++) { ctl = mixer[i].lm_ctl; - lm = mixer[i].hw_lm; dspp = mixer[i].hw_dspp; if (!dspp || !dspp->ops.setup_pcc) @@ -496,16 +489,8 @@ static void _dpu_crtc_setup_cp_blocks(struct drm_crtc *crtc) static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { - struct dpu_crtc *dpu_crtc; - struct dpu_crtc_state *cstate; + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct drm_encoder *encoder; - struct drm_device *dev; - unsigned long flags; - - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return; - } if (!crtc->state->enable) { DPU_DEBUG("crtc%d -> enable %d, skip atomic_begin\n", @@ -515,21 +500,8 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc, DPU_DEBUG("crtc%d\n", crtc->base.id); - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(crtc->state); - dev = crtc->dev; - _dpu_crtc_setup_lm_bounds(crtc, crtc->state); - if (dpu_crtc->event) { - WARN_ON(dpu_crtc->event); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - dpu_crtc->event = crtc->state->event; - crtc->state->event = NULL; - spin_unlock_irqrestore(&dev->event_lock, flags); - } - /* encoder will trigger pending mask now */ drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) dpu_encoder_trigger_kickoff_pending(encoder); @@ -583,14 +555,11 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, return; } - if (dpu_crtc->event) { - DPU_DEBUG("already received dpu_crtc->event\n"); - } else { - spin_lock_irqsave(&dev->event_lock, flags); - dpu_crtc->event = crtc->state->event; - crtc->state->event = NULL; - spin_unlock_irqrestore(&dev->event_lock, flags); - } + WARN_ON(dpu_crtc->event); + spin_lock_irqsave(&dev->event_lock, flags); + dpu_crtc->event = crtc->state->event; + crtc->state->event = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); /* * If no mixers has been allocated in dpu_crtc_atomic_check(), @@ -635,14 +604,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, static void dpu_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct dpu_crtc_state *cstate; - - if (!crtc || !state) { - DPU_ERROR("invalid argument(s)\n"); - return; - } - - cstate = to_dpu_crtc_state(state); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); DPU_DEBUG("crtc%d\n", crtc->base.id); @@ -731,14 +693,8 @@ static void dpu_crtc_reset(struct drm_crtc *crtc) */ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) { - struct dpu_crtc_state *cstate, *old_cstate; + struct dpu_crtc_state *cstate, *old_cstate = to_dpu_crtc_state(crtc->state); - if (!crtc || !crtc->state) { - DPU_ERROR("invalid argument(s)\n"); - return NULL; - } - - old_cstate = to_dpu_crtc_state(crtc->state); cstate = kmemdup(old_cstate, sizeof(*old_cstate), GFP_KERNEL); if (!cstate) { DPU_ERROR("failed to allocate state\n"); @@ -754,19 +710,12 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc) static void dpu_crtc_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { - struct dpu_crtc *dpu_crtc; - struct dpu_crtc_state *cstate; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state); struct drm_encoder *encoder; unsigned long flags; bool release_bandwidth = false; - if (!crtc || !crtc->state) { - DPU_ERROR("invalid crtc\n"); - return; - } - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(crtc->state); - DRM_DEBUG_KMS("crtc%d\n", crtc->base.id); /* Disable/save vblank irq handling */ @@ -825,19 +774,13 @@ static void dpu_crtc_disable(struct drm_crtc *crtc, static void dpu_crtc_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { - struct dpu_crtc *dpu_crtc; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); struct drm_encoder *encoder; bool request_bandwidth = false; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return; - } - pm_runtime_get_sync(crtc->dev->dev); DRM_DEBUG_KMS("crtc%d\n", crtc->base.id); - dpu_crtc = to_dpu_crtc(crtc); drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) { /* in video mode, we hold an extra bandwidth reference @@ -873,9 +816,9 @@ struct plane_state { static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct dpu_crtc *dpu_crtc; + struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); + struct dpu_crtc_state *cstate = to_dpu_crtc_state(state); struct plane_state *pstates; - struct dpu_crtc_state *cstate; const struct drm_plane_state *pstate; struct drm_plane *plane; @@ -889,16 +832,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, int left_zpos_cnt = 0, right_zpos_cnt = 0; struct drm_rect crtc_rect = { 0 }; - if (!crtc) { - DPU_ERROR("invalid crtc\n"); - return -EINVAL; - } - pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL); - dpu_crtc = to_dpu_crtc(crtc); - cstate = to_dpu_crtc_state(state); - if (!state->enable || !state->active) { DPU_DEBUG("crtc%d -> enable %d, active %d, skip atomic_check\n", crtc->base.id, state->enable, state->active); -- GitLab From 22f760941844dbcee6ee446e1896532f6dff01ef Mon Sep 17 00:00:00 2001 From: Stephen Boyd <swboyd@chromium.org> Date: Tue, 1 Sep 2020 14:59:41 -0700 Subject: [PATCH 0991/1494] drm/msm: Avoid div-by-zero in dpu_crtc_atomic_check() The cstate->num_mixers member is only set to a non-zero value once dpu_encoder_virt_mode_set() is called, but the atomic check function can be called by userspace before that. Let's avoid the div-by-zero here and inside _dpu_crtc_setup_lm_bounds() by skipping this part of the atomic check if dpu_encoder_virt_mode_set() hasn't been called yet. This fixes an UBSAN warning: UBSAN: Undefined behaviour in drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:860:31 division by zero CPU: 7 PID: 409 Comm: frecon Tainted: G S 5.4.31 #128 Hardware name: Google Trogdor (rev0) (DT) Call trace: dump_backtrace+0x0/0x14c show_stack+0x20/0x2c dump_stack+0xa0/0xd8 __ubsan_handle_divrem_overflow+0xec/0x110 dpu_crtc_atomic_check+0x97c/0x9d4 drm_atomic_helper_check_planes+0x160/0x1c8 drm_atomic_helper_check+0x54/0xbc drm_atomic_check_only+0x6a8/0x880 drm_atomic_commit+0x20/0x5c drm_atomic_helper_set_config+0x98/0xa0 drm_mode_setcrtc+0x308/0x5dc drm_ioctl_kernel+0x9c/0x114 drm_ioctl+0x2ac/0x4b0 drm_compat_ioctl+0xe8/0x13c __arm64_compat_sys_ioctl+0x184/0x324 el0_svc_common+0xa4/0x154 el0_svc_compat_handler+0x Cc: Abhinav Kumar <abhinavk@codeaurora.org> Cc: Jeykumar Sankaran <jsanka@codeaurora.org> Cc: Jordan Crouse <jcrouse@codeaurora.org> Cc: Sean Paul <seanpaul@chromium.org> Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Signed-off-by: Stephen Boyd <swboyd@chromium.org> Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org> Tested-by: Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 999e3bfc7452f..3114a67dd7ac5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -824,7 +824,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, struct drm_plane *plane; struct drm_display_mode *mode; - int cnt = 0, rc = 0, mixer_width, i, z_pos; + int cnt = 0, rc = 0, mixer_width = 0, i, z_pos; struct dpu_multirect_plane_states multirect_plane[DPU_STAGE_MAX * 2]; int multirect_count = 0; @@ -849,9 +849,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc, memset(pipe_staged, 0, sizeof(pipe_staged)); - mixer_width = mode->hdisplay / cstate->num_mixers; + if (cstate->num_mixers) { + mixer_width = mode->hdisplay / cstate->num_mixers; - _dpu_crtc_setup_lm_bounds(crtc, state); + _dpu_crtc_setup_lm_bounds(crtc, state); + } crtc_rect.x2 = mode->hdisplay; crtc_rect.y2 = mode->vdisplay; -- GitLab From 38c2fa7ae2f25a561a33ac1d0680a92e293c65a5 Mon Sep 17 00:00:00 2001 From: Stephen Boyd <swboyd@chromium.org> Date: Tue, 1 Sep 2020 14:59:42 -0700 Subject: [PATCH 0992/1494] drm/msm: Drop debug print in _dpu_crtc_setup_lm_bounds() This function is called quite often if you have a blinking cursor on the screen, hello page flip. Let's drop this debug print here because it means enabling the print via the module parameter starts to spam the debug console. Cc: Abhinav Kumar <abhinavk@codeaurora.org> Cc: Jeykumar Sankaran <jsanka@codeaurora.org> Cc: Jordan Crouse <jcrouse@codeaurora.org> Cc: Sean Paul <seanpaul@chromium.org> Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") Signed-off-by: Stephen Boyd <swboyd@chromium.org> Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 3114a67dd7ac5..6169148b31700 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -416,8 +416,6 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc, trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r); } - - drm_mode_debug_printmodeline(adj_mode); } static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state, -- GitLab From 74c0a69cc5bee0eb1f1cf740f7480095c4a94fe7 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Tue, 1 Sep 2020 08:41:54 -0700 Subject: [PATCH 0993/1494] drm/msm/gpu: Add GPU freq_change traces Technically the GMU specific one is a bit redundant, but it was useful to track down a bug. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 3 +++ drivers/gpu/drm/msm/msm_gpu.c | 2 ++ drivers/gpu/drm/msm/msm_gpu_trace.h | 31 +++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 46a29e383bfd1..ab1e9eb619e04 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -11,6 +11,7 @@ #include "a6xx_gpu.h" #include "a6xx_gmu.xml.h" #include "msm_gem.h" +#include "msm_gpu_trace.h" #include "msm_mmu.h" static void a6xx_gmu_fault(struct a6xx_gmu *gmu) @@ -124,6 +125,8 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) gmu->current_perf_index = perf_index; gmu->freq = gmu->gpu_freqs[perf_index]; + trace_msm_gmu_freq_change(gmu->freq, perf_index); + /* * This can get called from devfreq while the hardware is idle. Don't * bring up the power if it isn't already active diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 57ddc9438351e..cec6ec1d3aa73 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -32,6 +32,8 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, if (IS_ERR(opp)) return PTR_ERR(opp); + trace_msm_gpu_freq_change(dev_pm_opp_get_freq(opp)); + if (gpu->funcs->gpu_set_freq) gpu->funcs->gpu_set_freq(gpu, opp); else diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index 122b847892388..07572ab179fa0 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -83,6 +83,37 @@ TRACE_EVENT(msm_gpu_submit_retired, __entry->start_ticks, __entry->end_ticks) ); + +TRACE_EVENT(msm_gpu_freq_change, + TP_PROTO(u32 freq), + TP_ARGS(freq), + TP_STRUCT__entry( + __field(u32, freq) + ), + TP_fast_assign( + /* trace freq in MHz to match intel_gpu_freq_change, to make life easier + * for userspace + */ + __entry->freq = DIV_ROUND_UP(freq, 1000000); + ), + TP_printk("new_freq=%u", __entry->freq) +); + + +TRACE_EVENT(msm_gmu_freq_change, + TP_PROTO(u32 freq, u32 perf_index), + TP_ARGS(freq, perf_index), + TP_STRUCT__entry( + __field(u32, freq) + __field(u32, perf_index) + ), + TP_fast_assign( + __entry->freq = freq; + __entry->perf_index = perf_index; + ), + TP_printk("freq=%u, perf_index=%u", __entry->freq, __entry->perf_index) +); + #endif #undef TRACE_INCLUDE_PATH -- GitLab From fdf38426cda6b5b3232f1fa470b5fa86734d7872 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Tue, 1 Sep 2020 08:41:55 -0700 Subject: [PATCH 0994/1494] drm/msm: Convert shrinker msgs to tracepoints This reduces the spam in dmesg when we start hitting the shrinker, and replaces it with something we can put on a timeline while profiling or debugging system issues. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> --- drivers/gpu/drm/msm/msm_gem_shrinker.c | 5 +++-- drivers/gpu/drm/msm/msm_gpu_trace.h | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 722d61668a970..482576d7a39a5 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -6,6 +6,7 @@ #include "msm_drv.h" #include "msm_gem.h" +#include "msm_gpu_trace.h" static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock) { @@ -87,7 +88,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) mutex_unlock(&dev->struct_mutex); if (freed > 0) - pr_info_ratelimited("Purging %lu bytes\n", freed << PAGE_SHIFT); + trace_msm_gem_purge(freed << PAGE_SHIFT); return freed; } @@ -123,7 +124,7 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr) *(unsigned long *)ptr += unmapped; if (unmapped > 0) - pr_info_ratelimited("Purging %u vmaps\n", unmapped); + trace_msm_gem_purge_vmaps(unmapped); return NOTIFY_DONE; } diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index 07572ab179fa0..1079fe5512798 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -114,6 +114,32 @@ TRACE_EVENT(msm_gmu_freq_change, TP_printk("freq=%u, perf_index=%u", __entry->freq, __entry->perf_index) ); + +TRACE_EVENT(msm_gem_purge, + TP_PROTO(u32 bytes), + TP_ARGS(bytes), + TP_STRUCT__entry( + __field(u32, bytes) + ), + TP_fast_assign( + __entry->bytes = bytes; + ), + TP_printk("Purging %u bytes", __entry->bytes) +); + + +TRACE_EVENT(msm_gem_purge_vmaps, + TP_PROTO(u32 unmapped), + TP_ARGS(unmapped), + TP_STRUCT__entry( + __field(u32, unmapped) + ), + TP_fast_assign( + __entry->unmapped = unmapped; + ), + TP_printk("Purging %u vmaps", __entry->unmapped) +); + #endif #undef TRACE_INCLUDE_PATH -- GitLab From 56d44649a7c207752be8907b801dd698b3451cad Mon Sep 17 00:00:00 2001 From: Yan Zhao <yan.y.zhao@intel.com> Date: Tue, 11 Aug 2020 14:09:44 +0800 Subject: [PATCH 0995/1494] drm/i915/gvt: rename F_IN_CTX flag to F_SR_IN_CTX F_IN_CTX is an inaccurate flag name, because people may wrongly think all MMIOs in context image are with this flag. But actually, this flag is only for MMIOs both in GVT's save-restore list and in hardare logical context's image. Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200811060944.3039-1-yan.y.zhao@intel.com --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 23 ++++++++++++++--------- drivers/gpu/drm/i915/gvt/mmio_context.c | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index f1940939260aa..018509eeb0fe2 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -976,7 +976,7 @@ static int cmd_reg_handler(struct parser_exec_state *s, * inhibit context will restore with correct values */ if (IS_GEN(s->engine->i915, 9) && - intel_gvt_mmio_is_in_ctx(gvt, offset) && + intel_gvt_mmio_is_sr_in_ctx(gvt, offset) && !strncmp(cmd, "lri", 3)) { intel_gvt_hypervisor_read_gpa(s->vgpu, s->workload->ring_context_gpa + 12, &ctx_sr_ctl, 4); diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index a4a6db6b7f908..899945b91cc6b 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -256,8 +256,10 @@ struct intel_gvt_mmio { #define F_CMD_ACCESSED (1 << 5) /* This reg could be accessed by unaligned address */ #define F_UNALIGN (1 << 6) -/* This reg is saved/restored in context */ -#define F_IN_CTX (1 << 7) +/* This reg is in GVT's mmio save-restor list and in hardware + * logical context image + */ +#define F_SR_IN_CTX (1 << 7) struct gvt_mmio_block *mmio_block; unsigned int num_mmio_block; @@ -645,30 +647,33 @@ static inline bool intel_gvt_mmio_has_mode_mask( } /** - * intel_gvt_mmio_is_in_ctx - check if a MMIO has in-ctx mask + * intel_gvt_mmio_is_sr_in_ctx - + * check if an MMIO has F_SR_IN_CTX mask * @gvt: a GVT device * @offset: register offset * * Returns: - * True if a MMIO has a in-context mask, false if it isn't. + * True if an MMIO has an F_SR_IN_CTX mask, false if it isn't. * */ -static inline bool intel_gvt_mmio_is_in_ctx( +static inline bool intel_gvt_mmio_is_sr_in_ctx( struct intel_gvt *gvt, unsigned int offset) { - return gvt->mmio.mmio_attribute[offset >> 2] & F_IN_CTX; + return gvt->mmio.mmio_attribute[offset >> 2] & F_SR_IN_CTX; } /** - * intel_gvt_mmio_set_in_ctx - mask a MMIO in logical context + * intel_gvt_mmio_set_sr_in_ctx - + * mask an MMIO in GVT's mmio save-restore list and also + * in hardware logical context image * @gvt: a GVT device * @offset: register offset * */ -static inline void intel_gvt_mmio_set_in_ctx( +static inline void intel_gvt_mmio_set_sr_in_ctx( struct intel_gvt *gvt, unsigned int offset) { - gvt->mmio.mmio_attribute[offset >> 2] |= F_IN_CTX; + gvt->mmio.mmio_attribute[offset >> 2] |= F_SR_IN_CTX; } void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu); diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 86a60bdf0818c..afe574d6b3b52 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -595,7 +595,7 @@ void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt) i915_mmio_reg_valid(mmio->reg); mmio++) { if (mmio->in_context) { gvt->engine_mmio_list.ctx_mmio_count[mmio->id]++; - intel_gvt_mmio_set_in_ctx(gvt, mmio->reg.reg); + intel_gvt_mmio_set_sr_in_ctx(gvt, mmio->reg.reg); } } } -- GitLab From a6c5817a38cfaddb3b5b4b3f2bc4b3750f264c57 Mon Sep 17 00:00:00 2001 From: Yan Zhao <yan.y.zhao@intel.com> Date: Tue, 11 Aug 2020 14:37:44 +0800 Subject: [PATCH 0996/1494] drm/i915/gvt: remove flag F_CMD_ACCESSED Flag F_CMD_ACCESSED is not used. just remove it. Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200811063744.3272-1-yan.y.zhao@intel.com --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 -- drivers/gpu/drm/i915/gvt/gvt.h | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 018509eeb0fe2..0292e3c1deb42 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -992,8 +992,6 @@ static int cmd_reg_handler(struct parser_exec_state *s, } } - /* TODO: Update the global mask if this MMIO is a masked-MMIO */ - intel_gvt_mmio_set_cmd_accessed(gvt, offset); return 0; } diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 899945b91cc6b..8fbe65471c011 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -253,8 +253,6 @@ struct intel_gvt_mmio { /* This reg has been accessed by a VM */ #define F_ACCESSED (1 << 4) /* This reg has been accessed through GPU commands */ -#define F_CMD_ACCESSED (1 << 5) -/* This reg could be accessed by unaligned address */ #define F_UNALIGN (1 << 6) /* This reg is in GVT's mmio save-restor list and in hardware * logical context image @@ -619,18 +617,6 @@ static inline bool intel_gvt_mmio_is_unalign( return gvt->mmio.mmio_attribute[offset >> 2] & F_UNALIGN; } -/** - * intel_gvt_mmio_set_cmd_accessed - mark a MMIO has been accessed by command - * @gvt: a GVT device - * @offset: register offset - * - */ -static inline void intel_gvt_mmio_set_cmd_accessed( - struct intel_gvt *gvt, unsigned int offset) -{ - gvt->mmio.mmio_attribute[offset >> 2] |= F_CMD_ACCESSED; -} - /** * intel_gvt_mmio_has_mode_mask - if a MMIO has a mode mask * @gvt: a GVT device -- GitLab From 7e93a0806f5a8b42c0a845a02816b6f80d406f79 Mon Sep 17 00:00:00 2001 From: Yan Zhao <yan.y.zhao@intel.com> Date: Tue, 11 Aug 2020 15:02:33 +0800 Subject: [PATCH 0997/1494] drm/i915/gvt: add/modify interfaces for flag F_CMD_ACCESS flag F_CMD_ACCESS represents whether an MMIO is able to be accessed by GPU commands. In this patch, 1. add interface to set this flag 2. rename intel_gvt_mmio_is_cmd_access() to intel_gvt_mmio_is_cmd_accessible() and update its description message. Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200811070233.3387-1-yan.y.zhao@intel.com --- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +- drivers/gpu/drm/i915/gvt/gvt.h | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0292e3c1deb42..affd05d2c2010 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -936,7 +936,7 @@ static int cmd_reg_handler(struct parser_exec_state *s, return -EFAULT; } - if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) { + if (!intel_gvt_mmio_is_cmd_accessible(gvt, offset)) { gvt_vgpu_err("%s access to non-render register (%x)\n", cmd, offset); return -EBADRQC; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 8fbe65471c011..d7279cd654ca0 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -594,17 +594,32 @@ static inline void intel_gvt_mmio_set_accessed( } /** - * intel_gvt_mmio_is_cmd_accessed - mark a MMIO could be accessed by command + * intel_gvt_mmio_is_cmd_accessible - if a MMIO could be accessed by command * @gvt: a GVT device * @offset: register offset * + * Returns: + * True if an MMIO is able to be accessed by GPU commands */ -static inline bool intel_gvt_mmio_is_cmd_access( +static inline bool intel_gvt_mmio_is_cmd_accessible( struct intel_gvt *gvt, unsigned int offset) { return gvt->mmio.mmio_attribute[offset >> 2] & F_CMD_ACCESS; } +/** + * intel_gvt_mmio_set_cmd_accessible - + * mark a MMIO could be accessible by command + * @gvt: a GVT device + * @offset: register offset + * + */ +static inline void intel_gvt_mmio_set_cmd_accessible( + struct intel_gvt *gvt, unsigned int offset) +{ + gvt->mmio.mmio_attribute[offset >> 2] |= F_CMD_ACCESS; +} + /** * intel_gvt_mmio_is_unalign - mark a MMIO could be accessed unaligned * @gvt: a GVT device -- GitLab From b2feabc6ebd39976b0085afd8205734dc3a9793b Mon Sep 17 00:00:00 2001 From: Yan Zhao <yan.y.zhao@intel.com> Date: Tue, 11 Aug 2020 15:27:20 +0800 Subject: [PATCH 0998/1494] drm/i915/gvt: remove F_CMD_ACCESS flag for some registers some registers cannot be cmd accessible. remove them from the list Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Wang Zhi <zhi.a.wang@intel.com> Signed-off-by: Yan Zhao <yan.y.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200811072720.3525-1-yan.y.zhao@intel.com --- drivers/gpu/drm/i915/gvt/handlers.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 63bba7b4bb2fb..d55cb43c9bd4a 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1892,7 +1892,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) struct drm_i915_private *dev_priv = gvt->gt->i915; int ret; - MMIO_RING_DFH(RING_IMR, D_ALL, F_CMD_ACCESS, NULL, + MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); @@ -1900,7 +1900,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler); MMIO_D(SDEISR, D_ALL); - MMIO_RING_DFH(RING_HWSTAM, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_RING_DFH(RING_HWSTAM, D_ALL, 0, NULL, NULL); + MMIO_DH(GEN8_GAMW_ECO_DEV_RW_IA, D_BDW_PLUS, NULL, gamw_echo_dev_rw_ia_write); @@ -1927,11 +1928,11 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_GM_RDR(_MMIO(0x12198), D_ALL, NULL, NULL); MMIO_D(GEN7_CXT_SIZE, D_ALL); - MMIO_RING_DFH(RING_TAIL, D_ALL, F_CMD_ACCESS, NULL, NULL); - MMIO_RING_DFH(RING_HEAD, D_ALL, F_CMD_ACCESS, NULL, NULL); - MMIO_RING_DFH(RING_CTL, D_ALL, F_CMD_ACCESS, NULL, NULL); - MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, mmio_read_from_hw, NULL); - MMIO_RING_GM_RDR(RING_START, D_ALL, NULL, NULL); + MMIO_RING_DFH(RING_TAIL, D_ALL, 0, NULL, NULL); + MMIO_RING_DFH(RING_HEAD, D_ALL, 0, NULL, NULL); + MMIO_RING_DFH(RING_CTL, D_ALL, 0, NULL, NULL); + MMIO_RING_DFH(RING_ACTHD, D_ALL, 0, mmio_read_from_hw, NULL); + MMIO_RING_GM(RING_START, D_ALL, NULL, NULL); /* RING MODE */ #define RING_REG(base) _MMIO((base) + 0x29c) @@ -2686,7 +2687,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_DFH(_MMIO(0x4094), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(ARB_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_RING_GM_RDR(RING_BBADDR, D_ALL, NULL, NULL); + MMIO_RING_GM(RING_BBADDR, D_ALL, NULL, NULL); MMIO_DFH(_MMIO(0x2220), D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0x12220), D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_DFH(_MMIO(0x22220), D_ALL, F_CMD_ACCESS, NULL, NULL); @@ -2771,7 +2772,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt) MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL, intel_vgpu_reg_master_irq_handler); - MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS, + MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, 0, mmio_read_from_hw, NULL); #define RING_REG(base) _MMIO((base) + 0xd0) @@ -2785,7 +2786,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt) #undef RING_REG #define RING_REG(base) _MMIO((base) + 0x234) - MMIO_RING_F(RING_REG, 8, F_RO | F_CMD_ACCESS, 0, ~0, D_BDW_PLUS, + MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); #undef RING_REG @@ -2820,7 +2821,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt) MMIO_RING_F(RING_REG, 32, F_CMD_ACCESS, 0, 0, D_BDW_PLUS, NULL, NULL); #undef RING_REG - MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, hws_pga_write); + MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, hws_pga_write); MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); @@ -3357,7 +3358,10 @@ void intel_gvt_clean_mmio_info(struct intel_gvt *gvt) gvt->mmio.mmio_attribute = NULL; } -/* Special MMIO blocks. */ +/* Special MMIO blocks. registers in MMIO block ranges should not be command + * accessible (should have no F_CMD_ACCESS flag). + * otherwise, need to update cmd_reg_handler in cmd_parser.c + */ static struct gvt_mmio_block mmio_blocks[] = { {D_SKL_PLUS, _MMIO(CSR_MMIO_START_RANGE), 0x3000, NULL, NULL}, {D_ALL, _MMIO(MCHBAR_MIRROR_BASE_SNB), 0x40000, NULL, NULL}, -- GitLab From d0a011094a0c1ba93dbf12a80b69d788b9a5437b Mon Sep 17 00:00:00 2001 From: Colin Xu <colin.xu@intel.com> Date: Wed, 19 Aug 2020 09:08:01 +0800 Subject: [PATCH 0999/1494] drm/i915/gvt: Add F_CMD_ACCESS for some GEN9 SKU WA MMIO access Without F_CMD_ACCESS, guest LRI cmd will fail due to "access to non-render register" when init below WAs: WaDisableDynamicCreditSharing: GAMT_CHKN_BIT_REG WaCompressedResourceSamplerPbeMediaNewHashMode: MMCD_MISC_CTRL So add F_CMD_ACCESS to the two MMIO. Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Colin Xu <colin.xu@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200819010801.53411-1-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/handlers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index d55cb43c9bd4a..840572add2d4c 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -2922,7 +2922,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); - MMIO_DH(MMCD_MISC_CTRL, D_SKL_PLUS, NULL, NULL); + MMIO_DFH(MMCD_MISC_CTRL, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_DH(CHICKEN_PAR1_1, D_SKL_PLUS, NULL, NULL); MMIO_D(DC_STATE_EN, D_SKL_PLUS); MMIO_D(DC_STATE_DEBUG, D_SKL_PLUS); @@ -3138,7 +3138,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_DFH(GEN9_WM_CHICKEN3, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_D(GAMT_CHKN_BIT_REG, D_KBL | D_CFL); + MMIO_DFH(GAMT_CHKN_BIT_REG, D_KBL | D_CFL, F_CMD_ACCESS, NULL, NULL); MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS); return 0; -- GitLab From df398e33b8fd3ac28b3c7166de555e38d26e7391 Mon Sep 17 00:00:00 2001 From: Colin Xu <colin.xu@intel.com> Date: Wed, 19 Aug 2020 09:09:00 +0800 Subject: [PATCH 1000/1494] drm/i915/gvt: Init vreg GUC_STATUS to GS_MIA_IN_RESET Although GVT doesn't support guest GuC, MIA core is still expected to be GS_MIA_IN_RESET after uc HW reset. Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Colin Xu <colin.xu@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20200819010900.54598-1-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/mmio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 291993615af99..b6811f6a230df 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -251,6 +251,9 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu, bool dmlr) /* set the bit 0:2(Core C-State ) to C0 */ vgpu_vreg_t(vgpu, GEN6_GT_CORE_STATUS) = 0; + /* uc reset hw expect GS_MIA_IN_RESET */ + vgpu_vreg_t(vgpu, GUC_STATUS) |= GS_MIA_IN_RESET; + if (IS_BROXTON(vgpu->gvt->gt->i915)) { vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1)); -- GitLab From d46e7ae24b81533d21edfa90914d27efa0c5f85d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 16:04:44 +0200 Subject: [PATCH 1001/1494] drm: prime: add common helper to check scatterlist contiguity It is a common operation done by DRM drivers to check the contiguity of the DMA-mapped buffer described by a scatterlist in the sg_table object. Let's add a common helper for this operation. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/drm_gem_cma_helper.c | 23 +++------------------ drivers/gpu/drm/drm_prime.c | 31 ++++++++++++++++++++++++++++ include/drm/drm_prime.h | 2 ++ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c index 822edeadbab3f..59b9ca207b42d 100644 --- a/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/drivers/gpu/drm/drm_gem_cma_helper.c @@ -471,26 +471,9 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev, { struct drm_gem_cma_object *cma_obj; - if (sgt->nents != 1) { - /* check if the entries in the sg_table are contiguous */ - dma_addr_t next_addr = sg_dma_address(sgt->sgl); - struct scatterlist *s; - unsigned int i; - - for_each_sg(sgt->sgl, s, sgt->nents, i) { - /* - * sg_dma_address(s) is only valid for entries - * that have sg_dma_len(s) != 0 - */ - if (!sg_dma_len(s)) - continue; - - if (sg_dma_address(s) != next_addr) - return ERR_PTR(-EINVAL); - - next_addr = sg_dma_address(s) + sg_dma_len(s); - } - } + /* check if the entries in the sg_table are contiguous */ + if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) + return ERR_PTR(-EINVAL); /* Create a CMA GEM buffer. */ cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 1693aa7c14b5f..4ed5ed1f078cd 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -825,6 +825,37 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_page } EXPORT_SYMBOL(drm_prime_pages_to_sg); +/** + * drm_prime_get_contiguous_size - returns the contiguous size of the buffer + * @sgt: sg_table describing the buffer to check + * + * This helper calculates the contiguous size in the DMA address space + * of the the buffer described by the provided sg_table. + * + * This is useful for implementing + * &drm_gem_object_funcs.gem_prime_import_sg_table. + */ +unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt) +{ + dma_addr_t expected = sg_dma_address(sgt->sgl); + struct scatterlist *sg; + unsigned long size = 0; + int i; + + for_each_sgtable_dma_sg(sgt, sg, i) { + unsigned int len = sg_dma_len(sg); + + if (!len) + break; + if (sg_dma_address(sg) != expected) + break; + expected += len; + size += len; + } + return size; +} +EXPORT_SYMBOL(drm_prime_get_contiguous_size); + /** * drm_gem_prime_export - helper library implementation of the export callback * @obj: GEM object to export diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h index 9af7422b44cf0..47ef11614627c 100644 --- a/include/drm/drm_prime.h +++ b/include/drm/drm_prime.h @@ -92,6 +92,8 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_page struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj, int flags); +unsigned long drm_prime_get_contiguous_size(struct sg_table *sgt); + /* helper functions for importing */ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, struct dma_buf *dma_buf, -- GitLab From 0552daac2d18fc92c71c94492476b8eb521227e9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 16:05:14 +0200 Subject: [PATCH 1002/1494] drm: prime: use sgtable iterators in drm_prime_sg_to_page_addr_arrays() Replace the current hand-crafted code for extracting pages and DMA addresses from the given scatterlist by the much more robust code based on the generic scatterlist iterators and recently introduced sg_table-based wrappers. The resulting code is simple and easy to understand, so the comment describing the old code is no longer needed. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/drm_prime.c | 49 ++++++++++++------------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 4ed5ed1f078cd..c5e796d4a4895 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -990,45 +990,26 @@ EXPORT_SYMBOL(drm_gem_prime_import); int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, dma_addr_t *addrs, int max_entries) { - unsigned count; - struct scatterlist *sg; - struct page *page; - u32 page_len, page_index; - dma_addr_t addr; - u32 dma_len, dma_index; - - /* - * Scatterlist elements contains both pages and DMA addresses, but - * one shoud not assume 1:1 relation between them. The sg->length is - * the size of the physical memory chunk described by the sg->page, - * while sg_dma_len(sg) is the size of the DMA (IO virtual) chunk - * described by the sg_dma_address(sg). - */ - page_index = 0; - dma_index = 0; - for_each_sg(sgt->sgl, sg, sgt->nents, count) { - page_len = sg->length; - page = sg_page(sg); - dma_len = sg_dma_len(sg); - addr = sg_dma_address(sg); - - while (pages && page_len > 0) { - if (WARN_ON(page_index >= max_entries)) + struct sg_dma_page_iter dma_iter; + struct sg_page_iter page_iter; + struct page **p = pages; + dma_addr_t *a = addrs; + + if (pages) { + for_each_sgtable_page(sgt, &page_iter, 0) { + if (WARN_ON(p - pages >= max_entries)) return -1; - pages[page_index] = page; - page++; - page_len -= PAGE_SIZE; - page_index++; + *p++ = sg_page_iter_page(&page_iter); } - while (addrs && dma_len > 0) { - if (WARN_ON(dma_index >= max_entries)) + } + if (addrs) { + for_each_sgtable_dma_page(sgt, &dma_iter, 0) { + if (WARN_ON(a - addrs >= max_entries)) return -1; - addrs[dma_index] = addr; - addr += PAGE_SIZE; - dma_len -= PAGE_SIZE; - dma_index++; + *a++ = sg_page_iter_dma_address(&dma_iter); } } + return 0; } EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays); -- GitLab From 6c6fa39ca958d5313ff90d3e6c3064e0043c1da3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Mon, 11 May 2020 12:27:54 +0200 Subject: [PATCH 1003/1494] drm: core: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/drm_cache.c | 2 +- drivers/gpu/drm/drm_gem_shmem_helper.c | 14 +++++++++----- drivers/gpu/drm/drm_prime.c | 11 ++++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 03e01b000f7ac..0fe3c496002a9 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -127,7 +127,7 @@ drm_clflush_sg(struct sg_table *st) struct sg_page_iter sg_iter; mb(); /*CLFLUSH is ordered only by using memory barriers*/ - for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) + for_each_sgtable_page(st, &sg_iter, 0) drm_clflush_page(sg_page_iter_page(&sg_iter)); mb(); /*Make sure that all cache line entry is flushed*/ diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 4b7cfbac4daae..47d8211221f2a 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -126,8 +126,8 @@ void drm_gem_shmem_free_object(struct drm_gem_object *obj) drm_prime_gem_destroy(obj, shmem->sgt); } else { if (shmem->sgt) { - dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl, - shmem->sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(obj->dev->dev, shmem->sgt, + DMA_BIDIRECTIONAL, 0); sg_free_table(shmem->sgt); kfree(shmem->sgt); } @@ -424,8 +424,7 @@ void drm_gem_shmem_purge_locked(struct drm_gem_object *obj) WARN_ON(!drm_gem_shmem_is_purgeable(shmem)); - dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl, - shmem->sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(obj->dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0); sg_free_table(shmem->sgt); kfree(shmem->sgt); shmem->sgt = NULL; @@ -697,12 +696,17 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_object *obj) goto err_put_pages; } /* Map the pages for use by the h/w. */ - dma_map_sg(obj->dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL); + ret = dma_map_sgtable(obj->dev->dev, sgt, DMA_BIDIRECTIONAL, 0); + if (ret) + goto err_free_sgt; shmem->sgt = sgt; return sgt; +err_free_sgt: + sg_free_table(sgt); + kfree(sgt); err_put_pages: drm_gem_shmem_put_pages(shmem); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index c5e796d4a4895..b8c7f068a5a41 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -617,6 +617,7 @@ struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, { struct drm_gem_object *obj = attach->dmabuf->priv; struct sg_table *sgt; + int ret; if (WARN_ON(dir == DMA_NONE)) return ERR_PTR(-EINVAL); @@ -626,11 +627,12 @@ struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, else sgt = obj->dev->driver->gem_prime_get_sg_table(obj); - if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC)) { + ret = dma_map_sgtable(attach->dev, sgt, dir, + DMA_ATTR_SKIP_CPU_SYNC); + if (ret) { sg_free_table(sgt); kfree(sgt); - sgt = ERR_PTR(-ENOMEM); + sgt = ERR_PTR(ret); } return sgt; @@ -652,8 +654,7 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, if (!sgt) return; - dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC); + dma_unmap_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC); sg_free_table(sgt); kfree(sgt); } -- GitLab From efcb3730ef4b2911bbe98a686468a5173c786150 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:08:07 +0200 Subject: [PATCH 1004/1494] drm: armada: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> --- drivers/gpu/drm/armada/armada_gem.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 8005614d2e6ba..a63008ce284de 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -379,7 +379,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, struct armada_gem_object *dobj = drm_to_armada_gem(obj); struct scatterlist *sg; struct sg_table *sgt; - int i, num; + int i; sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); if (!sgt) @@ -395,22 +395,18 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, mapping = dobj->obj.filp->f_mapping; - for_each_sg(sgt->sgl, sg, count, i) { + for_each_sgtable_sg(sgt, sg, i) { struct page *page; page = shmem_read_mapping_page(mapping, i); - if (IS_ERR(page)) { - num = i; + if (IS_ERR(page)) goto release; - } sg_set_page(sg, page, PAGE_SIZE, 0); } - if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) { - num = sgt->nents; + if (dma_map_sgtable(attach->dev, sgt, dir, 0)) goto release; - } } else if (dobj->page) { /* Single contiguous page */ if (sg_alloc_table(sgt, 1, GFP_KERNEL)) @@ -418,7 +414,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, sg_set_page(sgt->sgl, dobj->page, dobj->obj.size, 0); - if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) + if (dma_map_sgtable(attach->dev, sgt, dir, 0)) goto free_table; } else if (dobj->linear) { /* Single contiguous physical region - no struct page */ @@ -432,8 +428,9 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, return sgt; release: - for_each_sg(sgt->sgl, sg, num, i) - put_page(sg_page(sg)); + for_each_sgtable_sg(sgt, sg, i) + if (sg_page(sg)) + put_page(sg_page(sg)); free_table: sg_free_table(sgt); free_sgt: @@ -449,11 +446,12 @@ static void armada_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, int i; if (!dobj->linear) - dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); + dma_unmap_sgtable(attach->dev, sgt, dir, 0); if (dobj->obj.filp) { struct scatterlist *sg; - for_each_sg(sgt->sgl, sg, sgt->nents, i) + + for_each_sgtable_sg(sgt, sg, i) put_page(sg_page(sg)); } -- GitLab From 182354a526a0540c9197e03d9fce8a949ffd36ca Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:08:23 +0200 Subject: [PATCH 1005/1494] drm: etnaviv: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Lucas Stach <l.stach@pengutronix.de> --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 12 +++++------- drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 15 ++++----------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index f06e19e7be04a..eaf1949bc2e40 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -27,7 +27,7 @@ static void etnaviv_gem_scatter_map(struct etnaviv_gem_object *etnaviv_obj) * because display controller, GPU, etc. are not coherent. */ if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) - dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL); + dma_map_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0); } static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj) @@ -51,7 +51,7 @@ static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj * discard those writes. */ if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK) - dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0); } /* called with etnaviv_obj->lock held */ @@ -404,9 +404,8 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, } if (etnaviv_obj->flags & ETNA_BO_CACHED) { - dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl, - etnaviv_obj->sgt->nents, - etnaviv_op_to_dma_dir(op)); + dma_sync_sgtable_for_cpu(dev->dev, etnaviv_obj->sgt, + etnaviv_op_to_dma_dir(op)); etnaviv_obj->last_cpu_prep_op = op; } @@ -421,8 +420,7 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj) if (etnaviv_obj->flags & ETNA_BO_CACHED) { /* fini without a prep is almost certainly a userspace error */ WARN_ON(etnaviv_obj->last_cpu_prep_op == 0); - dma_sync_sg_for_device(dev->dev, etnaviv_obj->sgt->sgl, - etnaviv_obj->sgt->nents, + dma_sync_sgtable_for_device(dev->dev, etnaviv_obj->sgt, etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op)); etnaviv_obj->last_cpu_prep_op = 0; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index 3607d348c2980..15d9fa3879e5d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -73,13 +73,13 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova, struct sg_table *sgt, unsigned len, int prot) { struct scatterlist *sg; unsigned int da = iova; - unsigned int i, j; + unsigned int i; int ret; if (!context || !sgt) return -EINVAL; - for_each_sg(sgt->sgl, sg, sgt->nents, i) { + for_each_sgtable_dma_sg(sgt, sg, i) { u32 pa = sg_dma_address(sg) - sg->offset; size_t bytes = sg_dma_len(sg) + sg->offset; @@ -95,14 +95,7 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova, return 0; fail: - da = iova; - - for_each_sg(sgt->sgl, sg, i, j) { - size_t bytes = sg_dma_len(sg) + sg->offset; - - etnaviv_context_unmap(context, da, bytes); - da += bytes; - } + etnaviv_context_unmap(context, iova, da - iova); return ret; } @@ -113,7 +106,7 @@ static void etnaviv_iommu_unmap(struct etnaviv_iommu_context *context, u32 iova, unsigned int da = iova; int i; - for_each_sg(sgt->sgl, sg, sgt->nents, i) { + for_each_sgtable_dma_sg(sgt, sg, i) { size_t bytes = sg_dma_len(sg) + sg->offset; etnaviv_context_unmap(context, da, bytes); -- GitLab From 10740255d8beb78c6d3fd7a332f1a0e3e7dff878 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Thu, 30 Apr 2020 14:02:25 +0200 Subject: [PATCH 1006/1494] drm: exynos: use common helper for a scatterlist contiguity check Use common helper for checking the contiguity of the imported dma-buf. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Acked-by : Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_drm_gem.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index efa476858db54..1716a023bca03 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -431,27 +431,10 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev, { struct exynos_drm_gem *exynos_gem; - if (sgt->nents < 1) + /* check if the entries in the sg_table are contiguous */ + if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) { + DRM_ERROR("buffer chunks must be mapped contiguously"); return ERR_PTR(-EINVAL); - - /* - * Check if the provided buffer has been mapped as contiguous - * into DMA address space. - */ - if (sgt->nents > 1) { - dma_addr_t next_addr = sg_dma_address(sgt->sgl); - struct scatterlist *s; - unsigned int i; - - for_each_sg(sgt->sgl, s, sgt->nents, i) { - if (!sg_dma_len(s)) - break; - if (sg_dma_address(s) != next_addr) { - DRM_ERROR("buffer chunks must be mapped contiguously"); - return ERR_PTR(-EINVAL); - } - next_addr = sg_dma_address(s) + sg_dma_len(s); - } } exynos_gem = exynos_drm_gem_init(dev, attach->dmabuf->size); -- GitLab From 84404614167b829f7b58189cd24b6c0c74897171 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:08:41 +0200 Subject: [PATCH 1007/1494] drm: exynos: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Acked-by : Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 03be314271811..967a5cdc120e3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -395,8 +395,8 @@ static void g2d_userptr_put_dma_addr(struct g2d_data *g2d, return; out: - dma_unmap_sg(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt->sgl, - g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(to_dma_dev(g2d->drm_dev), g2d_userptr->sgt, + DMA_BIDIRECTIONAL, 0); pages = frame_vector_pages(g2d_userptr->vec); if (!IS_ERR(pages)) { @@ -511,10 +511,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct g2d_data *g2d, g2d_userptr->sgt = sgt; - if (!dma_map_sg(to_dma_dev(g2d->drm_dev), sgt->sgl, sgt->nents, - DMA_BIDIRECTIONAL)) { + ret = dma_map_sgtable(to_dma_dev(g2d->drm_dev), sgt, + DMA_BIDIRECTIONAL, 0); + if (ret) { DRM_DEV_ERROR(g2d->dev, "failed to map sgt with dma region.\n"); - ret = -ENOMEM; goto err_sg_free_table; } -- GitLab From b827e3ac4185a6091b90263b6516b54a766c109e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Mon, 4 May 2020 13:12:07 +0200 Subject: [PATCH 1008/1494] drm: i915: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. This driver creatively uses sg_table->orig_nents to store the size of the allocated scatterlist and ignores the number of the entries returned by dma_map_sg function. The sg_table->orig_nents is (mis)used to properly free the (over)allocated scatterlist. This patch only introduces the common DMA-mapping wrappers operating directly on the struct sg_table objects to the dmabuf related functions, so the other drivers, which might share buffers with i915 could rely on the properly set nents and orig_nents values. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 11 +++-------- drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c | 7 +++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 2679380159fc7..8a988592715b3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -48,12 +48,9 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme src = sg_next(src); } - if (!dma_map_sg_attrs(attachment->dev, - st->sgl, st->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC)) { - ret = -ENOMEM; + ret = dma_map_sgtable(attachment->dev, st, dir, DMA_ATTR_SKIP_CPU_SYNC); + if (ret) goto err_free_sg; - } return st; @@ -73,9 +70,7 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, { struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf); - dma_unmap_sg_attrs(attachment->dev, - sg->sgl, sg->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC); + dma_unmap_sgtable(attachment->dev, sg, dir, DMA_ATTR_SKIP_CPU_SYNC); sg_free_table(sg); kfree(sg); diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c index debaf7b18ab59..be30b27e2926b 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_dmabuf.c @@ -28,10 +28,9 @@ static struct sg_table *mock_map_dma_buf(struct dma_buf_attachment *attachment, sg = sg_next(sg); } - if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) { - err = -ENOMEM; + err = dma_map_sgtable(attachment->dev, st, dir, 0); + if (err) goto err_st; - } return st; @@ -46,7 +45,7 @@ static void mock_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *st, enum dma_data_direction dir) { - dma_unmap_sg(attachment->dev, st->sgl, st->nents, dir); + dma_unmap_sgtable(attachment->dev, st, dir, 0); sg_free_table(st); kfree(st); } -- GitLab From c3d9c17f486d5c54940487dc31a54ebfdeeb371a Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:09:11 +0200 Subject: [PATCH 1009/1494] drm: lima: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Qiang Yu <yuq825@gmail.com> --- drivers/gpu/drm/lima/lima_gem.c | 11 ++++++++--- drivers/gpu/drm/lima/lima_vm.c | 5 ++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c index 155f2b4b4030a..11223fe348dfe 100644 --- a/drivers/gpu/drm/lima/lima_gem.c +++ b/drivers/gpu/drm/lima/lima_gem.c @@ -69,8 +69,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm) return ret; if (bo->base.sgt) { - dma_unmap_sg(dev, bo->base.sgt->sgl, - bo->base.sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0); sg_free_table(bo->base.sgt); } else { bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL); @@ -80,7 +79,13 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm) } } - dma_map_sg(dev, sgt.sgl, sgt.nents, DMA_BIDIRECTIONAL); + ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0); + if (ret) { + sg_free_table(&sgt); + kfree(bo->base.sgt); + bo->base.sgt = NULL; + return ret; + } *bo->base.sgt = sgt; diff --git a/drivers/gpu/drm/lima/lima_vm.c b/drivers/gpu/drm/lima/lima_vm.c index 5b92fb82674a9..2b2739adc7f53 100644 --- a/drivers/gpu/drm/lima/lima_vm.c +++ b/drivers/gpu/drm/lima/lima_vm.c @@ -124,7 +124,7 @@ int lima_vm_bo_add(struct lima_vm *vm, struct lima_bo *bo, bool create) if (err) goto err_out1; - for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter, bo->base.sgt->nents, 0) { + for_each_sgtable_dma_page(bo->base.sgt, &sg_iter, 0) { err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter), bo_va->node.start + offset); if (err) @@ -298,8 +298,7 @@ int lima_vm_map_bo(struct lima_vm *vm, struct lima_bo *bo, int pageoff) mutex_lock(&vm->lock); base = bo_va->node.start + (pageoff << PAGE_SHIFT); - for_each_sg_dma_page(bo->base.sgt->sgl, &sg_iter, - bo->base.sgt->nents, pageoff) { + for_each_sgtable_dma_page(bo->base.sgt, &sg_iter, pageoff) { err = lima_vm_map_page(vm, sg_page_iter_dma_address(&sg_iter), base + offset); if (err) -- GitLab From 960db7fcbd67abbea52ab08baa8290fbd027fe3c Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 08:25:52 +0200 Subject: [PATCH 1010/1494] drm: mediatek: use common helper for a scatterlist contiguity check Use common helper for checking the contiguity of the imported dma-buf and do this check before allocating resources, so the error path is simpler. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 28 ++++++-------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 6190cc3b7b0db..3654ec732029e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -212,37 +212,21 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { struct mtk_drm_gem_obj *mtk_gem; - int ret; - struct scatterlist *s; - unsigned int i; - dma_addr_t expected; - mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); + /* check if the entries in the sg_table are contiguous */ + if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { + DRM_ERROR("sg_table is not contiguous"); + return ERR_PTR(-EINVAL); + } + mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); - expected = sg_dma_address(sg->sgl); - for_each_sg(sg->sgl, s, sg->nents, i) { - if (!sg_dma_len(s)) - break; - - if (sg_dma_address(s) != expected) { - DRM_ERROR("sg_table is not contiguous"); - ret = -EINVAL; - goto err_gem_free; - } - expected = sg_dma_address(s) + sg_dma_len(s); - } - mtk_gem->dma_addr = sg_dma_address(sg->sgl); mtk_gem->sg = sg; return &mtk_gem->base; - -err_gem_free: - kfree(mtk_gem); - return ERR_PTR(ret); } void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) -- GitLab From 90dcf4449008cfae24ffd920c0998c09ada46aad Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 11:02:47 +0200 Subject: [PATCH 1011/1494] drm: mediatek: use common helper for extracting pages array Use common helper for converting a sg_table object into struct page pointer array. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_drm_gem.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 3654ec732029e..0583e557ad372 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -233,9 +233,7 @@ void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) { struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct sg_table *sgt; - struct sg_page_iter iter; unsigned int npages; - unsigned int i = 0; if (mtk_gem->kvaddr) return mtk_gem->kvaddr; @@ -249,11 +247,8 @@ void *mtk_drm_gem_prime_vmap(struct drm_gem_object *obj) if (!mtk_gem->pages) goto out; - for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) { - mtk_gem->pages[i++] = sg_page_iter_page(&iter); - if (i > npages) - break; - } + drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages); + mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); -- GitLab From 7690a33f22abab03274d9f5337e22c340664bc45 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 09:56:57 +0200 Subject: [PATCH 1012/1494] drm: msm: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Rob Clark <robdclark@gmail.com> --- drivers/gpu/drm/msm/msm_gem.c | 13 +++++-------- drivers/gpu/drm/msm/msm_gpummu.c | 15 +++++++-------- drivers/gpu/drm/msm/msm_iommu.c | 2 +- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index b2f49152b4d4c..8c7ae812b8131 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -53,11 +53,10 @@ static void sync_for_device(struct msm_gem_object *msm_obj) struct device *dev = msm_obj->base.dev->dev; if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) { - dma_sync_sg_for_device(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + dma_sync_sgtable_for_device(dev, msm_obj->sgt, + DMA_BIDIRECTIONAL); } else { - dma_map_sg(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + dma_map_sgtable(dev, msm_obj->sgt, DMA_BIDIRECTIONAL, 0); } } @@ -66,11 +65,9 @@ static void sync_for_cpu(struct msm_gem_object *msm_obj) struct device *dev = msm_obj->base.dev->dev; if (get_dma_ops(dev) && IS_ENABLED(CONFIG_ARM64)) { - dma_sync_sg_for_cpu(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + dma_sync_sgtable_for_cpu(dev, msm_obj->sgt, DMA_BIDIRECTIONAL); } else { - dma_unmap_sg(dev, msm_obj->sgt->sgl, - msm_obj->sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(dev, msm_obj->sgt, DMA_BIDIRECTIONAL, 0); } } diff --git a/drivers/gpu/drm/msm/msm_gpummu.c b/drivers/gpu/drm/msm/msm_gpummu.c index 310a31b05faa9..53a7348476a16 100644 --- a/drivers/gpu/drm/msm/msm_gpummu.c +++ b/drivers/gpu/drm/msm/msm_gpummu.c @@ -30,21 +30,20 @@ static int msm_gpummu_map(struct msm_mmu *mmu, uint64_t iova, { struct msm_gpummu *gpummu = to_msm_gpummu(mmu); unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE; - struct scatterlist *sg; + struct sg_dma_page_iter dma_iter; unsigned prot_bits = 0; - unsigned i, j; if (prot & IOMMU_WRITE) prot_bits |= 1; if (prot & IOMMU_READ) prot_bits |= 2; - for_each_sg(sgt->sgl, sg, sgt->nents, i) { - dma_addr_t addr = sg->dma_address; - for (j = 0; j < sg->length / GPUMMU_PAGE_SIZE; j++, idx++) { - gpummu->table[idx] = addr | prot_bits; - addr += GPUMMU_PAGE_SIZE; - } + for_each_sgtable_dma_page(sgt, &dma_iter, 0) { + dma_addr_t addr = sg_page_iter_dma_address(&dma_iter); + int i; + + for (i = 0; i < PAGE_SIZE; i += GPUMMU_PAGE_SIZE) + gpummu->table[idx++] = (addr + i) | prot_bits; } /* we can improve by deferring flush for multiple map() */ diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 3a381a9674c92..6c31e65834c62 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -36,7 +36,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, struct msm_iommu *iommu = to_msm_iommu(mmu); size_t ret; - ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); + ret = iommu_map_sgtable(iommu->domain, iova, sgt, prot); WARN_ON(!ret); return (ret == len) ? 0 : -EINVAL; -- GitLab From 537606558c08e1dcb2d35b67aab9d80253dbc6c4 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 11:02:26 +0200 Subject: [PATCH 1013/1494] drm: omapdrm: use common helper for extracting pages array Use common helper for converting a sg_table object into struct page pointer array. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/omapdrm/omap_gem.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index d0d12d5dd76c5..f67f223c6479f 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1297,10 +1297,9 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, omap_obj->dma_addr = sg_dma_address(sgt->sgl); } else { /* Create pages list from sgt */ - struct sg_page_iter iter; struct page **pages; unsigned int npages; - unsigned int i = 0; + unsigned int ret; npages = DIV_ROUND_UP(size, PAGE_SIZE); pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL); @@ -1311,14 +1310,9 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size, } omap_obj->pages = pages; - - for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) { - pages[i++] = sg_page_iter_page(&iter); - if (i > npages) - break; - } - - if (WARN_ON(i != npages)) { + ret = drm_prime_sg_to_page_addr_arrays(sgt, pages, NULL, + npages); + if (ret) { omap_gem_free_object(obj); obj = ERR_PTR(-ENOMEM); goto done; -- GitLab From 34a4e66faf8b22c8409cbd46839ba5e488b1e6a9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:09:35 +0200 Subject: [PATCH 1014/1494] drm: panfrost: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Rob Herring <robh@kernel.org> --- drivers/gpu/drm/panfrost/panfrost_gem.c | 4 ++-- drivers/gpu/drm/panfrost/panfrost_mmu.c | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 33355dd302f11..1a6cea0e0bd74 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -41,8 +41,8 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) for (i = 0; i < n_sgt; i++) { if (bo->sgts[i].sgl) { - dma_unmap_sg(pfdev->dev, bo->sgts[i].sgl, - bo->sgts[i].nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(pfdev->dev, &bo->sgts[i], + DMA_BIDIRECTIONAL, 0); sg_free_table(&bo->sgts[i]); } } diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index e8f7b11352d27..776448c527ea9 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -253,7 +253,7 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, struct io_pgtable_ops *ops = mmu->pgtbl_ops; u64 start_iova = iova; - for_each_sg(sgt->sgl, sgl, sgt->nents, count) { + for_each_sgtable_dma_sg(sgt, sgl, count) { unsigned long paddr = sg_dma_address(sgl); size_t len = sg_dma_len(sgl); @@ -517,10 +517,9 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, if (ret) goto err_pages; - if (!dma_map_sg(pfdev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL)) { - ret = -EINVAL; + ret = dma_map_sgtable(pfdev->dev, sgt, DMA_BIDIRECTIONAL, 0); + if (ret) goto err_map; - } mmu_map_sg(pfdev, bomapping->mmu, addr, IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt); -- GitLab From 6a8f15c62cd9235a3a4eb1c96e79131061310d57 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Thu, 30 Apr 2020 14:02:47 +0200 Subject: [PATCH 1015/1494] drm: rockchip: use common helper for a scatterlist contiguity check Use common helper for checking the contiguity of the imported dma-buf. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index b9275ba7c5a53..2970e534e2bb7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -460,23 +460,6 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj) return sgt; } -static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt, - int count) -{ - struct scatterlist *s; - dma_addr_t expected = sg_dma_address(sgt->sgl); - unsigned int i; - unsigned long size = 0; - - for_each_sg(sgt->sgl, s, count, i) { - if (sg_dma_address(s) != expected) - break; - expected = sg_dma_address(s) + sg_dma_len(s); - size += sg_dma_len(s); - } - return size; -} - static int rockchip_gem_iommu_map_sg(struct drm_device *drm, struct dma_buf_attachment *attach, @@ -498,7 +481,7 @@ rockchip_gem_dma_map_sg(struct drm_device *drm, if (!count) return -EINVAL; - if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) { + if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { DRM_ERROR("failed to map sg_table to contiguous linear address.\n"); dma_unmap_sg(drm->dev, sg->sgl, sg->nents, DMA_BIDIRECTIONAL); -- GitLab From 82c245b592da791c63316e7a82d9b9d01552c0c5 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:10:01 +0200 Subject: [PATCH 1016/1494] drm: rockchip: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 23 +++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 2970e534e2bb7..cb50f2ba2e466 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -36,8 +36,8 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) rk_obj->dma_addr = rk_obj->mm.start; - ret = iommu_map_sg(private->domain, rk_obj->dma_addr, rk_obj->sgt->sgl, - rk_obj->sgt->nents, prot); + ret = iommu_map_sgtable(private->domain, rk_obj->dma_addr, rk_obj->sgt, + prot); if (ret < rk_obj->base.size) { DRM_ERROR("failed to map buffer: size=%zd request_size=%zd\n", ret, rk_obj->base.size); @@ -98,11 +98,10 @@ static int rockchip_gem_get_pages(struct rockchip_gem_object *rk_obj) * TODO: Replace this by drm_clflush_sg() once it can be implemented * without relying on symbols that are not exported. */ - for_each_sg(rk_obj->sgt->sgl, s, rk_obj->sgt->nents, i) + for_each_sgtable_sg(rk_obj->sgt, s, i) sg_dma_address(s) = sg_phys(s); - dma_sync_sg_for_device(drm->dev, rk_obj->sgt->sgl, rk_obj->sgt->nents, - DMA_TO_DEVICE); + dma_sync_sgtable_for_device(drm->dev, rk_obj->sgt, DMA_TO_DEVICE); return 0; @@ -350,8 +349,8 @@ void rockchip_gem_free_object(struct drm_gem_object *obj) if (private->domain) { rockchip_gem_iommu_unmap(rk_obj); } else { - dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, - rk_obj->sgt->nents, DMA_BIDIRECTIONAL); + dma_unmap_sgtable(drm->dev, rk_obj->sgt, + DMA_BIDIRECTIONAL, 0); } drm_prime_gem_destroy(obj, rk_obj->sgt); } else { @@ -476,15 +475,13 @@ rockchip_gem_dma_map_sg(struct drm_device *drm, struct sg_table *sg, struct rockchip_gem_object *rk_obj) { - int count = dma_map_sg(drm->dev, sg->sgl, sg->nents, - DMA_BIDIRECTIONAL); - if (!count) - return -EINVAL; + int err = dma_map_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0); + if (err) + return err; if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { DRM_ERROR("failed to map sg_table to contiguous linear address.\n"); - dma_unmap_sg(drm->dev, sg->sgl, sg->nents, - DMA_BIDIRECTIONAL); + dma_unmap_sgtable(drm->dev, sg, DMA_BIDIRECTIONAL, 0); return -EINVAL; } -- GitLab From d4fea3e61b47a22e57a58d7afd6f0209051208bd Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:10:10 +0200 Subject: [PATCH 1017/1494] drm: tegra: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/tegra/gem.c | 27 ++++++++++----------------- drivers/gpu/drm/tegra/plane.c | 15 +++++---------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 723df142a9818..01d94befab11f 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -98,8 +98,8 @@ static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo, * the SG table needs to be copied to avoid overwriting any * other potential users of the original SG table. */ - err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, obj->sgt->nents, - GFP_KERNEL); + err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, + obj->sgt->orig_nents, GFP_KERNEL); if (err < 0) goto free; } else { @@ -196,8 +196,7 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo) bo->iova = bo->mm->start; - bo->size = iommu_map_sg(tegra->domain, bo->iova, bo->sgt->sgl, - bo->sgt->nents, prot); + bo->size = iommu_map_sgtable(tegra->domain, bo->iova, bo->sgt, prot); if (!bo->size) { dev_err(tegra->drm->dev, "failed to map buffer\n"); err = -ENOMEM; @@ -264,8 +263,7 @@ static struct tegra_bo *tegra_bo_alloc_object(struct drm_device *drm, static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) { if (bo->pages) { - dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); + dma_unmap_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0); drm_gem_put_pages(&bo->gem, bo->pages, true, true); sg_free_table(bo->sgt); kfree(bo->sgt); @@ -290,12 +288,9 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) goto put_pages; } - err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); - if (err == 0) { - err = -EFAULT; + err = dma_map_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0); + if (err) goto free_sgt; - } return 0; @@ -571,7 +566,7 @@ tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, goto free; } - if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) + if (dma_map_sgtable(attach->dev, sgt, dir, 0)) goto free; return sgt; @@ -590,7 +585,7 @@ static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, struct tegra_bo *bo = to_tegra_bo(gem); if (bo->pages) - dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); + dma_unmap_sgtable(attach->dev, sgt, dir, 0); sg_free_table(sgt); kfree(sgt); @@ -609,8 +604,7 @@ static int tegra_gem_prime_begin_cpu_access(struct dma_buf *buf, struct drm_device *drm = gem->dev; if (bo->pages) - dma_sync_sg_for_cpu(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); + dma_sync_sgtable_for_cpu(drm->dev, bo->sgt, DMA_FROM_DEVICE); return 0; } @@ -623,8 +617,7 @@ static int tegra_gem_prime_end_cpu_access(struct dma_buf *buf, struct drm_device *drm = gem->dev; if (bo->pages) - dma_sync_sg_for_device(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_TO_DEVICE); + dma_sync_sgtable_for_device(drm->dev, bo->sgt, DMA_TO_DEVICE); return 0; } diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 4cd0461cc5088..539d14935728e 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -131,12 +131,9 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) } if (sgt) { - err = dma_map_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); - if (err == 0) { - err = -ENOMEM; + err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); + if (err) goto unpin; - } /* * The display controller needs contiguous memory, so @@ -144,7 +141,7 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) * map its SG table to a single contiguous chunk of * I/O virtual memory. */ - if (err > 1) { + if (sgt->nents > 1) { err = -EINVAL; goto unpin; } @@ -166,8 +163,7 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) struct sg_table *sgt = state->sgt[i]; if (sgt) - dma_unmap_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); + dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); host1x_bo_unpin(dc->dev, &bo->base, sgt); state->iova[i] = DMA_MAPPING_ERROR; @@ -186,8 +182,7 @@ static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state) struct sg_table *sgt = state->sgt[i]; if (sgt) - dma_unmap_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); + dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); host1x_bo_unpin(dc->dev, &bo->base, sgt); state->iova[i] = DMA_MAPPING_ERROR; -- GitLab From e96418da0a2b9f52538c4a84f6f565708d7ed32e Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 08:26:50 +0200 Subject: [PATCH 1018/1494] drm: v3d: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Eric Anholt <eric@anholt.net> --- drivers/gpu/drm/v3d/v3d_mmu.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c index 3b81ea28c0bbc..5a453532901f1 100644 --- a/drivers/gpu/drm/v3d/v3d_mmu.c +++ b/drivers/gpu/drm/v3d/v3d_mmu.c @@ -90,18 +90,17 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo) struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev); u32 page = bo->node.start; u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID; - unsigned int count; - struct scatterlist *sgl; + struct sg_dma_page_iter dma_iter; - for_each_sg(shmem_obj->sgt->sgl, sgl, shmem_obj->sgt->nents, count) { - u32 page_address = sg_dma_address(sgl) >> V3D_MMU_PAGE_SHIFT; + for_each_sgtable_dma_page(shmem_obj->sgt, &dma_iter, 0) { + dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter); + u32 page_address = dma_addr >> V3D_MMU_PAGE_SHIFT; u32 pte = page_prot | page_address; u32 i; - BUG_ON(page_address + (sg_dma_len(sgl) >> V3D_MMU_PAGE_SHIFT) >= + BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >= BIT(24)); - - for (i = 0; i < sg_dma_len(sgl) >> V3D_MMU_PAGE_SHIFT; i++) + for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++) v3d->pt[page++] = pte + i; } -- GitLab From 75ef337bdba418e7b8117765aa03a8d261b8f32d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:10:19 +0200 Subject: [PATCH 1019/1494] drm: virtio: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/gpu/drm/virtio/virtgpu_object.c | 36 ++++++++++++++----------- drivers/gpu/drm/virtio/virtgpu_vq.c | 12 ++++----- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 2cdd3cd9ce75f..5419b7f41af08 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -72,9 +72,8 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo) if (shmem->pages) { if (shmem->mapped) { - dma_unmap_sg(vgdev->vdev->dev.parent, - shmem->pages->sgl, shmem->mapped, - DMA_TO_DEVICE); + dma_unmap_sgtable(vgdev->vdev->dev.parent, + shmem->pages, DMA_TO_DEVICE, 0); shmem->mapped = 0; } @@ -157,13 +156,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, } if (use_dma_api) { - shmem->mapped = dma_map_sg(vgdev->vdev->dev.parent, - shmem->pages->sgl, - shmem->pages->nents, - DMA_TO_DEVICE); - *nents = shmem->mapped; + ret = dma_map_sgtable(vgdev->vdev->dev.parent, + shmem->pages, DMA_TO_DEVICE, 0); + if (ret) + return ret; + *nents = shmem->mapped = shmem->pages->nents; } else { - *nents = shmem->pages->nents; + *nents = shmem->pages->orig_nents; } *ents = kmalloc_array(*nents, sizeof(struct virtio_gpu_mem_entry), @@ -173,13 +172,20 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, return -ENOMEM; } - for_each_sg(shmem->pages->sgl, sg, *nents, si) { - (*ents)[si].addr = cpu_to_le64(use_dma_api - ? sg_dma_address(sg) - : sg_phys(sg)); - (*ents)[si].length = cpu_to_le32(sg->length); - (*ents)[si].padding = 0; + if (use_dma_api) { + for_each_sgtable_dma_sg(shmem->pages, sg, si) { + (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg)); + (*ents)[si].length = cpu_to_le32(sg_dma_len(sg)); + (*ents)[si].padding = 0; + } + } else { + for_each_sgtable_sg(shmem->pages, sg, si) { + (*ents)[si].addr = cpu_to_le64(sg_phys(sg)); + (*ents)[si].length = cpu_to_le32(sg->length); + (*ents)[si].padding = 0; + } } + return 0; } diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 53af60d484a44..7947b1047bd07 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -302,7 +302,7 @@ static struct sg_table *vmalloc_to_sgt(char *data, uint32_t size, int *sg_ents) return NULL; } - for_each_sg(sgt->sgl, sg, *sg_ents, i) { + for_each_sgtable_sg(sgt, sg, i) { pg = vmalloc_to_page(data); if (!pg) { sg_free_table(sgt); @@ -603,9 +603,8 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); if (use_dma_api) - dma_sync_sg_for_device(vgdev->vdev->dev.parent, - shmem->pages->sgl, shmem->pages->nents, - DMA_TO_DEVICE); + dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, + shmem->pages, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); memset(cmd_p, 0, sizeof(*cmd_p)); @@ -1019,9 +1018,8 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo); if (use_dma_api) - dma_sync_sg_for_device(vgdev->vdev->dev.parent, - shmem->pages->sgl, shmem->pages->nents, - DMA_TO_DEVICE); + dma_sync_sgtable_for_device(vgdev->vdev->dev.parent, + shmem->pages, DMA_TO_DEVICE); cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); memset(cmd_p, 0, sizeof(*cmd_p)); -- GitLab From c915c2cbaf5eb256d26f40cfce1c5defbfcadab9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:10:36 +0200 Subject: [PATCH 1020/1494] drm: vmwgfx: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Roland Scheidegger <sroland@vmware.com> --- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index ab524ab3b0b4c..f2f2bff1eedf5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -362,8 +362,7 @@ static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt *vmw_tt) { struct device *dev = vmw_tt->dev_priv->dev->dev; - dma_unmap_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.nents, - DMA_BIDIRECTIONAL); + dma_unmap_sgtable(dev, &vmw_tt->sgt, DMA_BIDIRECTIONAL, 0); vmw_tt->sgt.nents = vmw_tt->sgt.orig_nents; } @@ -383,16 +382,8 @@ static void vmw_ttm_unmap_from_dma(struct vmw_ttm_tt *vmw_tt) static int vmw_ttm_map_for_dma(struct vmw_ttm_tt *vmw_tt) { struct device *dev = vmw_tt->dev_priv->dev->dev; - int ret; - - ret = dma_map_sg(dev, vmw_tt->sgt.sgl, vmw_tt->sgt.orig_nents, - DMA_BIDIRECTIONAL); - if (unlikely(ret == 0)) - return -ENOMEM; - vmw_tt->sgt.nents = ret; - - return 0; + return dma_map_sgtable(dev, &vmw_tt->sgt, DMA_BIDIRECTIONAL, 0); } /** @@ -449,10 +440,10 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) if (unlikely(ret != 0)) goto out_sg_alloc_fail; - if (vsgt->num_pages > vmw_tt->sgt.nents) { + if (vsgt->num_pages > vmw_tt->sgt.orig_nents) { uint64_t over_alloc = sgl_size * (vsgt->num_pages - - vmw_tt->sgt.nents); + vmw_tt->sgt.orig_nents); ttm_mem_global_free(glob, over_alloc); vmw_tt->sg_alloc_size -= over_alloc; -- GitLab From 5e0ff16b9edf3379e5a0e1545b0d9831a7353cca Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:10:45 +0200 Subject: [PATCH 1021/1494] drm: xen: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. Fix the code to refer to proper nents or orig_nents entries. This driver reports the number of the pages in the imported scatterlist, so it should refer to sg_table->orig_nents entry. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> --- drivers/gpu/drm/xen/xen_drm_front_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index 39ff95b75357d..0e57c80058b2f 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -216,7 +216,7 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev, return ERR_PTR(ret); DRM_DEBUG("Imported buffer of size %zu with nents %u\n", - size, sgt->nents); + size, sgt->orig_nents); return &xen_obj->base; } -- GitLab From d1749eb1ab85e04e58c29e58900e3abebbdd6e82 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 16:07:13 +0200 Subject: [PATCH 1022/1494] xen: gntdev: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Juergen Gross <jgross@suse.com> --- drivers/xen/gntdev-dmabuf.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c index b1b6eebafd5de..4c13cbc99896a 100644 --- a/drivers/xen/gntdev-dmabuf.c +++ b/drivers/xen/gntdev-dmabuf.c @@ -247,10 +247,9 @@ static void dmabuf_exp_ops_detach(struct dma_buf *dma_buf, if (sgt) { if (gntdev_dmabuf_attach->dir != DMA_NONE) - dma_unmap_sg_attrs(attach->dev, sgt->sgl, - sgt->nents, - gntdev_dmabuf_attach->dir, - DMA_ATTR_SKIP_CPU_SYNC); + dma_unmap_sgtable(attach->dev, sgt, + gntdev_dmabuf_attach->dir, + DMA_ATTR_SKIP_CPU_SYNC); sg_free_table(sgt); } @@ -288,8 +287,8 @@ dmabuf_exp_ops_map_dma_buf(struct dma_buf_attachment *attach, sgt = dmabuf_pages_to_sgt(gntdev_dmabuf->pages, gntdev_dmabuf->nr_pages); if (!IS_ERR(sgt)) { - if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC)) { + if (dma_map_sgtable(attach->dev, sgt, dir, + DMA_ATTR_SKIP_CPU_SYNC)) { sg_free_table(sgt); kfree(sgt); sgt = ERR_PTR(-ENOMEM); @@ -633,7 +632,7 @@ dmabuf_imp_to_refs(struct gntdev_dmabuf_priv *priv, struct device *dev, /* Now convert sgt to array of pages and check for page validity. */ i = 0; - for_each_sg_page(sgt->sgl, &sg_iter, sgt->nents, 0) { + for_each_sgtable_page(sgt, &sg_iter, 0) { struct page *page = sg_page_iter_page(&sg_iter); /* * Check if page is valid: this can happen if we are given -- GitLab From 67ed9f9d95189d0f99c38f34b8bb1a8fa135c877 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 28 Apr 2020 13:11:16 +0200 Subject: [PATCH 1023/1494] drm: host1x: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/host1x/job.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index 89b6c14b73920..82d0a60ba3f77 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -170,11 +170,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } - err = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); - if (!err) { - err = -ENOMEM; + err = dma_map_sgtable(dev, sgt, dir, 0); + if (err) goto unpin; - } job->unpins[job->num_unpins].dev = dev; job->unpins[job->num_unpins].dir = dir; @@ -228,7 +226,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) } if (host->domain) { - for_each_sg(sgt->sgl, sg, sgt->nents, j) + for_each_sgtable_sg(sgt, sg, j) gather_size += sg->length; gather_size = iova_align(&host->iova, gather_size); @@ -240,9 +238,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto put; } - err = iommu_map_sg(host->domain, + err = iommu_map_sgtable(host->domain, iova_dma_addr(&host->iova, alloc), - sgt->sgl, sgt->nents, IOMMU_READ); + sgt, IOMMU_READ); if (err == 0) { __free_iova(&host->iova, alloc); err = -EINVAL; @@ -252,12 +250,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) job->unpins[job->num_unpins].size = gather_size; phys_addr = iova_dma_addr(&host->iova, alloc); } else if (sgt) { - err = dma_map_sg(host->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); - if (!err) { - err = -ENOMEM; + err = dma_map_sgtable(host->dev, sgt, DMA_TO_DEVICE, 0); + if (err) goto put; - } job->unpins[job->num_unpins].dir = DMA_TO_DEVICE; job->unpins[job->num_unpins].dev = host->dev; @@ -660,8 +655,7 @@ void host1x_job_unpin(struct host1x_job *job) } if (unpin->dev && sgt) - dma_unmap_sg(unpin->dev, sgt->sgl, sgt->nents, - unpin->dir); + dma_unmap_sgtable(unpin->dev, sgt, unpin->dir, 0); host1x_bo_unpin(dev, unpin->bo, sgt); host1x_bo_put(unpin->bo); -- GitLab From 34e8548168758f1adf50984f40ce190e5c19c621 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Fri, 8 May 2020 16:10:16 +0200 Subject: [PATCH 1024/1494] drm: rcar-du: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. dma_map_sgtable() function returns zero or an error code, so adjust the return value check for the vsp1_du_map_sg() function. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 3 +-- drivers/media/platform/vsp1/vsp1_drm.c | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index f1a81c9b184d4..a27bff9996493 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -197,9 +197,8 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, goto fail; ret = vsp1_du_map_sg(vsp->vsp, sgt); - if (!ret) { + if (ret) { sg_free_table(sgt); - ret = -ENOMEM; goto fail; } } diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index a4a45d68a6efc..86d5e3f4b1ffc 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -912,8 +912,8 @@ int vsp1_du_map_sg(struct device *dev, struct sg_table *sgt) * skip cache sync. This will need to be revisited when support for * non-coherent buffers will be added to the DU driver. */ - return dma_map_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + return dma_map_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); } EXPORT_SYMBOL_GPL(vsp1_du_map_sg); @@ -921,8 +921,8 @@ void vsp1_du_unmap_sg(struct device *dev, struct sg_table *sgt) { struct vsp1_device *vsp1 = dev_get_drvdata(dev); - dma_unmap_sg_attrs(vsp1->bus_master, sgt->sgl, sgt->nents, - DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); + dma_unmap_sgtable(vsp1->bus_master, sgt, DMA_TO_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); } EXPORT_SYMBOL_GPL(vsp1_du_unmap_sg); -- GitLab From 62296b395a512930686666089ad285b1f78fd2f0 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Mon, 6 Apr 2020 16:41:45 +0200 Subject: [PATCH 1025/1494] dmabuf: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> --- drivers/dma-buf/heaps/heap-helpers.c | 13 ++++++------- drivers/dma-buf/udmabuf.c | 7 +++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c index 9f964ca3f59ce..d0696cf937af3 100644 --- a/drivers/dma-buf/heaps/heap-helpers.c +++ b/drivers/dma-buf/heaps/heap-helpers.c @@ -140,13 +140,12 @@ struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction direction) { struct dma_heaps_attachment *a = attachment->priv; - struct sg_table *table; - - table = &a->table; + struct sg_table *table = &a->table; + int ret; - if (!dma_map_sg(attachment->dev, table->sgl, table->nents, - direction)) - table = ERR_PTR(-ENOMEM); + ret = dma_map_sgtable(attachment->dev, table, direction, 0); + if (ret) + table = ERR_PTR(ret); return table; } @@ -154,7 +153,7 @@ static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *table, enum dma_data_direction direction) { - dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); + dma_unmap_sgtable(attachment->dev, table, direction, 0); } static vm_fault_t dma_heap_vm_fault(struct vm_fault *vmf) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index acb26c627d27b..89e293bd92523 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -63,10 +63,9 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf, GFP_KERNEL); if (ret < 0) goto err; - if (!dma_map_sg(dev, sg->sgl, sg->nents, direction)) { - ret = -EINVAL; + ret = dma_map_sgtable(dev, sg, direction, 0); + if (ret < 0) goto err; - } return sg; err: @@ -78,7 +77,7 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf, static void put_sg_table(struct device *dev, struct sg_table *sg, enum dma_data_direction direction) { - dma_unmap_sg(dev, sg->sgl, sg->nents, direction); + dma_unmap_sgtable(dev, sg, direction, 0); sg_free_table(sg); kfree(sg); } -- GitLab From be0704beb229431f206fee3ddd65fa2c5eebdce3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Thu, 30 Apr 2020 13:57:22 +0200 Subject: [PATCH 1026/1494] samples: vfio-mdev/mbochs: fix common struct sg_table related issues The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. While touching this code, also add missing call to dma_unmap_sgtable. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> --- samples/vfio-mdev/mbochs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index 3cc5e59216825..e03068917273d 100644 --- a/samples/vfio-mdev/mbochs.c +++ b/samples/vfio-mdev/mbochs.c @@ -846,7 +846,7 @@ static struct sg_table *mbochs_map_dmabuf(struct dma_buf_attachment *at, if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount, 0, dmabuf->mode.size, GFP_KERNEL) < 0) goto err2; - if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction)) + if (dma_map_sgtable(at->dev, sg, direction, 0)) goto err3; return sg; @@ -868,6 +868,7 @@ static void mbochs_unmap_dmabuf(struct dma_buf_attachment *at, dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id); + dma_unmap_sgtable(at->dev, sg, direction, 0); sg_free_table(sg); kfree(sg); } -- GitLab From c00579943c576e02154c9b2bf29b3164a06756c6 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 20:19:00 +0800 Subject: [PATCH 1027/1494] drm/bridge/tc358775: Remove unneeded semicolon Fixes coccicheck warning: drivers/gpu/drm/bridge/tc358775.c:488:2-3: Unneeded semicolon Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200909121900.103712-1-zhengbin13@huawei.com --- drivers/gpu/drm/bridge/tc358775.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index d951cdc582971..2272adcc5b4ad 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -485,7 +485,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge) val |= TC358775_LVCFG_PCLKDIV(DIVIDE_BY_6); } else { val |= TC358775_LVCFG_PCLKDIV(DIVIDE_BY_3); - }; + } d2l_write(tc->i2c, LVCFG, val); } -- GitLab From 13138ab2dacd0076a93f74b49ea8fe806e49c3f5 Mon Sep 17 00:00:00 2001 From: YueHaibing <yuehaibing@huawei.com> Date: Wed, 9 Sep 2020 21:41:37 +0800 Subject: [PATCH 1028/1494] drm/panel: s6e63m0: Add missing MODULE_LICENSE Kbuild warns when this file is built as a loadable module: WARNING: modpost: missing MODULE_LICENSE() in drivers/gpu/drm/panel/panel-samsung-s6e63m0.o Add the missing license/author/description tags. Fixes: b7b23e447687 ("drm/panel: s6e63m0: Break out SPI transport") Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200909134137.32284-1-yuehaibing@huawei.com --- drivers/gpu/drm/panel/panel-samsung-s6e63m0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 044294aafe278..3eee67e2d86a4 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -534,3 +534,7 @@ int s6e63m0_remove(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(s6e63m0_remove); + +MODULE_AUTHOR("PaweÅ‚ Chmiel <pawel.mikolaj.chmiel@gmail.com>"); +MODULE_DESCRIPTION("s6e63m0 LCD Driver"); +MODULE_LICENSE("GPL v2"); -- GitLab From 5bfe37ca8ac8e9176bfd923d0a83802b7305d2f5 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf <sebastien.boeuf@intel.com> Date: Wed, 19 Aug 2020 18:19:41 -0400 Subject: [PATCH 1029/1494] virtio: Add get_shm_region method Virtio defines 'shared memory regions' that provide a continuously shared region between the host and guest. Provide a method to find a particular region on a device. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Cc: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Cc: "Michael S. Tsirkin" <mst@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- include/linux/virtio_config.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 8fe857e27ef32..4b8e38c5c4d8c 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h @@ -11,6 +11,11 @@ struct irq_affinity; +struct virtio_shm_region { + u64 addr; + u64 len; +}; + /** * virtio_config_ops - operations for configuring a virtio device * Note: Do not assume that a transport implements all of the operations @@ -66,6 +71,7 @@ struct irq_affinity; * the caller can then copy. * @set_vq_affinity: set the affinity for a virtqueue (optional). * @get_vq_affinity: get the affinity for a virtqueue (optional). + * @get_shm_region: get a shared memory region based on the index. */ typedef void vq_callback_t(struct virtqueue *); struct virtio_config_ops { @@ -89,6 +95,8 @@ struct virtio_config_ops { const struct cpumask *cpu_mask); const struct cpumask *(*get_vq_affinity)(struct virtio_device *vdev, int index); + bool (*get_shm_region)(struct virtio_device *vdev, + struct virtio_shm_region *region, u8 id); }; /* If driver didn't advertise the feature, it will never appear. */ @@ -251,6 +259,15 @@ int virtqueue_set_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask) return 0; } +static inline +bool virtio_get_shm_region(struct virtio_device *vdev, + struct virtio_shm_region *region, u8 id) +{ + if (!vdev->config->get_shm_region) + return false; + return vdev->config->get_shm_region(vdev, region, id); +} + static inline bool virtio_is_little_endian(struct virtio_device *vdev) { return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) || -- GitLab From 0dd4ff93f4c8dba016ad79384007da4938cd54a1 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf <sebastien.boeuf@intel.com> Date: Wed, 19 Aug 2020 18:19:42 -0400 Subject: [PATCH 1030/1494] virtio: Implement get_shm_region for PCI transport On PCI the shm regions are found using capability entries; find a region by searching for the capability. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: kbuild test robot <lkp@intel.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Cc: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Cc: "Michael S. Tsirkin" <mst@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- drivers/virtio/virtio_pci_modern.c | 95 ++++++++++++++++++++++++++++++ include/uapi/linux/virtio_pci.h | 11 +++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 3e14e700b2312..3d6ae5a5e252e 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -444,6 +444,99 @@ static void del_vq(struct virtio_pci_vq_info *info) vring_del_virtqueue(vq); } +static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id, + u8 *bar, u64 *offset, u64 *len) +{ + int pos; + + for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); pos > 0; + pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) { + u8 type, cap_len, id; + u32 tmp32; + u64 res_offset, res_length; + + pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, + cfg_type), &type); + if (type != VIRTIO_PCI_CAP_SHARED_MEMORY_CFG) + continue; + + pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, + cap_len), &cap_len); + if (cap_len != sizeof(struct virtio_pci_cap64)) { + dev_err(&dev->dev, "%s: shm cap with bad size offset:" + " %d size: %d\n", __func__, pos, cap_len); + continue; + } + + pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, + id), &id); + if (id != required_id) + continue; + + /* Type, and ID match, looks good */ + pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, + bar), bar); + + /* Read the lower 32bit of length and offset */ + pci_read_config_dword(dev, pos + offsetof(struct virtio_pci_cap, + offset), &tmp32); + res_offset = tmp32; + pci_read_config_dword(dev, pos + offsetof(struct virtio_pci_cap, + length), &tmp32); + res_length = tmp32; + + /* and now the top half */ + pci_read_config_dword(dev, + pos + offsetof(struct virtio_pci_cap64, + offset_hi), &tmp32); + res_offset |= ((u64)tmp32) << 32; + pci_read_config_dword(dev, + pos + offsetof(struct virtio_pci_cap64, + length_hi), &tmp32); + res_length |= ((u64)tmp32) << 32; + + *offset = res_offset; + *len = res_length; + + return pos; + } + return 0; +} + +static bool vp_get_shm_region(struct virtio_device *vdev, + struct virtio_shm_region *region, u8 id) +{ + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + struct pci_dev *pci_dev = vp_dev->pci_dev; + u8 bar; + u64 offset, len; + phys_addr_t phys_addr; + size_t bar_len; + + if (!virtio_pci_find_shm_cap(pci_dev, id, &bar, &offset, &len)) + return false; + + phys_addr = pci_resource_start(pci_dev, bar); + bar_len = pci_resource_len(pci_dev, bar); + + if ((offset + len) < offset) { + dev_err(&pci_dev->dev, "%s: cap offset+len overflow detected\n", + __func__); + return false; + } + + if (offset + len > bar_len) { + dev_err(&pci_dev->dev, "%s: bar shorter than cap offset+len\n", + __func__); + return false; + } + + region->len = len; + region->addr = (u64) phys_addr + offset; + + return true; +} + static const struct virtio_config_ops virtio_pci_config_nodev_ops = { .get = NULL, .set = NULL, @@ -458,6 +551,7 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = { .bus_name = vp_bus_name, .set_vq_affinity = vp_set_vq_affinity, .get_vq_affinity = vp_get_vq_affinity, + .get_shm_region = vp_get_shm_region, }; static const struct virtio_config_ops virtio_pci_config_ops = { @@ -474,6 +568,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = { .bus_name = vp_bus_name, .set_vq_affinity = vp_set_vq_affinity, .get_vq_affinity = vp_get_vq_affinity, + .get_shm_region = vp_get_shm_region, }; /** diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h index 90007a1abcab1..3a86f36d7e3d9 100644 --- a/include/uapi/linux/virtio_pci.h +++ b/include/uapi/linux/virtio_pci.h @@ -113,6 +113,8 @@ #define VIRTIO_PCI_CAP_DEVICE_CFG 4 /* PCI configuration access */ #define VIRTIO_PCI_CAP_PCI_CFG 5 +/* Additional shared memory capability */ +#define VIRTIO_PCI_CAP_SHARED_MEMORY_CFG 8 /* This is the PCI capability header: */ struct virtio_pci_cap { @@ -121,11 +123,18 @@ struct virtio_pci_cap { __u8 cap_len; /* Generic PCI field: capability length */ __u8 cfg_type; /* Identifies the structure. */ __u8 bar; /* Where to find it. */ - __u8 padding[3]; /* Pad to full dword. */ + __u8 id; /* Multiple capabilities of the same type */ + __u8 padding[2]; /* Pad to full dword. */ __le32 offset; /* Offset within bar. */ __le32 length; /* Length of the structure, in bytes. */ }; +struct virtio_pci_cap64 { + struct virtio_pci_cap cap; + __le32 offset_hi; /* Most sig 32 bits of offset */ + __le32 length_hi; /* Most sig 32 bits of length */ +}; + struct virtio_pci_notify_cap { struct virtio_pci_cap cap; __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */ -- GitLab From 38e895487afc2ed42c11045853cbb3fa20b52b6e Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf <sebastien.boeuf@intel.com> Date: Wed, 19 Aug 2020 18:19:43 -0400 Subject: [PATCH 1031/1494] virtio: Implement get_shm_region for MMIO transport On MMIO a new set of registers is defined for finding SHM regions. Add their definitions and use them to find the region. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com> Cc: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Cc: "Michael S. Tsirkin" <mst@redhat.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- drivers/virtio/virtio_mmio.c | 31 +++++++++++++++++++++++++++++++ include/uapi/linux/virtio_mmio.h | 11 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 627ac04874940..238383ff1064c 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -498,6 +498,36 @@ static const char *vm_bus_name(struct virtio_device *vdev) return vm_dev->pdev->name; } +static bool vm_get_shm_region(struct virtio_device *vdev, + struct virtio_shm_region *region, u8 id) +{ + struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); + u64 len, addr; + + /* Select the region we're interested in */ + writel(id, vm_dev->base + VIRTIO_MMIO_SHM_SEL); + + /* Read the region size */ + len = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_LOW); + len |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_HIGH) << 32; + + region->len = len; + + /* Check if region length is -1. If that's the case, the shared memory + * region does not exist and there is no need to proceed further. + */ + if (len == ~(u64)0) + return false; + + /* Read the region base address */ + addr = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_LOW); + addr |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_HIGH) << 32; + + region->addr = addr; + + return true; +} + static const struct virtio_config_ops virtio_mmio_config_ops = { .get = vm_get, .set = vm_set, @@ -510,6 +540,7 @@ static const struct virtio_config_ops virtio_mmio_config_ops = { .get_features = vm_get_features, .finalize_features = vm_finalize_features, .bus_name = vm_bus_name, + .get_shm_region = vm_get_shm_region, }; diff --git a/include/uapi/linux/virtio_mmio.h b/include/uapi/linux/virtio_mmio.h index c4b09689ab644..0650f91bea6c7 100644 --- a/include/uapi/linux/virtio_mmio.h +++ b/include/uapi/linux/virtio_mmio.h @@ -122,6 +122,17 @@ #define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 #define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 +/* Shared memory region id */ +#define VIRTIO_MMIO_SHM_SEL 0x0ac + +/* Shared memory region length, 64 bits in two halves */ +#define VIRTIO_MMIO_SHM_LEN_LOW 0x0b0 +#define VIRTIO_MMIO_SHM_LEN_HIGH 0x0b4 + +/* Shared memory region base address, 64 bits in two halves */ +#define VIRTIO_MMIO_SHM_BASE_LOW 0x0b8 +#define VIRTIO_MMIO_SHM_BASE_HIGH 0x0bc + /* Configuration atomicity value */ #define VIRTIO_MMIO_CONFIG_GENERATION 0x0fc -- GitLab From 6a8a58acfe82a49e91a3c3e1c1c07865024b4ff4 Mon Sep 17 00:00:00 2001 From: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> Date: Thu, 10 Sep 2020 12:52:50 +0300 Subject: [PATCH 1032/1494] drm/imx/dcss: fix compilation issue on 32bit When compiling for 32bit platforms, the compilation fails with: ERROR: modpost: "__aeabi_ldivmod" [drivers/gpu/drm/imx/dcss/imx-dcss.ko] undefined! ERROR: modpost: "__aeabi_uldivmod" [drivers/gpu/drm/imx/dcss/imx-dcss.ko] undefined! This patch adds a dependency on ARM64 since no 32bit SoCs have DCSS, so far. Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> Reported-by: Daniel Vetter <daniel@ffwll.ch> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200910095250.7663-1-laurentiu.palcu@oss.nxp.com --- drivers/gpu/drm/imx/dcss/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/dcss/Kconfig b/drivers/gpu/drm/imx/dcss/Kconfig index 69860de8861f4..2b17a964ff05a 100644 --- a/drivers/gpu/drm/imx/dcss/Kconfig +++ b/drivers/gpu/drm/imx/dcss/Kconfig @@ -3,7 +3,7 @@ config DRM_IMX_DCSS select IMX_IRQSTEER select DRM_KMS_CMA_HELPER select VIDEOMODE_HELPERS - depends on DRM && ARCH_MXC + depends on DRM && ARCH_MXC && ARM64 help Choose this if you have a NXP i.MX8MQ based system and want to use the Display Controller Subsystem. This option enables DCSS support. -- GitLab From 130cdec4e12836cb2d5346216902c49800a07c33 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Thu, 10 Sep 2020 13:07:48 +0300 Subject: [PATCH 1033/1494] drm/vc4: hdmi: Fix off by ones in vc4_hdmi_read/write() The variant->registers[] has ->num_registers elements so the > comparison needs to be changes to >= to prevent an out of bounds access. Fixes: 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200910100748.GA79916@mwanda --- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index a5f1354e3e067..47364bd3960dd 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -398,7 +398,7 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, const struct vc4_hdmi_variant *variant = hdmi->variant; void __iomem *base; - if (reg > variant->num_registers) { + if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, "Invalid register ID %u\n", reg); return 0; @@ -424,7 +424,7 @@ static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, const struct vc4_hdmi_variant *variant = hdmi->variant; void __iomem *base; - if (reg > variant->num_registers) { + if (reg >= variant->num_registers) { dev_warn(&hdmi->pdev->dev, "Invalid register ID %u\n", reg); return; -- GitLab From 14929c5ae8b6dc4ad89d4888cfc0bd7678eee04c Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Thu, 10 Sep 2020 13:08:25 +0300 Subject: [PATCH 1034/1494] drm/vc4: hdmi: Fix NULL vs IS_ERR() checks in vc5_hdmi_init_resources() The devm_ioremap() function never returns error pointers, it returns NULL. Fixes: 8323989140f3 ("drm/vc4: hdmi: Support the BCM2711 HDMI controllers") Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200910100825.GC79916@mwanda --- drivers/gpu/drm/vc4/vc4_hdmi.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d0792915436c4..03825596a3085 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1545,64 +1545,64 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->hdmicore_regs)) - return PTR_ERR(vc4_hdmi->hdmicore_regs); + if (!vc4_hdmi->hdmicore_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd"); if (!res) return -ENODEV; vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->hd_regs)) - return PTR_ERR(vc4_hdmi->hd_regs); + if (!vc4_hdmi->hd_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec"); if (!res) return -ENODEV; vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->cec_regs)) - return PTR_ERR(vc4_hdmi->cec_regs); + if (!vc4_hdmi->cec_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc"); if (!res) return -ENODEV; vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->csc_regs)) - return PTR_ERR(vc4_hdmi->csc_regs); + if (!vc4_hdmi->csc_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp"); if (!res) return -ENODEV; vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->dvp_regs)) - return PTR_ERR(vc4_hdmi->dvp_regs); + if (!vc4_hdmi->dvp_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); if (!res) return -ENODEV; vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->phy_regs)) - return PTR_ERR(vc4_hdmi->phy_regs); + if (!vc4_hdmi->phy_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet"); if (!res) return -ENODEV; vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->ram_regs)) - return PTR_ERR(vc4_hdmi->ram_regs); + if (!vc4_hdmi->ram_regs) + return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm"); if (!res) return -ENODEV; vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (IS_ERR(vc4_hdmi->rm_regs)) - return PTR_ERR(vc4_hdmi->rm_regs); + if (!vc4_hdmi->rm_regs) + return -ENOMEM; vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); if (IS_ERR(vc4_hdmi->hsm_clock)) { -- GitLab From ac5037afefd33fea9a9c1a4a5ac46ece396e7465 Mon Sep 17 00:00:00 2001 From: Robin Murphy <robin.murphy@arm.com> Date: Thu, 3 Sep 2020 14:59:23 +0100 Subject: [PATCH 1035/1494] drm/panfrost: Set DMA max segment size Since all we do with scatterlists is map them in the MMU, we don't have any hardware constraints on how they're laid out. Let the DMA layer know so it won't warn when DMA API debugging is enabled. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/04371bc36512076b7feee07f854e56b80675d953.1599141563.git.robin.murphy@arm.com --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index e0f190e438139..eea049c640a67 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -344,6 +344,7 @@ int panfrost_gpu_init(struct panfrost_device *pfdev) dma_set_mask_and_coherent(pfdev->dev, DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features))); + dma_set_max_seg_size(pfdev->dev, UINT_MAX); irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu"); if (irq <= 0) -- GitLab From 8c3c818c23a5bbce6ff180dd2ee04415241df77c Mon Sep 17 00:00:00 2001 From: Steven Price <steven.price@arm.com> Date: Wed, 9 Sep 2020 13:29:57 +0100 Subject: [PATCH 1036/1494] drm/panfrost: Ensure GPU quirks are always initialised The GPU 'CONFIG' registers used to work around hardware issues are cleared on reset so need to be programmed every time the GPU is reset. However panfrost_device_reset() failed to do this. To avoid this in future instead move the call to panfrost_gpu_init_quirks() to panfrost_gpu_power_on() so that the regsiters are always programmed just before the cores are powered. Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver") Signed-off-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200909122957.51667-1-steven.price@arm.com --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index eea049c640a67..c7c5da5a31d47 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -305,6 +305,8 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) int ret; u32 val; + panfrost_gpu_init_quirks(pfdev); + /* Just turn on everything for now */ gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present); ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO, @@ -357,7 +359,6 @@ int panfrost_gpu_init(struct panfrost_device *pfdev) return err; } - panfrost_gpu_init_quirks(pfdev); panfrost_gpu_power_on(pfdev); return 0; -- GitLab From 166774a2c2c6b82da5d984f587567071ff00c1f3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Thu, 10 Sep 2020 13:12:25 +0200 Subject: [PATCH 1037/1494] drm/i915: Fix slightly botched merge in __reloc_entry_gpu This function should be an int, not a bool. Presumably because we had the same 2 reverts in a slightly different way, git got confused. Thanks to Dan for reporting. :) The conflict is between the 3 reverts in drm-fixes: 4993a8a37808 ("Revert "drm/i915: Remove i915_gem_object_get_dirty_page()"") ad5d95e4d538 ("Revert "drm/i915/gem: Async GPU relocations only"") 20561da3a2e1 ("Revert "drm/i915/gem: Delete unused code"") And the slightly different combined revert in drm-intel-gt-next, but with the same goal: 102a0a9051f4 ("Revert "drm/i915/gem: Async GPU relocations only"") In the merge commit 1f4b2aca794f ("Merge tag 'drm-intel-gt-next-2020-09-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next") things went wrong, but the merge commit view now doesn't show any conflict anymore (as git tends to do when the resolution picks one or the other branch). The need to handle other than just true/false error codes in __reloc_entry_gpu was added in the dma_resv locking changes in c43ce12328df ("drm/i915: Use per object locking in execbuf, v12.") Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Cc: Dave Airlie <airlied@redhat.com> [danvet: Explain this entire saga a lot better, adding tons of commit references. Also note that this was merged before full intel-gfx-CI results, only after BAT, since the breakage at the BAT run is already severe enough to block all pre-merge testing.] Fixes: 1f4b2aca794f ("Merge tag 'drm-intel-gt-next-2020-09-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next") Acked-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200910111225.2184193-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 804339255df19..5509946f1a1da 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1437,7 +1437,7 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static bool __reloc_entry_gpu(struct i915_execbuffer *eb, +static int __reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1456,7 +1456,7 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, batch = reloc_gpu(eb, vma, len); if (batch == ERR_PTR(-EDEADLK)) - return (s64)-EDEADLK; + return -EDEADLK; else if (IS_ERR(batch)) return false; -- GitLab From 90ad200b4cbc92e160c3f3331bb999f87cc0fbfd Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri, 4 Sep 2020 16:39:18 +0200 Subject: [PATCH 1038/1494] drm/armada: Use devm_drm_dev_alloc Also remove the now no longer needed build bug on since that's already not needed anymore with drmm_add_final_kfree. Conversion to managed drm_device cleanup is easy, the final drm_dev_put() is already the last thing in both the bind unbind as in the unbind flow. Also, this relies on component.c correctly wrapping bind&unbind in separate devres groups, which it does. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Cc: Russell King <linux@armlinux.org.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200904143941.110665-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/armada/armada_drv.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 5fc25c3f445c2..a8d5908b39229 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -87,24 +87,13 @@ static int armada_drm_bind(struct device *dev) "armada-drm")) return -EBUSY; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - /* - * The drm_device structure must be at the start of - * armada_private for drm_dev_put() to work correctly. - */ - BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0); - - ret = drm_dev_init(&priv->drm, &armada_drm_driver, dev); - if (ret) { - dev_err(dev, "[" DRM_NAME ":%s] drm_dev_init failed: %d\n", - __func__, ret); - kfree(priv); - return ret; + priv = devm_drm_dev_alloc(dev, &armada_drm_driver, + struct armada_private, drm); + if (IS_ERR(priv)) { + dev_err(dev, "[" DRM_NAME ":%s] devm_drm_dev_alloc failed: %li\n", + __func__, PTR_ERR(priv)); + return PTR_ERR(priv); } - drmm_add_final_kfree(&priv->drm, priv); /* Remove early framebuffers */ ret = drm_fb_helper_remove_conflicting_framebuffers(NULL, @@ -174,7 +163,6 @@ static int armada_drm_bind(struct device *dev) err_kms: drm_mode_config_cleanup(&priv->drm); drm_mm_takedown(&priv->linear); - drm_dev_put(&priv->drm); return ret; } @@ -194,8 +182,6 @@ static void armada_drm_unbind(struct device *dev) drm_mode_config_cleanup(&priv->drm); drm_mm_takedown(&priv->linear); - - drm_dev_put(&priv->drm); } static int compare_of(struct device *dev, void *data) -- GitLab From dad75a5208ec88779d9ccd2c95ef5de659209208 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri, 4 Sep 2020 16:39:19 +0200 Subject: [PATCH 1039/1494] drm/armada: Don't use drm_device->dev_private Upcasting using a container_of macro is more typesafe, faster and easier for the compiler to optimize. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Cc: Russell King <linux@armlinux.org.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200904143941.110665-3-daniel.vetter@ffwll.ch --- drivers/gpu/drm/armada/armada_crtc.c | 4 ++-- drivers/gpu/drm/armada/armada_debugfs.c | 2 +- drivers/gpu/drm/armada/armada_drm.h | 2 ++ drivers/gpu/drm/armada/armada_drv.c | 4 +--- drivers/gpu/drm/armada/armada_fbdev.c | 4 ++-- drivers/gpu/drm/armada/armada_gem.c | 4 ++-- drivers/gpu/drm/armada/armada_overlay.c | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 38dfaa46d3069..a887b6a5f8bd7 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -757,7 +757,7 @@ static int armada_drm_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) static void armada_drm_crtc_destroy(struct drm_crtc *crtc) { struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); - struct armada_private *priv = crtc->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(crtc->dev); if (dcrtc->cursor_obj) drm_gem_object_put(&dcrtc->cursor_obj->obj); @@ -901,7 +901,7 @@ static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, struct resource *res, int irq, const struct armada_variant *variant, struct device_node *port) { - struct armada_private *priv = drm->dev_private; + struct armada_private *priv = drm_to_armada_dev(drm); struct armada_crtc *dcrtc; struct drm_plane *primary; void __iomem *base; diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c index c6fc2f1d58e99..29f4b52e3c8d3 100644 --- a/drivers/gpu/drm/armada/armada_debugfs.c +++ b/drivers/gpu/drm/armada/armada_debugfs.c @@ -19,7 +19,7 @@ static int armada_debugfs_gem_linear_show(struct seq_file *m, void *data) { struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_printer p = drm_seq_file_printer(m); mutex_lock(&priv->linear_lock); diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index a11bdaccbb336..6a5a879325766 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -73,6 +73,8 @@ struct armada_private { #endif }; +#define drm_to_armada_dev(dev) container_of(dev, struct armada_private, drm) + int armada_fbdev_init(struct drm_device *); void armada_fbdev_fini(struct drm_device *); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index a8d5908b39229..980d3f1f8f16e 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -106,8 +106,6 @@ static int armada_drm_bind(struct device *dev) return ret; } - priv->drm.dev_private = priv; - dev_set_drvdata(dev, &priv->drm); /* Mode setting support */ @@ -169,7 +167,7 @@ static int armada_drm_bind(struct device *dev) static void armada_drm_unbind(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct armada_private *priv = drm->dev_private; + struct armada_private *priv = drm_to_armada_dev(drm); drm_kms_helper_poll_fini(&priv->drm); armada_fbdev_fini(&priv->drm); diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 0c46012755078..38f5170c0fea6 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -117,7 +117,7 @@ static const struct drm_fb_helper_funcs armada_fb_helper_funcs = { int armada_fbdev_init(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_fb_helper *fbh; int ret; @@ -151,7 +151,7 @@ int armada_fbdev_init(struct drm_device *dev) void armada_fbdev_fini(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_fb_helper *fbh = priv->fbdev; if (fbh) { diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 8005614d2e6ba..ecf8a55e93d93 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -39,7 +39,7 @@ static size_t roundup_gem_size(size_t size) void armada_gem_free_object(struct drm_gem_object *obj) { struct armada_gem_object *dobj = drm_to_armada_gem(obj); - struct armada_private *priv = obj->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(obj->dev); DRM_DEBUG_DRIVER("release obj %p\n", dobj); @@ -77,7 +77,7 @@ void armada_gem_free_object(struct drm_gem_object *obj) int armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); size_t size = obj->obj.size; if (obj->page || obj->linear) diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 07f0da4d9ba19..30e01101f59ed 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -344,7 +344,7 @@ static int armada_overlay_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val) { - struct armada_private *priv = plane->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(plane->dev); #define K2R(val) (((val) >> 0) & 0xff) #define K2G(val) (((val) >> 8) & 0xff) @@ -412,7 +412,7 @@ static int armada_overlay_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) { - struct armada_private *priv = plane->dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(plane->dev); #define C2K(c,s) (((c) >> (s)) & 0xff) #define R2BGR(r,g,b,s) (C2K(r,s) << 0 | C2K(g,s) << 8 | C2K(b,s) << 16) @@ -505,7 +505,7 @@ static const struct drm_prop_enum_list armada_drm_colorkey_enum_list[] = { static int armada_overlay_create_properties(struct drm_device *dev) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); if (priv->colorkey_prop) return 0; @@ -539,7 +539,7 @@ static int armada_overlay_create_properties(struct drm_device *dev) int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) { - struct armada_private *priv = dev->dev_private; + struct armada_private *priv = drm_to_armada_dev(dev); struct drm_mode_object *mobj; struct drm_plane *overlay; int ret; -- GitLab From c2c25c1cf96927a0b6ddb6aaa063f1fdcc90d749 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri, 4 Sep 2020 16:39:20 +0200 Subject: [PATCH 1040/1494] drm/aspeed: Use managed drmm_mode_config_cleanup Since aspeed doesn't use devm_kzalloc anymore we can use the managed mode config cleanup. v2: Keep call order as suggested by Sam. Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: Joel Stanley <joel@jms.id.au> Cc: Andrew Jeffery <andrew@aj.id.au> Cc: linux-aspeed@lists.ozlabs.org Cc: linux-arm-kernel@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20200904143941.110665-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/aspeed/aspeed_gfx_drv.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 903f4f3046472..2b424b2b85cc8 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -63,15 +63,21 @@ static const struct drm_mode_config_funcs aspeed_gfx_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static void aspeed_gfx_setup_mode_config(struct drm_device *drm) +static int aspeed_gfx_setup_mode_config(struct drm_device *drm) { - drm_mode_config_init(drm); + int ret; + + ret = drmm_mode_config_init(drm); + if (ret) + return ret; drm->mode_config.min_width = 0; drm->mode_config.min_height = 0; drm->mode_config.max_width = 800; drm->mode_config.max_height = 600; drm->mode_config.funcs = &aspeed_gfx_mode_config_funcs; + + return ret; } static irqreturn_t aspeed_gfx_irq_handler(int irq, void *data) @@ -144,7 +150,9 @@ static int aspeed_gfx_load(struct drm_device *drm) writel(0, priv->base + CRT_CTRL1); writel(0, priv->base + CRT_CTRL2); - aspeed_gfx_setup_mode_config(drm); + ret = aspeed_gfx_setup_mode_config(drm); + if (ret < 0) + return ret; ret = drm_vblank_init(drm, 1); if (ret < 0) { @@ -179,7 +187,6 @@ static int aspeed_gfx_load(struct drm_device *drm) static void aspeed_gfx_unload(struct drm_device *drm) { drm_kms_helper_poll_fini(drm); - drm_mode_config_cleanup(drm); } DEFINE_DRM_GEM_CMA_FOPS(fops); -- GitLab From bcc0ef7f57e51e5a5607eafb2a8ab63c6c1f21ff Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed, 9 Sep 2020 14:07:45 +0200 Subject: [PATCH 1041/1494] drm/vgem: Use devm_drm_dev_alloc This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vgem, we don't bind), and also when unregistering the device (very much the case for vgem). Therefore we can rely on devres even though vgem isn't a proper platform device driver. This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps. v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc. v3: Fix error code handling (Melissa) Cc: Melissa Wen <melissa.srw@gmail.com> Reviewed-by: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Emil Velikov <emil.velikov@collabora.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Rob Clark <robdclark@chromium.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200909120745.716178-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/vgem/vgem_drv.c | 55 ++++++++++++++------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 15dd41e67de3b..cb884c8900654 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -401,16 +401,8 @@ static int vgem_prime_mmap(struct drm_gem_object *obj, return 0; } -static void vgem_release(struct drm_device *dev) -{ - struct vgem_device *vgem = container_of(dev, typeof(*vgem), drm); - - platform_device_unregister(vgem->platform); -} - static struct drm_driver vgem_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER, - .release = vgem_release, .open = vgem_open, .postclose = vgem_postclose, .gem_free_object_unlocked = vgem_gem_free_object, @@ -442,48 +434,49 @@ static struct drm_driver vgem_driver = { static int __init vgem_init(void) { int ret; + struct platform_device *pdev; - vgem_device = kzalloc(sizeof(*vgem_device), GFP_KERNEL); - if (!vgem_device) - return -ENOMEM; + pdev = platform_device_register_simple("vgem", -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - vgem_device->platform = - platform_device_register_simple("vgem", -1, NULL, 0); - if (IS_ERR(vgem_device->platform)) { - ret = PTR_ERR(vgem_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; } - dma_coerce_mask_and_coherent(&vgem_device->platform->dev, + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - ret = drm_dev_init(&vgem_device->drm, &vgem_driver, - &vgem_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vgem_device->drm, vgem_device); + + vgem_device = devm_drm_dev_alloc(&pdev->dev, &vgem_driver, + struct vgem_device, drm); + if (IS_ERR(vgem_device)) { + ret = PTR_ERR(vgem_device); + goto out_devres; + } + vgem_device->platform = pdev; /* Final step: expose the device/driver to userspace */ ret = drm_dev_register(&vgem_device->drm, 0); if (ret) - goto out_put; + goto out_devres; return 0; -out_put: - drm_dev_put(&vgem_device->drm); - platform_device_unregister(vgem_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vgem_device->platform); -out_free: - kfree(vgem_device); + platform_device_unregister(pdev); return ret; } static void __exit vgem_exit(void) { + struct platform_device *pdev = vgem_device->platform; + drm_dev_unregister(&vgem_device->drm); - drm_dev_put(&vgem_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); } module_init(vgem_init); -- GitLab From 53d77aaa3f76d203db8b681d2eb80b6b2fd6195a Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed, 9 Sep 2020 11:18:33 +0200 Subject: [PATCH 1042/1494] drm/vkms: Use devm_drm_dev_alloc This means we also need to slightly restructure the exit code, so that final cleanup of the drm_device is triggered by unregistering the platform device. Note that devres is both clean up when the driver is unbound (not the case for vkms, we don't bind), and also when unregistering the device (very much the case for vkms). Therefore we can rely on devres even though vkms isn't a proper platform device driver. This also somewhat untangles the load code, since the drm and platform device setup are no longer interleaved, but two distinct steps. v2: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc. v3: Only deref vkms_device after checking it (Melissa) Reviewed-by: Melissa Wen <melissa.srw@gmail.com> Cc: Melissa Wen <melissa.srw@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: Rodrigo Siqueira <rodrigosiqueiramelo@gmail.com> Cc: Haneen Mohammed <hamohammed.sa@gmail.com> Cc: Daniel Vetter <daniel@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200909091833.440548-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/vkms/vkms_drv.c | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83dd5567de8b5..cb0b6230c22ce 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -61,9 +61,6 @@ static void vkms_release(struct drm_device *dev) { struct vkms_device *vkms = container_of(dev, struct vkms_device, drm); - platform_device_unregister(vkms->platform); - drm_atomic_helper_shutdown(&vkms->drm); - drm_mode_config_cleanup(&vkms->drm); destroy_workqueue(vkms->output.composer_workq); } @@ -144,30 +141,31 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) static int __init vkms_init(void) { int ret; + struct platform_device *pdev; - vkms_device = kzalloc(sizeof(*vkms_device), GFP_KERNEL); - if (!vkms_device) - return -ENOMEM; + pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); - vkms_device->platform = - platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); - if (IS_ERR(vkms_device->platform)) { - ret = PTR_ERR(vkms_device->platform); - goto out_free; + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + ret = -ENOMEM; + goto out_unregister; } - ret = drm_dev_init(&vkms_device->drm, &vkms_driver, - &vkms_device->platform->dev); - if (ret) - goto out_unregister; - drmm_add_final_kfree(&vkms_device->drm, vkms_device); + vkms_device = devm_drm_dev_alloc(&pdev->dev, &vkms_driver, + struct vkms_device, drm); + if (IS_ERR(vkms_device)) { + ret = PTR_ERR(vkms_device); + goto out_devres; + } + vkms_device->platform = pdev; ret = dma_coerce_mask_and_coherent(vkms_device->drm.dev, DMA_BIT_MASK(64)); if (ret) { DRM_ERROR("Could not initialize DMA support\n"); - goto out_put; + goto out_devres; } vkms_device->drm.irq_enabled = true; @@ -175,39 +173,41 @@ static int __init vkms_init(void) ret = drm_vblank_init(&vkms_device->drm, 1); if (ret) { DRM_ERROR("Failed to vblank\n"); - goto out_put; + goto out_devres; } ret = vkms_modeset_init(vkms_device); if (ret) - goto out_put; + goto out_devres; ret = drm_dev_register(&vkms_device->drm, 0); if (ret) - goto out_put; + goto out_devres; return 0; -out_put: - drm_dev_put(&vkms_device->drm); - platform_device_unregister(vkms_device->platform); - return ret; +out_devres: + devres_release_group(&pdev->dev, NULL); out_unregister: - platform_device_unregister(vkms_device->platform); -out_free: - kfree(vkms_device); + platform_device_unregister(pdev); return ret; } static void __exit vkms_exit(void) { + struct platform_device *pdev; + if (!vkms_device) { DRM_INFO("vkms_device is NULL.\n"); return; } + pdev = vkms_device->platform; + drm_dev_unregister(&vkms_device->drm); - drm_dev_put(&vkms_device->drm); + drm_atomic_helper_shutdown(&vkms_device->drm); + devres_release_group(&pdev->dev, NULL); + platform_device_unregister(pdev); } module_init(vkms_init); -- GitLab From 075342ea3d93044d68f821cf91c1a1a7d2fa569e Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Mon, 7 Sep 2020 10:22:25 +0200 Subject: [PATCH 1043/1494] drm/xlnx: Use devm_drm_dev_alloc Gets rid of drmm_add_final_kfree, which I want to unexport so that it stops confusion people about this transitional state of rolling drm managed memory out. This also fixes the missing drm_dev_put in the error path of the probe code. v2: Drop the misplaced drm_dev_put from zynqmp_dpsub_drm_init (all other paths leaked on error, this should have been in zynqmp_dpsub_probe), now that subsumed by the auto-cleanup of devm_drm_dev_alloc. Reviewed-by: Hyun Kwon <hyun.kwon@xilinx.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: Hyun Kwon <hyun.kwon@xilinx.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Cc: Michal Simek <michal.simek@xilinx.com> Cc: linux-arm-kernel@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20200907082225.150837-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/xlnx/zynqmp_dpsub.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c index 26328c76305be..8e69303aad3f7 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c +++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c @@ -111,7 +111,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) /* Initialize mode config, vblank and the KMS poll helper. */ ret = drmm_mode_config_init(drm); if (ret < 0) - goto err_dev_put; + return ret; drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs; drm->mode_config.min_width = 0; @@ -121,7 +121,7 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) ret = drm_vblank_init(drm, 1); if (ret) - goto err_dev_put; + return ret; drm->irq_enabled = 1; @@ -154,8 +154,6 @@ static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub) err_poll_fini: drm_kms_helper_poll_fini(drm); -err_dev_put: - drm_dev_put(drm); return ret; } @@ -208,27 +206,16 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev) int ret; /* Allocate private data. */ - dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL); - if (!dpsub) - return -ENOMEM; + dpsub = devm_drm_dev_alloc(&pdev->dev, &zynqmp_dpsub_drm_driver, + struct zynqmp_dpsub, drm); + if (IS_ERR(dpsub)) + return PTR_ERR(dpsub); dpsub->dev = &pdev->dev; platform_set_drvdata(pdev, dpsub); dma_set_mask(dpsub->dev, DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT)); - /* - * Initialize the DRM device early, as the DRM core mandates usage of - * the managed memory helpers tied to the DRM device. - */ - ret = drm_dev_init(&dpsub->drm, &zynqmp_dpsub_drm_driver, &pdev->dev); - if (ret < 0) { - kfree(dpsub); - return ret; - } - - drmm_add_final_kfree(&dpsub->drm, dpsub); - /* Try the reserved memory. Proceed if there's none. */ of_reserved_mem_device_init(&pdev->dev); @@ -286,8 +273,6 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev) clk_disable_unprepare(dpsub->apb_clk); of_reserved_mem_device_release(&pdev->dev); - drm_dev_put(drm); - return 0; } -- GitLab From 268d0a92600e50820916a5aeda0242a7153a2fd7 Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Thu, 10 Sep 2020 22:06:10 +0800 Subject: [PATCH 1044/1494] drm/i810: make i810_flush_queue() return void This function always return '0' and no callers use the return value. So make it a void function. This eliminates the following coccicheck warning: drivers/gpu/drm/i810/i810_dma.c:860:8-11: Unneeded variable: "ret". Return "0" on line 885 Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200910140610.1191578-1-yanaijie@huawei.com --- drivers/gpu/drm/i810/i810_dma.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 303c2d483c6ea..88250860f8e45 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -853,11 +853,11 @@ static void i810_dma_quiescent(struct drm_device *dev) i810_wait_ring(dev, dev_priv->ring.Size - 8); } -static int i810_flush_queue(struct drm_device *dev) +static void i810_flush_queue(struct drm_device *dev) { drm_i810_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; - int i, ret = 0; + int i; RING_LOCALS; i810_kernel_lost_context(dev); @@ -882,7 +882,7 @@ static int i810_flush_queue(struct drm_device *dev) DRM_DEBUG("still on client\n"); } - return ret; + return; } /* Must be called with the lock held */ -- GitLab From 910e1ca6f36f48b7911e72dc8b6667d652031d97 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor <natechancellor@gmail.com> Date: Thu, 10 Sep 2020 10:04:02 -0700 Subject: [PATCH 1045/1494] drm/vc4: Update type of reg parameter in vc4_hdmi_{read,write} Clang warns 100+ times in the vc4 driver along the lines of: drivers/gpu/drm/vc4/vc4_hdmi_phy.c:518:13: warning: implicit conversion from enumeration type 'enum vc4_hdmi_field' to different enumeration type 'enum vc4_hdmi_regs' [-Wenum-conversion] HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ The HDMI_READ and HDMI_WRITE macros pass in enumerators of type vc4_hdmi_field but vc4_hdmi_write and vc4_hdmi_read expect a enumerator of type vc4_hdmi_regs, causing a warning for every instance of this. Update the parameter type so there is no more mismatch. Fixes: 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction") Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> Link: https://github.com/ClangBuiltLinux/linux/issues/1149 Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200910170401.3857250-1-natechancellor@gmail.com --- drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index 47364bd3960dd..7c6b4818f2455 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -392,7 +392,7 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi, } static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, - enum vc4_hdmi_regs reg) + enum vc4_hdmi_field reg) { const struct vc4_hdmi_register *field; const struct vc4_hdmi_variant *variant = hdmi->variant; @@ -417,7 +417,7 @@ static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi, #define HDMI_READ(reg) vc4_hdmi_read(vc4_hdmi, reg) static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi, - enum vc4_hdmi_regs reg, + enum vc4_hdmi_field reg, u32 value) { const struct vc4_hdmi_register *field; -- GitLab From 4494346392204ab4387d08eb5e089be8e7e1b74e Mon Sep 17 00:00:00 2001 From: Nathan Chancellor <natechancellor@gmail.com> Date: Thu, 10 Sep 2020 10:18:32 -0700 Subject: [PATCH 1046/1494] drm/vc4: Fix bitwise OR versus ternary operator in vc4_plane_mode_set Clang warns: drivers/gpu/drm/vc4/vc4_plane.c:901:27: warning: operator '?:' has lower precedence than '|'; '|' will be evaluated first [-Wbitwise-conditional-parentheses] fb->format->has_alpha ? ~~~~~~~~~~~~~~~~~~~~~ ^ drivers/gpu/drm/vc4/vc4_plane.c:901:27: note: place parentheses around the '|' expression to silence this warning fb->format->has_alpha ? ~~~~~~~~~~~~~~~~~~~~~ ^ drivers/gpu/drm/vc4/vc4_plane.c:901:27: note: place parentheses around the '?:' expression to evaluate it first fb->format->has_alpha ? ~~~~~~~~~~~~~~~~~~~~~~^ 1 warning generated. Add the parentheses as that was clearly intended, otherwise SCALER5_CTL2_ALPHA_PREMULT won't be added to the list. Fixes: c54619b0bfb3 ("drm/vc4: Add support for the BCM2711 HVS5") Signed-off-by: Nathan Chancellor <natechancellor@gmail.com> Link: https://github.com/ClangBuiltLinux/linux/issues/1150 Signed-off-by: Maxime Ripard <maxime@cerno.tech> Link: https://patchwork.freedesktop.org/patch/msgid/20200910171831.4112580-1-natechancellor@gmail.com --- drivers/gpu/drm/vc4/vc4_plane.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 24d7e6db6fdd2..89543fa8ca4de 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -898,8 +898,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, vc4_dlist_write(vc4_state, VC4_SET_FIELD(state->alpha >> 4, SCALER5_CTL2_ALPHA) | - fb->format->has_alpha ? - SCALER5_CTL2_ALPHA_PREMULT : 0 | + (fb->format->has_alpha ? + SCALER5_CTL2_ALPHA_PREMULT : 0) | (mix_plane_alpha ? SCALER5_CTL2_ALPHA_MIX : 0) | VC4_SET_FIELD(fb->format->has_alpha ? -- GitLab From 5e0e390d02257b9176095dd65a8b107d93499a25 Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Thu, 10 Sep 2020 12:52:25 +0300 Subject: [PATCH 1047/1494] drm/i915: disable all display features when no display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable all display feature flags when there are no pipes i.e. there is no display. This should help with not having to additionally check for HAS_DISPLAY() when a feature flag check would suffice. Also disable modeset and atomic driver features. Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200910095227.9466-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_device_info.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index e2aa5bc3a6e01..adc836f15fde1 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -516,6 +516,14 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) S32_MAX), USEC_PER_SEC)); } + + if (!HAS_DISPLAY(dev_priv)) { + dev_priv->drm.driver_features &= ~(DRIVER_MODESET | + DRIVER_ATOMIC); + memset(&info->display, 0, sizeof(info->display)); + memset(runtime->num_sprites, 0, sizeof(runtime->num_sprites)); + memset(runtime->num_scalers, 0, sizeof(runtime->num_scalers)); + } } void intel_driver_caps_print(const struct intel_driver_caps *caps, -- GitLab From 59c0df3cd27c330f1282722004369d173c9c2a3d Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Thu, 10 Sep 2020 12:52:26 +0300 Subject: [PATCH 1048/1494] drm/i915: move gen4 GCDGMBUS save/restore to display save/restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Logically part of the display save/restore. No functional changes. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200910095227.9466-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_suspend.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index ed2be3489f8e0..4a93247942b71 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -34,6 +34,8 @@ static void i915_save_display(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; + /* Display arbitration control */ if (INTEL_GEN(dev_priv) <= 4) dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); @@ -41,10 +43,20 @@ static void i915_save_display(struct drm_i915_private *dev_priv) /* save FBC interval */ if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); + + if (IS_GEN(dev_priv, 4)) + pci_read_config_word(pdev, GCDGMBUS, + &dev_priv->regfile.saveGCDGMBUS); } static void i915_restore_display(struct drm_i915_private *dev_priv) { + struct pci_dev *pdev = dev_priv->drm.pdev; + + if (IS_GEN(dev_priv, 4)) + pci_write_config_word(pdev, GCDGMBUS, + dev_priv->regfile.saveGCDGMBUS); + /* Display arbitration */ if (INTEL_GEN(dev_priv) <= 4) I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB); @@ -61,15 +73,10 @@ static void i915_restore_display(struct drm_i915_private *dev_priv) int i915_save_state(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev_priv->drm.pdev; int i; i915_save_display(dev_priv); - if (IS_GEN(dev_priv, 4)) - pci_read_config_word(pdev, GCDGMBUS, - &dev_priv->regfile.saveGCDGMBUS); - /* Cache mode state */ if (INTEL_GEN(dev_priv) < 7) dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); @@ -102,12 +109,8 @@ int i915_save_state(struct drm_i915_private *dev_priv) int i915_restore_state(struct drm_i915_private *dev_priv) { - struct pci_dev *pdev = dev_priv->drm.pdev; int i; - if (IS_GEN(dev_priv, 4)) - pci_write_config_word(pdev, GCDGMBUS, - dev_priv->regfile.saveGCDGMBUS); i915_restore_display(dev_priv); /* Cache mode state */ -- GitLab From 4a1a4a442736b5f6b71a0fcce292c351e889b808 Mon Sep 17 00:00:00 2001 From: Jani Nikula <jani.nikula@intel.com> Date: Thu, 10 Sep 2020 12:52:27 +0300 Subject: [PATCH 1049/1494] drm/i915: move gmbus restore to i915_restore_display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Logically part of the display restore. Note: This has been in place since the introduction of gmbus support. The gmbus code also does the resets before transfers. Is this really needed, or a historical accident? Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200910095227.9466-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/i915_suspend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 4a93247942b71..09026c4db7d05 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -69,6 +69,8 @@ static void i915_restore_display(struct drm_i915_private *dev_priv) I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); intel_vga_redisable(dev_priv); + + intel_gmbus_reset(dev_priv); } int i915_save_state(struct drm_i915_private *dev_priv) @@ -141,7 +143,5 @@ int i915_restore_state(struct drm_i915_private *dev_priv) I915_WRITE(SWF3(i), dev_priv->regfile.saveSWF3[i]); } - intel_gmbus_reset(dev_priv); - return 0; } -- GitLab From 7053e0eab473119503f6565b4e398f9a73122481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Mon, 7 Sep 2020 16:14:52 +0200 Subject: [PATCH 1050/1494] drm/vram-helper: stop using TTM placement flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are going to be removed, stop using them here. Instead define separate flags for the helper. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389823/?series=81551&rev=1 --- drivers/gpu/drm/drm_gem_vram_helper.c | 14 +++++++++----- include/drm/drm_gem_vram_helper.h | 7 +++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 07447abb41341..da045c5ba1187 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -135,20 +135,23 @@ static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo) static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, unsigned long pl_flag) { + u32 invariant_flags = 0; unsigned int i; unsigned int c = 0; - u32 invariant_flags = pl_flag & TTM_PL_FLAG_TOPDOWN; + + if (pl_flag & DRM_GEM_VRAM_PL_FLAG_TOPDOWN) + pl_flag = TTM_PL_FLAG_TOPDOWN; gbo->placement.placement = gbo->placements; gbo->placement.busy_placement = gbo->placements; - if (pl_flag & TTM_PL_FLAG_VRAM) + if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) gbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM | invariant_flags; - if (pl_flag & TTM_PL_FLAG_SYSTEM) + if (pl_flag & DRM_GEM_VRAM_PL_FLAG_SYSTEM) gbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | invariant_flags; @@ -189,7 +192,8 @@ static int drm_gem_vram_init(struct drm_device *dev, acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); gbo->bo.bdev = bdev; - drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM); + drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | + DRM_GEM_VRAM_PL_FLAG_SYSTEM); ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, &gbo->placement, pg_align, false, acc_size, @@ -647,7 +651,7 @@ static bool drm_is_gem_vram(struct ttm_buffer_object *bo) static void drm_gem_vram_bo_driver_evict_flags(struct drm_gem_vram_object *gbo, struct ttm_placement *pl) { - drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM); + drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM); *pl = gbo->placement; } diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index 035332f3723f2..a5e477bf96ccd 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -9,7 +9,6 @@ #include <drm/drm_modes.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> #include <linux/kernel.h> /* for container_of() */ @@ -20,9 +19,9 @@ struct drm_simple_display_pipe; struct filp; struct vm_area_struct; -#define DRM_GEM_VRAM_PL_FLAG_VRAM TTM_PL_FLAG_VRAM -#define DRM_GEM_VRAM_PL_FLAG_SYSTEM TTM_PL_FLAG_SYSTEM -#define DRM_GEM_VRAM_PL_FLAG_TOPDOWN TTM_PL_FLAG_TOPDOWN +#define DRM_GEM_VRAM_PL_FLAG_SYSTEM (1 << 0) +#define DRM_GEM_VRAM_PL_FLAG_VRAM (1 << 1) +#define DRM_GEM_VRAM_PL_FLAG_TOPDOWN (1 << 2) /* * Buffer-object helpers -- GitLab From 81b615798e9459ded773cad7a280a796012f2759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Tue, 8 Sep 2020 14:39:36 +0200 Subject: [PATCH 1051/1494] drm/nouveau: stop using TTM placement flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are going to be removed, stop using them here. Instead use the GEM flags from the UAPI. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389825/?series=81551&rev=1 --- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 9 ++- drivers/gpu/drm/nouveau/dispnv04/disp.c | 5 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 4 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 5 +- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 2 +- drivers/gpu/drm/nouveau/nouveau_abi16.c | 3 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 91 ++++++++++++++-------- drivers/gpu/drm/nouveau/nouveau_bo.h | 12 +-- drivers/gpu/drm/nouveau/nouveau_chan.c | 4 +- drivers/gpu/drm/nouveau/nouveau_dmem.c | 6 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 34 +++----- drivers/gpu/drm/nouveau/nouveau_prime.c | 11 ++- drivers/gpu/drm/nouveau/nv17_fence.c | 5 +- drivers/gpu/drm/nouveau/nv50_fence.c | 5 +- drivers/gpu/drm/nouveau/nv84_fence.c | 13 ++-- 16 files changed, 114 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6416b6907aeb0..f9e962fd94d0d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -615,7 +615,7 @@ nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ret; - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret == 0) { if (disp->image[nv_crtc->index]) nouveau_bo_unpin(disp->image[nv_crtc->index]); @@ -1172,7 +1172,7 @@ nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, return -ENOMEM; if (new_bo != old_bo) { - ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM, true); + ret = nouveau_bo_pin(new_bo, NOUVEAU_GEM_DOMAIN_VRAM, true); if (ret) goto fail_free; } @@ -1336,10 +1336,11 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); ret = nouveau_bo_new(&nouveau_drm(dev)->client, 64*64*4, 0x100, - TTM_PL_FLAG_VRAM, 0, 0x0000, NULL, NULL, + NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, NULL, NULL, &nv_crtc->cursor.nvbo); if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, + NOUVEAU_GEM_DOMAIN_VRAM, false); if (!ret) { ret = nouveau_bo_map(nv_crtc->cursor.nvbo); if (ret) diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 900ab69df7e8f..41d990cca6850 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -112,7 +112,7 @@ nv04_display_init(struct drm_device *dev, bool resume, bool runtime) if (!fb || !fb->obj[0]) continue; nvbo = nouveau_gem_object(fb->obj[0]); - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, true); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, true); if (ret) NV_ERROR(drm, "Could not pin framebuffer\n"); } @@ -122,7 +122,8 @@ nv04_display_init(struct drm_device *dev, bool resume, bool runtime) if (!nv_crtc->cursor.nvbo) continue; - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM, true); + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, + NOUVEAU_GEM_DOMAIN_VRAM, true); if (!ret && nv_crtc->cursor.set_offset) ret = nouveau_bo_map(nv_crtc->cursor.nvbo); if (ret) diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c index 193ba9498f3d3..37e63e98cd08a 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -142,7 +142,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return ret; nvbo = nouveau_gem_object(fb->obj[0]); - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret) return ret; @@ -387,7 +387,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, return ret; nvbo = nouveau_gem_object(fb->obj[0]); - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index e7874877da858..9dfb577f148a7 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -2581,10 +2581,11 @@ nv50_display_create(struct drm_device *dev) dev->mode_config.normalize_zpos = true; /* small shared memory area we use for notifiers and semaphores */ - ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, + ret = nouveau_bo_new(&drm->client, 4096, 0x1000, + NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, NULL, NULL, &disp->sync); if (!ret) { - ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM, true); + ret = nouveau_bo_pin(disp->sync, NOUVEAU_GEM_DOMAIN_VRAM, true); if (!ret) { ret = nouveau_bo_map(disp->sync); if (ret) diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 447ecc9fec42c..0356474ad6f6a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -542,7 +542,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) return 0; nvbo = nouveau_gem_object(fb->obj[0]); - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, true); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, true); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 21537ca1dd392..9a5be6f324249 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -328,7 +328,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) ret = nouveau_gem_new(cli, PAGE_SIZE, 0, NOUVEAU_GEM_DOMAIN_GART, 0, 0, &chan->ntfy); if (ret == 0) - ret = nouveau_bo_pin(chan->ntfy, TTM_PL_FLAG_TT, false); + ret = nouveau_bo_pin(chan->ntfy, NOUVEAU_GEM_DOMAIN_GART, + false); if (ret) goto done; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a9ad27d86a3cc..ddabefaab7cf7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -159,8 +159,7 @@ roundup_64(u64 x, u32 y) } static void -nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, - int *align, u64 *size) +nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, u64 *size) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct nvif_device *device = &drm->client.device; @@ -193,7 +192,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, } struct nouveau_bo * -nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 flags, +nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, u32 tile_mode, u32 tile_flags) { struct nouveau_drm *drm = cli->drm; @@ -219,7 +218,7 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 flags, * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated * into in nouveau_gem_new(). */ - if (flags & TTM_PL_FLAG_UNCACHED) { + if (domain & NOUVEAU_GEM_DOMAIN_COHERENT) { /* Determine if we can get a cache-coherent map, forcing * uncached mapping if we can't. */ @@ -259,9 +258,9 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 flags, * Skip page sizes that can't support needed domains. */ if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE && - (flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram) + (domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram) continue; - if ((flags & TTM_PL_FLAG_TT) && + if ((domain & NOUVEAU_GEM_DOMAIN_GART) && (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT)) continue; @@ -288,13 +287,13 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 flags, } nvbo->page = vmm->page[pi].shift; - nouveau_bo_fixup_align(nvbo, flags, align, size); + nouveau_bo_fixup_align(nvbo, align, size); return nvbo; } int -nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags, +nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 domain, struct sg_table *sg, struct dma_resv *robj) { int type = sg ? ttm_bo_type_sg : ttm_bo_type_device; @@ -304,7 +303,7 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags, acc_size = ttm_bo_dma_acc_size(nvbo->bo.bdev, size, sizeof(*nvbo)); nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; - nouveau_bo_placement_set(nvbo, flags, 0); + nouveau_bo_placement_set(nvbo, domain, 0); INIT_LIST_HEAD(&nvbo->io_reserve_lru); ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type, @@ -320,19 +319,19 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 flags, int nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, - uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, + uint32_t domain, uint32_t tile_mode, uint32_t tile_flags, struct sg_table *sg, struct dma_resv *robj, struct nouveau_bo **pnvbo) { struct nouveau_bo *nvbo; int ret; - nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode, + nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode, tile_flags); if (IS_ERR(nvbo)) return PTR_ERR(nvbo); - ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj); + ret = nouveau_bo_init(nvbo, size, align, domain, sg, robj); if (ret) return ret; @@ -341,27 +340,28 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, } static void -set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t type, uint32_t flags) +set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain, + uint32_t flags) { *n = 0; - if (type & TTM_PL_FLAG_VRAM) + if (domain & NOUVEAU_GEM_DOMAIN_VRAM) pl[(*n)++].flags = TTM_PL_FLAG_VRAM | flags; - if (type & TTM_PL_FLAG_TT) + if (domain & NOUVEAU_GEM_DOMAIN_GART) pl[(*n)++].flags = TTM_PL_FLAG_TT | flags; - if (type & TTM_PL_FLAG_SYSTEM) + if (domain & NOUVEAU_GEM_DOMAIN_CPU) pl[(*n)++].flags = TTM_PL_FLAG_SYSTEM | flags; } static void -set_placement_range(struct nouveau_bo *nvbo, uint32_t type) +set_placement_range(struct nouveau_bo *nvbo, uint32_t domain) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); u32 vram_pages = drm->client.device.info.ram_size >> PAGE_SHIFT; unsigned i, fpfn, lpfn; if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS && - nvbo->mode && (type & TTM_PL_FLAG_VRAM) && + nvbo->mode && (domain & NOUVEAU_GEM_DOMAIN_VRAM) && nvbo->bo.mem.num_pages < vram_pages / 4) { /* * Make sure that the color and depth buffers are handled @@ -388,7 +388,8 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type) } void -nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) +nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain, + uint32_t busy) { struct ttm_placement *pl = &nvbo->placement; uint32_t flags = (nvbo->force_coherent ? TTM_PL_FLAG_UNCACHED : @@ -397,17 +398,17 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) pl->placement = nvbo->placements; set_placement_list(nvbo->placements, &pl->num_placement, - type, flags); + domain, flags); pl->busy_placement = nvbo->busy_placements; set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, - type | busy, flags); + domain | busy, flags); - set_placement_range(nvbo, type); + set_placement_range(nvbo, domain); } int -nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) +nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_buffer_object *bo = &nvbo->bo; @@ -419,7 +420,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) return ret; if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA && - memtype == TTM_PL_FLAG_VRAM && contig) { + domain == NOUVEAU_GEM_DOMAIN_VRAM && contig) { if (!nvbo->contig) { nvbo->contig = true; force = true; @@ -428,10 +429,22 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) } if (nvbo->pin_refcnt) { - if (!(memtype & (1 << bo->mem.mem_type)) || evict) { + bool error = evict; + + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + error |= !(domain & NOUVEAU_GEM_DOMAIN_VRAM); + break; + case TTM_PL_TT: + error |= !(domain & NOUVEAU_GEM_DOMAIN_GART); + default: + break; + } + + if (error) { NV_ERROR(drm, "bo %p pinned elsewhere: " "0x%08x vs 0x%08x\n", bo, - 1 << bo->mem.mem_type, memtype); + bo->mem.mem_type, domain); ret = -EBUSY; } nvbo->pin_refcnt++; @@ -439,14 +452,14 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) } if (evict) { - nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT, 0); + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, 0); ret = nouveau_bo_validate(nvbo, false, false); if (ret) goto out; } nvbo->pin_refcnt++; - nouveau_bo_placement_set(nvbo, memtype, 0); + nouveau_bo_placement_set(nvbo, domain, 0); /* drop pin_refcnt temporarily, so we don't trip the assertion * in nouveau_bo_move() that makes sure we're not trying to @@ -492,7 +505,16 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo) if (ref) goto out; - nouveau_bo_placement_set(nvbo, bo->mem.placement, 0); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0); + break; + case TTM_PL_TT: + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, 0); + break; + default: + break; + } ret = nouveau_bo_validate(nvbo, false, false); if (ret == 0) { @@ -702,11 +724,11 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) switch (bo->mem.mem_type) { case TTM_PL_VRAM: - nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT, - TTM_PL_FLAG_SYSTEM); + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, + NOUVEAU_GEM_DOMAIN_CPU); break; default: - nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM, 0); + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_CPU, 0); break; } @@ -1214,7 +1236,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) return 0; if (bo->mem.mem_type == TTM_PL_SYSTEM) { - nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0); + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, + 0); ret = nouveau_bo_validate(nvbo, false, false); if (ret) @@ -1238,7 +1261,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) nvbo->busy_placements[i].lpfn = mappable; } - nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0); + nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0); return nouveau_bo_validate(nvbo, false, false); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index ae90aca33fefd..2a23c82074362 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -77,10 +77,10 @@ extern struct ttm_bo_driver nouveau_bo_driver; void nouveau_bo_move_init(struct nouveau_drm *); struct nouveau_bo *nouveau_bo_alloc(struct nouveau_cli *, u64 *size, int *align, - u32 flags, u32 tile_mode, u32 tile_flags); -int nouveau_bo_init(struct nouveau_bo *, u64 size, int align, u32 flags, + u32 domain, u32 tile_mode, u32 tile_flags); +int nouveau_bo_init(struct nouveau_bo *, u64 size, int align, u32 domain, struct sg_table *sg, struct dma_resv *robj); -int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 flags, +int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 domain, u32 tile_mode, u32 tile_flags, struct sg_table *sg, struct dma_resv *robj, struct nouveau_bo **); @@ -122,13 +122,13 @@ nouveau_bo_unmap_unpin_unref(struct nouveau_bo **pnvbo) } static inline int -nouveau_bo_new_pin_map(struct nouveau_cli *cli, u64 size, int align, u32 flags, +nouveau_bo_new_pin_map(struct nouveau_cli *cli, u64 size, int align, u32 domain, struct nouveau_bo **pnvbo) { - int ret = nouveau_bo_new(cli, size, align, flags, + int ret = nouveau_bo_new(cli, size, align, domain, 0, 0, NULL, NULL, pnvbo); if (ret == 0) { - ret = nouveau_bo_pin(*pnvbo, flags, true); + ret = nouveau_bo_pin(*pnvbo, domain, true); if (ret == 0) { ret = nouveau_bo_map(*pnvbo); if (ret == 0) diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index b80e4ebf14a6e..8f099601d2f2d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -163,9 +163,9 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, atomic_set(&chan->killed, 0); /* allocate memory for dma push buffer */ - target = TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED; + target = NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT; if (nouveau_vram_pushbuf) - target = TTM_PL_FLAG_VRAM; + target = NOUVEAU_GEM_DOMAIN_VRAM; ret = nouveau_bo_new(cli, size, 0, target, 0, 0, NULL, NULL, &chan->push.buffer); diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 4e8112fde3e6b..af70ef8e5471d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -254,12 +254,12 @@ nouveau_dmem_chunk_alloc(struct nouveau_drm *drm, struct page **ppage) chunk->pagemap.owner = drm->dev; ret = nouveau_bo_new(&drm->client, DMEM_CHUNK_SIZE, 0, - TTM_PL_FLAG_VRAM, 0, 0, NULL, NULL, + NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, NULL, NULL, &chunk->bo); if (ret) goto out_release; - ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(chunk->bo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret) goto out_bo_free; @@ -346,7 +346,7 @@ nouveau_dmem_resume(struct nouveau_drm *drm) mutex_lock(&drm->dmem->mutex); list_for_each_entry(chunk, &drm->dmem->chunks, list) { - ret = nouveau_bo_pin(chunk->bo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(chunk->bo, NOUVEAU_GEM_DOMAIN_VRAM, false); /* FIXME handle pin failure */ WARN_ON(ret); } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 3159a2172db57..24ec5339efb46 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -341,7 +341,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, if (ret) goto out_unref; - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (ret) { NV_ERROR(drm, "failed to pin fb: %d\n", ret); goto out_unref; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 81f111ad3f4fd..89adadf4706b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -176,20 +176,12 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, { struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; - u32 flags = 0; int ret; - if (domain & NOUVEAU_GEM_DOMAIN_VRAM) - flags |= TTM_PL_FLAG_VRAM; - if (domain & NOUVEAU_GEM_DOMAIN_GART) - flags |= TTM_PL_FLAG_TT; - if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) - flags |= TTM_PL_FLAG_SYSTEM; + if (!(domain & (NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART))) + domain |= NOUVEAU_GEM_DOMAIN_CPU; - if (domain & NOUVEAU_GEM_DOMAIN_COHERENT) - flags |= TTM_PL_FLAG_UNCACHED; - - nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode, + nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode, tile_flags); if (IS_ERR(nvbo)) return PTR_ERR(nvbo); @@ -202,7 +194,7 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, return ret; } - ret = nouveau_bo_init(nvbo, size, align, flags, NULL, NULL); + ret = nouveau_bo_init(nvbo, size, align, domain, NULL, NULL); if (ret) { nouveau_bo_ref(NULL, &nvbo); return ret; @@ -296,32 +288,28 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, struct ttm_buffer_object *bo = &nvbo->bo; uint32_t domains = valid_domains & nvbo->valid_domains & (write_domains ? write_domains : read_domains); - uint32_t pref_flags = 0, valid_flags = 0; + uint32_t pref_domains = 0;; if (!domains) return -EINVAL; - if (valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) - valid_flags |= TTM_PL_FLAG_VRAM; - - if (valid_domains & NOUVEAU_GEM_DOMAIN_GART) - valid_flags |= TTM_PL_FLAG_TT; + valid_domains &= ~(NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART); if ((domains & NOUVEAU_GEM_DOMAIN_VRAM) && bo->mem.mem_type == TTM_PL_VRAM) - pref_flags |= TTM_PL_FLAG_VRAM; + pref_domains |= NOUVEAU_GEM_DOMAIN_VRAM; else if ((domains & NOUVEAU_GEM_DOMAIN_GART) && bo->mem.mem_type == TTM_PL_TT) - pref_flags |= TTM_PL_FLAG_TT; + pref_domains |= NOUVEAU_GEM_DOMAIN_GART; else if (domains & NOUVEAU_GEM_DOMAIN_VRAM) - pref_flags |= TTM_PL_FLAG_VRAM; + pref_domains |= NOUVEAU_GEM_DOMAIN_VRAM; else - pref_flags |= TTM_PL_FLAG_TT; + pref_domains |= NOUVEAU_GEM_DOMAIN_GART; - nouveau_bo_placement_set(nvbo, pref_flags, valid_flags); + nouveau_bo_placement_set(nvbo, pref_domains, valid_domains); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 7766b810653f5..b2ecb91f8ddc0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -64,14 +64,12 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, struct nouveau_bo *nvbo; struct dma_resv *robj = attach->dmabuf->resv; u64 size = attach->dmabuf->size; - u32 flags = 0; int align = 0; int ret; - flags = TTM_PL_FLAG_TT; - dma_resv_lock(robj, NULL); - nvbo = nouveau_bo_alloc(&drm->client, &size, &align, flags, 0, 0); + nvbo = nouveau_bo_alloc(&drm->client, &size, &align, + NOUVEAU_GEM_DOMAIN_GART, 0, 0); if (IS_ERR(nvbo)) { obj = ERR_CAST(nvbo); goto unlock; @@ -88,7 +86,8 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, goto unlock; } - ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj); + ret = nouveau_bo_init(nvbo, size, align, NOUVEAU_GEM_DOMAIN_GART, + sg, robj); if (ret) { nouveau_bo_ref(NULL, &nvbo); obj = ERR_PTR(ret); @@ -108,7 +107,7 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) int ret; /* pin buffer into GTT */ - ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT, false); + ret = nouveau_bo_pin(nvbo, NOUVEAU_GEM_DOMAIN_GART, false); if (ret) return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c index 6b697ee6bc0ec..1253fdec712d4 100644 --- a/drivers/gpu/drm/nouveau/nv17_fence.c +++ b/drivers/gpu/drm/nouveau/nv17_fence.c @@ -130,10 +130,11 @@ nv17_fence_create(struct nouveau_drm *drm) priv->base.context_del = nv10_fence_context_del; spin_lock_init(&priv->lock); - ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, + ret = nouveau_bo_new(&drm->client, 4096, 0x1000, + NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, NULL, NULL, &priv->bo); if (!ret) { - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(priv->bo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (!ret) { ret = nouveau_bo_map(priv->bo); if (ret) diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index 49b46f51073c7..447238e3cbe77 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -81,10 +81,11 @@ nv50_fence_create(struct nouveau_drm *drm) priv->base.context_del = nv10_fence_context_del; spin_lock_init(&priv->lock); - ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM, + ret = nouveau_bo_new(&drm->client, 4096, 0x1000, + NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, NULL, NULL, &priv->bo); if (!ret) { - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM, false); + ret = nouveau_bo_pin(priv->bo, NOUVEAU_GEM_DOMAIN_VRAM, false); if (!ret) { ret = nouveau_bo_map(priv->bo); if (ret) diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index 7ed36b3a6b7da..7c9c928c31966 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -209,12 +209,13 @@ nv84_fence_create(struct nouveau_drm *drm) mutex_init(&priv->mutex); /* Use VRAM if there is any ; otherwise fallback to system memory */ - domain = drm->client.device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM : - /* - * fences created in sysmem must be non-cached or we - * will lose CPU/GPU coherency! - */ - TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED; + domain = drm->client.device.info.ram_size != 0 ? + NOUVEAU_GEM_DOMAIN_VRAM : + /* + * fences created in sysmem must be non-cached or we + * will lose CPU/GPU coherency! + */ + NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT; ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0, domain, 0, 0, NULL, NULL, &priv->bo); if (ret == 0) { -- GitLab From e03d342c621b985b68b3062cdbc3cdd6c6d7860b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Tue, 8 Sep 2020 16:55:55 +0200 Subject: [PATCH 1052/1494] drm/vmwgfx: stop setting multiple domain flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting more than one placement flag is illegal. Fix this by using the current flags. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389824/?series=81551&rev=1 --- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 3229451d07062..03f5660d85a44 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -354,10 +354,11 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) pl.fpfn = 0; pl.lpfn = 0; - pl.flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | VMW_PL_FLAG_MOB - | TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; + pl.flags = bo->mem.placement; if (pin) pl.flags |= TTM_PL_FLAG_NO_EVICT; + else + pl.flags &= ~TTM_PL_FLAG_NO_EVICT; memset(&placement, 0, sizeof(placement)); placement.num_placement = 1; -- GitLab From 48e07c23cbeba2a2cda7ca73be0015e727818536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Thu, 10 Sep 2020 13:39:41 +0200 Subject: [PATCH 1053/1494] drm/ttm: nuke memory type flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not supported to specify more than one of those flags. So it never made sense to make this a flag in the first place. Nuke the flags and specify directly which memory type to use. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/389826/?series=81551&rev=1 --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 24 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 13 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 - drivers/gpu/drm/drm_gem_vram_helper.c | 15 ++-- drivers/gpu/drm/nouveau/nouveau_bo.c | 24 ++++-- drivers/gpu/drm/qxl/qxl_object.c | 24 ++++-- drivers/gpu/drm/qxl/qxl_ttm.c | 3 +- drivers/gpu/drm/radeon/radeon_object.c | 42 +++++------ drivers/gpu/drm/radeon/radeon_ttm.c | 11 ++- drivers/gpu/drm/ttm/ttm_bo.c | 86 ++++------------------ drivers/gpu/drm/ttm/ttm_bo_util.c | 2 - drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 63 ++++++++++------ include/drm/ttm/ttm_bo_driver.h | 17 ----- include/drm/ttm/ttm_placement.h | 9 +-- 16 files changed, 149 insertions(+), 191 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index b36d94f57d428..eaff4c4506ebd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -136,8 +136,8 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM; + places[c].mem_type = TTM_PL_VRAM; + places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) places[c].lpfn = visible_pfn; @@ -152,7 +152,8 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) if (domain & AMDGPU_GEM_DOMAIN_GTT) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_TT; + places[c].mem_type = TTM_PL_TT; + places[c].flags = 0; if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) places[c].flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; @@ -164,7 +165,8 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) if (domain & AMDGPU_GEM_DOMAIN_CPU) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_SYSTEM; + places[c].mem_type = TTM_PL_SYSTEM; + places[c].flags = 0; if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) places[c].flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; @@ -176,28 +178,32 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) if (domain & AMDGPU_GEM_DOMAIN_GDS) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GDS; + places[c].mem_type = AMDGPU_PL_GDS; + places[c].flags = TTM_PL_FLAG_UNCACHED; c++; } if (domain & AMDGPU_GEM_DOMAIN_GWS) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_GWS; + places[c].mem_type = AMDGPU_PL_GWS; + places[c].flags = TTM_PL_FLAG_UNCACHED; c++; } if (domain & AMDGPU_GEM_DOMAIN_OA) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_FLAG_UNCACHED | AMDGPU_PL_FLAG_OA; + places[c].mem_type = AMDGPU_PL_OA; + places[c].flags = TTM_PL_FLAG_UNCACHED; c++; } if (!c) { places[c].fpfn = 0; places[c].lpfn = 0; - places[c].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; + places[c].mem_type = TTM_PL_SYSTEM; + places[c].flags = TTM_PL_MASK_CACHING; c++; } @@ -591,7 +597,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, 0); if (bp->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED && - bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) { + bo->tbo.mem.mem_type == TTM_PL_VRAM) { struct dma_fence *fence; r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 4ffbe4f666081..651365183e75f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -88,7 +88,8 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_MASK_CACHING }; /* Don't handle scatter gather BOs */ @@ -533,7 +534,8 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = 0; - placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + placements.mem_type = TTM_PL_TT; + placements.flags = TTM_PL_MASK_CACHING; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx); if (unlikely(r)) { pr_err("Failed to find GTT space for blit from VRAM\n"); @@ -589,7 +591,8 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = 0; - placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + placements.mem_type = TTM_PL_TT; + placements.flags = TTM_PL_MASK_CACHING; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx); if (unlikely(r)) { pr_err("Failed to find GTT space for blit to VRAM\n"); @@ -1171,8 +1174,8 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = adev->gmc.gart_size >> PAGE_SHIFT; - placements.flags = (bo->mem.placement & ~TTM_PL_MASK_MEM) | - TTM_PL_FLAG_TT; + placements.mem_type = TTM_PL_TT; + placements.flags = bo->mem.placement; r = ttm_bo_mem_space(bo, &placement, &tmp, &ctx); if (unlikely(r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 7ba2be37e6ba5..4f9426ecf0391 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -32,10 +32,6 @@ #define AMDGPU_PL_GWS (TTM_PL_PRIV + 1) #define AMDGPU_PL_OA (TTM_PL_PRIV + 2) -#define AMDGPU_PL_FLAG_GDS (TTM_PL_FLAG_PRIV << 0) -#define AMDGPU_PL_FLAG_GWS (TTM_PL_FLAG_PRIV << 1) -#define AMDGPU_PL_FLAG_OA (TTM_PL_FLAG_PRIV << 2) - #define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 #define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index da045c5ba1187..5f10aa7aa0999 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -145,21 +145,18 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, gbo->placement.placement = gbo->placements; gbo->placement.busy_placement = gbo->placements; - if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) + if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) { + gbo->placements[c].mem_type = TTM_PL_VRAM; gbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM | - invariant_flags; - - if (pl_flag & DRM_GEM_VRAM_PL_FLAG_SYSTEM) - gbo->placements[c++].flags = TTM_PL_MASK_CACHING | - TTM_PL_FLAG_SYSTEM | invariant_flags; + } - if (!c) + if (pl_flag & DRM_GEM_VRAM_PL_FLAG_SYSTEM || !c) { + gbo->placements[c].mem_type = TTM_PL_SYSTEM; gbo->placements[c++].flags = TTM_PL_MASK_CACHING | - TTM_PL_FLAG_SYSTEM | invariant_flags; + } gbo->placement.num_placement = c; gbo->placement.num_busy_placement = c; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index ddabefaab7cf7..97e1908eada07 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -345,12 +345,18 @@ set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain, { *n = 0; - if (domain & NOUVEAU_GEM_DOMAIN_VRAM) - pl[(*n)++].flags = TTM_PL_FLAG_VRAM | flags; - if (domain & NOUVEAU_GEM_DOMAIN_GART) - pl[(*n)++].flags = TTM_PL_FLAG_TT | flags; - if (domain & NOUVEAU_GEM_DOMAIN_CPU) - pl[(*n)++].flags = TTM_PL_FLAG_SYSTEM | flags; + if (domain & NOUVEAU_GEM_DOMAIN_VRAM) { + pl[*n].mem_type = TTM_PL_VRAM; + pl[(*n)++].flags = flags; + } + if (domain & NOUVEAU_GEM_DOMAIN_GART) { + pl[*n].mem_type = TTM_PL_TT; + pl[(*n)++].flags = flags; + } + if (domain & NOUVEAU_GEM_DOMAIN_CPU) { + pl[*n].mem_type = TTM_PL_SYSTEM; + pl[(*n)++].flags = flags; + } } static void @@ -882,7 +888,8 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, struct ttm_place placement_memtype = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING + .mem_type = TTM_PL_TT, + .flags = TTM_PL_MASK_CACHING }; struct ttm_placement placement; struct ttm_resource tmp_reg; @@ -919,7 +926,8 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, struct ttm_place placement_memtype = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING + .mem_type = TTM_PL_TT, + .flags = TTM_PL_MASK_CACHING }; struct ttm_placement placement; struct ttm_resource tmp_reg; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index b2a1fa61920be..2bc364412e8b8 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -64,16 +64,24 @@ void qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain, bool pinned) qbo->placement.placement = qbo->placements; qbo->placement.busy_placement = qbo->placements; - if (domain == QXL_GEM_DOMAIN_VRAM) - qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag; + if (domain == QXL_GEM_DOMAIN_VRAM) { + qbo->placements[c].mem_type = TTM_PL_VRAM; + qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | pflag; + } if (domain == QXL_GEM_DOMAIN_SURFACE) { - qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_PRIV | pflag; - qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_VRAM | pflag; + qbo->placements[c].mem_type = TTM_PL_PRIV; + qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | pflag; + qbo->placements[c].mem_type = TTM_PL_VRAM; + qbo->placements[c++].flags = TTM_PL_FLAG_CACHED | pflag; + } + if (domain == QXL_GEM_DOMAIN_CPU) { + qbo->placements[c].mem_type = TTM_PL_SYSTEM; + qbo->placements[c++].flags = TTM_PL_MASK_CACHING | pflag; + } + if (!c) { + qbo->placements[c].mem_type = TTM_PL_SYSTEM; + qbo->placements[c++].flags = TTM_PL_MASK_CACHING; } - if (domain == QXL_GEM_DOMAIN_CPU) - qbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM | pflag; - if (!c) - qbo->placements[c++].flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; qbo->placement.num_placement = c; qbo->placement.num_busy_placement = c; for (i = 0; i < c; ++i) { diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 0b8f12e6dd6a8..5ffc8b752f01b 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -55,7 +55,8 @@ static void qxl_evict_flags(struct ttm_buffer_object *bo, static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_MASK_CACHING }; if (!qxl_ttm_bo_is_qxl_bo(bo)) { diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 3fcd15d21ddcc..316e35d3f8a9d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -112,58 +112,58 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) rbo->rdev->mc.visible_vram_size < rbo->rdev->mc.real_vram_size) { rbo->placements[c].fpfn = rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT; + rbo->placements[c].mem_type = TTM_PL_VRAM; rbo->placements[c++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM; + TTM_PL_FLAG_UNCACHED; } rbo->placements[c].fpfn = 0; + rbo->placements[c].mem_type = TTM_PL_VRAM; rbo->placements[c++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_VRAM; + TTM_PL_FLAG_UNCACHED; } if (domain & RADEON_GEM_DOMAIN_GTT) { if (rbo->flags & RADEON_GEM_GTT_UC) { rbo->placements[c].fpfn = 0; - rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_TT; + rbo->placements[c].mem_type = TTM_PL_TT; + rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED; } else if ((rbo->flags & RADEON_GEM_GTT_WC) || (rbo->rdev->flags & RADEON_IS_AGP)) { rbo->placements[c].fpfn = 0; + rbo->placements[c].mem_type = TTM_PL_TT; rbo->placements[c++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_TT; + TTM_PL_FLAG_UNCACHED; } else { rbo->placements[c].fpfn = 0; - rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_TT; + rbo->placements[c].mem_type = TTM_PL_TT; + rbo->placements[c++].flags = TTM_PL_FLAG_CACHED; } } if (domain & RADEON_GEM_DOMAIN_CPU) { if (rbo->flags & RADEON_GEM_GTT_UC) { rbo->placements[c].fpfn = 0; - rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_SYSTEM; + rbo->placements[c].mem_type = TTM_PL_SYSTEM; + rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED; } else if ((rbo->flags & RADEON_GEM_GTT_WC) || rbo->rdev->flags & RADEON_IS_AGP) { rbo->placements[c].fpfn = 0; + rbo->placements[c].mem_type = TTM_PL_SYSTEM; rbo->placements[c++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_SYSTEM; + TTM_PL_FLAG_UNCACHED; } else { rbo->placements[c].fpfn = 0; - rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_SYSTEM; + rbo->placements[c].mem_type = TTM_PL_SYSTEM; + rbo->placements[c++].flags = TTM_PL_FLAG_CACHED; } } if (!c) { rbo->placements[c].fpfn = 0; - rbo->placements[c++].flags = TTM_PL_MASK_CACHING | - TTM_PL_FLAG_SYSTEM; + rbo->placements[c].mem_type = TTM_PL_SYSTEM; + rbo->placements[c++].flags = TTM_PL_MASK_CACHING; } rbo->placement.num_placement = c; @@ -171,7 +171,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) for (i = 0; i < c; ++i) { if ((rbo->flags & RADEON_GEM_CPU_ACCESS) && - (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) && + (rbo->placements[i].mem_type == TTM_PL_VRAM) && !rbo->placements[i].fpfn) rbo->placements[i].lpfn = rbo->rdev->mc.visible_vram_size >> PAGE_SHIFT; @@ -360,7 +360,7 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, radeon_ttm_placement_from_domain(bo, domain); for (i = 0; i < bo->placement.num_placement; i++) { /* force to pin into visible video ram */ - if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && + if ((bo->placements[i].mem_type == TTM_PL_VRAM) && !(bo->flags & RADEON_GEM_NO_CPU_ACCESS) && (!max_offset || max_offset > bo->rdev->mc.visible_vram_size)) bo->placements[i].lpfn = @@ -824,7 +824,7 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; for (i = 0; i < rbo->placement.num_placement; i++) { /* Force into visible VRAM */ - if ((rbo->placements[i].flags & TTM_PL_FLAG_VRAM) && + if ((rbo->placements[i].mem_type == TTM_PL_VRAM) && (!rbo->placements[i].lpfn || rbo->placements[i].lpfn > lpfn)) rbo->placements[i].lpfn = lpfn; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 0612d3b311ad3..602a591a53dc7 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -88,7 +88,8 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, static const struct ttm_place placements = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_MASK_CACHING }; struct radeon_bo *rbo; @@ -119,7 +120,7 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, RADEON_GEM_DOMAIN_GTT); rbo->placement.num_busy_placement = 0; for (i = 0; i < rbo->placement.num_placement; i++) { - if (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) { + if (rbo->placements[i].mem_type == TTM_PL_VRAM) { if (rbo->placements[i].fpfn < fpfn) rbo->placements[i].fpfn = fpfn; } else { @@ -224,7 +225,8 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = 0; - placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + placements.mem_type = TTM_PL_TT; + placements.flags = TTM_PL_MASK_CACHING; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, &ctx); if (unlikely(r)) { return r; @@ -269,7 +271,8 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo, placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = 0; - placements.flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + placements.mem_type = TTM_PL_TT; + placements.flags = TTM_PL_MASK_CACHING; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, &ctx); if (unlikely(r)) { return r; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c93de7fab7395..e2bfe3a13c63d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -64,34 +64,18 @@ static void ttm_bo_default_destroy(struct ttm_buffer_object *bo) kfree(bo); } -static inline int ttm_mem_type_from_place(const struct ttm_place *place, - uint32_t *mem_type) -{ - int pos; - - pos = ffs(place->flags & TTM_PL_MASK_MEM); - if (unlikely(!pos)) - return -EINVAL; - - *mem_type = pos - 1; - return 0; -} - static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, struct ttm_placement *placement) { struct drm_printer p = drm_debug_printer(TTM_PFX); - int i, ret, mem_type; struct ttm_resource_manager *man; + int i, mem_type; drm_printf(&p, "No space for %p (%lu pages, %luK, %luM)\n", bo, bo->mem.num_pages, bo->mem.size >> 10, bo->mem.size >> 20); for (i = 0; i < placement->num_placement; i++) { - ret = ttm_mem_type_from_place(&placement->placement[i], - &mem_type); - if (ret) - return; + mem_type = placement->placement[i].mem_type; drm_printf(&p, " placement[%d]=0x%08X (%d)\n", i, placement->placement[i].flags, mem_type); man = ttm_manager_type(bo->bdev, mem_type); @@ -125,12 +109,6 @@ static struct kobj_type ttm_bo_glob_kobj_type = { .default_attrs = ttm_bo_global_attrs }; - -static inline uint32_t ttm_bo_type_flags(unsigned type) -{ - return 1 << (type); -} - static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, struct ttm_resource *mem) { @@ -910,25 +888,6 @@ static uint32_t ttm_bo_select_caching(struct ttm_resource_manager *man, return result; } -static bool ttm_bo_mt_compatible(struct ttm_resource_manager *man, - uint32_t mem_type, - const struct ttm_place *place, - uint32_t *masked_placement) -{ - uint32_t cur_flags = ttm_bo_type_flags(mem_type); - - if ((cur_flags & place->flags & TTM_PL_MASK_MEM) == 0) - return false; - - if ((place->flags & man->available_caching) == 0) - return false; - - cur_flags |= (place->flags & man->available_caching); - - *masked_placement = cur_flags; - return true; -} - /** * ttm_bo_mem_placement - check if placement is compatible * @bo: BO to find memory for @@ -946,30 +905,21 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) { struct ttm_bo_device *bdev = bo->bdev; - uint32_t mem_type = TTM_PL_SYSTEM; struct ttm_resource_manager *man; uint32_t cur_flags = 0; - int ret; - ret = ttm_mem_type_from_place(place, &mem_type); - if (ret) - return ret; - - man = ttm_manager_type(bdev, mem_type); + man = ttm_manager_type(bdev, place->mem_type); if (!man || !ttm_resource_manager_used(man)) return -EBUSY; - if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags)) + if ((place->flags & man->available_caching) == 0) return -EBUSY; + cur_flags = place->flags & man->available_caching; cur_flags = ttm_bo_select_caching(man, bo->mem.placement, cur_flags); - /* - * Use the access and other non-mapping-related flag bits from - * the memory placement flags to the current flags - */ - ttm_flag_masked(&cur_flags, place->flags, ~TTM_PL_MASK_MEMTYPE); + cur_flags |= place->flags & ~TTM_PL_MASK_CACHING; - mem->mem_type = mem_type; + mem->mem_type = place->mem_type; mem->placement = cur_flags; spin_lock(&ttm_bo_glob.lru_lock); @@ -1006,10 +956,8 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_resource_manager *man; ret = ttm_bo_mem_placement(bo, place, mem, ctx); - if (ret == -EBUSY) - continue; if (ret) - goto error; + continue; type_found = true; ret = ttm_resource_alloc(bo, place, mem); @@ -1034,10 +982,8 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, const struct ttm_place *place = &placement->busy_placement[i]; ret = ttm_bo_mem_placement(bo, place, mem, ctx); - if (ret == -EBUSY) - continue; if (ret) - goto error; + continue; type_found = true; ret = ttm_bo_mem_force_space(bo, place, mem, ctx); @@ -1108,7 +1054,7 @@ static bool ttm_bo_places_compat(const struct ttm_place *places, *new_flags = heap->flags; if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) && - (*new_flags & mem->placement & TTM_PL_MASK_MEM) && + (mem->mem_type == heap->mem_type) && (!(*new_flags & TTM_PL_FLAG_CONTIGUOUS) || (mem->placement & TTM_PL_FLAG_CONTIGUOUS))) return true; @@ -1163,12 +1109,8 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, if (ret) return ret; } else { - /* - * Use the access and other non-mapping-related flag bits from - * the compatible memory placement flags to the active flags - */ - ttm_flag_masked(&bo->mem.placement, new_flags, - ~TTM_PL_MASK_MEMTYPE); + bo->mem.placement &= TTM_PL_MASK_CACHING; + bo->mem.placement |= new_flags & ~TTM_PL_MASK_CACHING; } /* * We might need to add a TTM. @@ -1236,7 +1178,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->mem.bus.offset = 0; bo->mem.bus.addr = NULL; bo->moving = NULL; - bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); + bo->mem.placement = TTM_PL_FLAG_CACHED; bo->acc_size = acc_size; bo->sg = sg; if (resv) { @@ -1627,7 +1569,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) evict_mem = bo->mem; evict_mem.mm_node = NULL; - evict_mem.placement = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; + evict_mem.placement = TTM_PL_FLAG_CACHED; evict_mem.mem_type = TTM_PL_SYSTEM; ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, &ctx); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 5ac8da43238be..1b56432dfa438 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -69,8 +69,6 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, ttm_tt_unbind(bo->bdev, ttm); ttm_bo_free_old_node(bo); - ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM, - TTM_PL_MASK_MEM); old_mem->mem_type = TTM_PL_SYSTEM; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 03f5660d85a44..813f1b1480941 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -354,6 +354,7 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) pl.fpfn = 0; pl.lpfn = 0; + pl.mem_type = bo->mem.mem_type; pl.flags = bo->mem.placement; if (pin) pl.flags |= TTM_PL_FLAG_NO_EVICT; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 871ad738dadbd..1523b51a7284c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -82,9 +82,7 @@ VMWGFX_NUM_GB_SCREEN_TARGET) #define VMW_PL_GMR (TTM_PL_PRIV + 0) -#define VMW_PL_FLAG_GMR (TTM_PL_FLAG_PRIV << 0) #define VMW_PL_MOB (TTM_PL_PRIV + 1) -#define VMW_PL_FLAG_MOB (TTM_PL_FLAG_PRIV << 1) #define VMW_RES_CONTEXT ttm_driver_type0 #define VMW_RES_SURFACE ttm_driver_type1 diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 9d62e57fcb8de..03aa0fc5e753c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -33,49 +33,57 @@ static const struct ttm_place vram_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED }; static const struct ttm_place vram_ne_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT }; static const struct ttm_place sys_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_FLAG_CACHED }; static const struct ttm_place sys_ne_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT }; static const struct ttm_place gmr_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED }; static const struct ttm_place gmr_ne_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT }; static const struct ttm_place mob_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_MOB, + .flags = TTM_PL_FLAG_CACHED }; static const struct ttm_place mob_ne_placement_flags = { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT + .mem_type = VMW_PL_MOB, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT }; struct ttm_placement vmw_vram_placement = { @@ -89,11 +97,13 @@ static const struct ttm_place vram_gmr_placement_flags[] = { { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED } }; @@ -101,11 +111,13 @@ static const struct ttm_place gmr_vram_placement_flags[] = { { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED } }; @@ -120,12 +132,14 @@ static const struct ttm_place vram_gmr_ne_placement_flags[] = { { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT } }; @@ -169,19 +183,23 @@ static const struct ttm_place evictable_placement_flags[] = { { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_VRAM, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_MOB, + .flags = TTM_PL_FLAG_CACHED } }; @@ -189,15 +207,18 @@ static const struct ttm_place nonfixed_placement_flags[] = { { .fpfn = 0, .lpfn = 0, - .flags = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED + .mem_type = TTM_PL_SYSTEM, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_GMR, + .flags = TTM_PL_FLAG_CACHED }, { .fpfn = 0, .lpfn = 0, - .flags = VMW_PL_FLAG_MOB | TTM_PL_FLAG_CACHED + .mem_type = VMW_PL_MOB, + .flags = TTM_PL_FLAG_CACHED } }; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 32c0651cc0fd6..303a89d1066d0 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -393,23 +393,6 @@ struct ttm_lru_bulk_move { struct ttm_lru_bulk_move_pos swap[TTM_MAX_BO_PRIORITY]; }; -/** - * ttm_flag_masked - * - * @old: Pointer to the result and original value. - * @new: New value of bits. - * @mask: Mask of bits to change. - * - * Convenience function to change a number of bits identified by a mask. - */ - -static inline uint32_t -ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) -{ - *old ^= (*old ^ new) & mask; - return *old; -} - /* * ttm_bo.c */ diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index e88a8e39767bf..d4022655eae40 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -42,12 +42,6 @@ #define TTM_PL_VRAM 2 #define TTM_PL_PRIV 3 -#define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM) -#define TTM_PL_FLAG_TT (1 << TTM_PL_TT) -#define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM) -#define TTM_PL_FLAG_PRIV (1 << TTM_PL_PRIV) -#define TTM_PL_MASK_MEM 0x0000FFFF - /* * Other flags that affects data placement. * TTM_PL_FLAG_CACHED indicates cache-coherent mappings @@ -71,8 +65,6 @@ TTM_PL_FLAG_UNCACHED | \ TTM_PL_FLAG_WC) -#define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING) - /** * struct ttm_place * @@ -85,6 +77,7 @@ struct ttm_place { unsigned fpfn; unsigned lpfn; + uint32_t mem_type; uint32_t flags; }; -- GitLab From 33f290811d4c1a09c4e92f5bf0458525835dbcba Mon Sep 17 00:00:00 2001 From: Alex Dewar <alex.dewar90@gmail.com> Date: Wed, 9 Sep 2020 20:02:08 +0100 Subject: [PATCH 1054/1494] drm/bridge: dw-mipi-dsi: Use kmemdup cf. kmalloc+memcpy kmemdup can be used instead of kmalloc+memcpy. Replace an occurrence of this pattern. Issue identified with Coccinelle. Signed-off-by: Alex Dewar <alex.dewar90@gmail.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200909190213.156302-1-alex.dewar90@gmail.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 52f5c5a2ed647..7e9a62ad56e83 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -1049,12 +1049,10 @@ static void debugfs_create_files(void *data) }; int i; - dsi->debugfs_vpg = kmalloc(sizeof(debugfs), GFP_KERNEL); + dsi->debugfs_vpg = kmemdup(debugfs, sizeof(debugfs), GFP_KERNEL); if (!dsi->debugfs_vpg) return; - memcpy(dsi->debugfs_vpg, debugfs, sizeof(debugfs)); - for (i = 0; i < ARRAY_SIZE(debugfs); i++) debugfs_create_file(dsi->debugfs_vpg[i].name, 0644, dsi->debugfs, &dsi->debugfs_vpg[i], -- GitLab From a328ca7e4af347e47742f36933df0fdac1c24ea5 Mon Sep 17 00:00:00 2001 From: Neil Armstrong <narmstrong@baylibre.com> Date: Fri, 4 Sep 2020 14:55:31 +0200 Subject: [PATCH 1055/1494] drm/bridge: dw-mipi-dsi: permit configuring the escape clock rate The Amlogic D-PHY in the Amlogic AXG SoC Family does support a frequency higher than 10MHz for the TX Escape Clock, thus make the target rate configurable. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Philippe Cornu <philippe.cornu@st.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904125531.15248-1-narmstrong@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 25 +++++++++++++++---- include/drm/bridge/dw_mipi_dsi.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 7e9a62ad56e83..6b268f9445b36 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -605,15 +605,30 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi) static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) { + const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; + unsigned int esc_rate; /* in MHz */ + u32 esc_clk_division; + int ret; + /* * The maximum permitted escape clock is 20MHz and it is derived from - * lanebyteclk, which is running at "lane_mbps / 8". Thus we want: - * - * (lane_mbps >> 3) / esc_clk_division < 20 + * lanebyteclk, which is running at "lane_mbps / 8". + */ + if (phy_ops->get_esc_clk_rate) { + ret = phy_ops->get_esc_clk_rate(dsi->plat_data->priv_data, + &esc_rate); + if (ret) + DRM_DEBUG_DRIVER("Phy get_esc_clk_rate() failed\n"); + } else + esc_rate = 20; /* Default to 20MHz */ + + /* + * We want : + * (lane_mbps >> 3) / esc_clk_division < X * which is: - * (lane_mbps >> 3) / 20 > esc_clk_division + * (lane_mbps >> 3) / X > esc_clk_division */ - u32 esc_clk_division = (dsi->lane_mbps >> 3) / 20 + 1; + esc_clk_division = (dsi->lane_mbps >> 3) / esc_rate + 1; dsi_write(dsi, DSI_PWR_UP, RESET); diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h index b0e390b3288e8..bda8aa7c22804 100644 --- a/include/drm/bridge/dw_mipi_dsi.h +++ b/include/drm/bridge/dw_mipi_dsi.h @@ -36,6 +36,7 @@ struct dw_mipi_dsi_phy_ops { unsigned int *lane_mbps); int (*get_timing)(void *priv_data, unsigned int lane_mbps, struct dw_mipi_dsi_dphy_timing *timing); + int (*get_esc_clk_rate)(void *priv_data, unsigned int *esc_clk_rate); }; struct dw_mipi_dsi_host_ops { -- GitLab From 0560c2173e3f12bc39ef5d61b26d43307cab8694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Mon, 7 Sep 2020 19:27:09 +0300 Subject: [PATCH 1056/1494] drm/i915: Nuke dpio_phy_iosf_port[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no real reason to stash away the DPIO PHY IOSF sideband port numbers for VLV/CHV. Just compute them at runtime in the sideband code. Gets rid of the oddball intel_init_dpio() function from the high level init flow. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907162709.29579-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/display/intel_display.h | 2 -- drivers/gpu/drm/i915/i915_drv.c | 16 ---------------- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_reg.h | 1 - drivers/gpu/drm/i915/intel_sideband.c | 16 ++++++++++++++-- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 3670cabeb3cd6..003b68dda9445 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -272,8 +272,6 @@ enum dpio_phy { DPIO_PHY2, }; -#define I915_NUM_PHYS_VLV 2 - enum aux_ch { AUX_CH_A, AUX_CH_B, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2746f3dcdc34d..873634931506d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -215,21 +215,6 @@ intel_teardown_mchbar(struct drm_i915_private *dev_priv) release_resource(&dev_priv->mch_res); } -static void intel_init_dpio(struct drm_i915_private *dev_priv) -{ - /* - * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C), - * CHV x1 PHY (DP/HDMI D) - * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C) - */ - if (IS_CHERRYVIEW(dev_priv)) { - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2; - DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO; - } else if (IS_VALLEYVIEW(dev_priv)) { - DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO; - } -} - static int i915_workqueues_init(struct drm_i915_private *dev_priv) { /* @@ -358,7 +343,6 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) intel_detect_pch(dev_priv); intel_pm_setup(dev_priv); - intel_init_dpio(dev_priv); ret = intel_power_domains_init(dev_priv); if (ret < 0) goto err_gem; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bf33cbfcf2a1a..c5a06d3d1c392 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1030,8 +1030,6 @@ struct drm_i915_private { */ u8 active_pipes; - int dpio_phy_iosf_port[I915_NUM_PHYS_VLV]; - struct i915_wa_list gt_wa_list; struct i915_frontbuffer_tracking fb_tracking; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ab4b1abd4364d..90a05e37ba2fe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1382,7 +1382,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define DPIO_CMNRST (1 << 0) #define DPIO_PHY(pipe) ((pipe) >> 1) -#define DPIO_PHY_IOSF_PORT(phy) (dev_priv->dpio_phy_iosf_port[phy]) /* * Per pipe/PLL DPIO regs diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 916ccd1c0e969..5b32792621232 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -231,9 +231,21 @@ void vlv_ccu_write(struct drm_i915_private *i915, u32 reg, u32 val) SB_CRWRDA_NP, reg, &val); } +static u32 vlv_dpio_phy_iosf_port(struct drm_i915_private *i915, enum dpio_phy phy) +{ + /* + * IOSF_PORT_DPIO: VLV x2 PHY (DP/HDMI B and C), CHV x1 PHY (DP/HDMI D) + * IOSF_PORT_DPIO_2: CHV x2 PHY (DP/HDMI B and C) + */ + if (IS_CHERRYVIEW(i915)) + return phy == DPIO_PHY0 ? IOSF_PORT_DPIO_2 : IOSF_PORT_DPIO; + else + return IOSF_PORT_DPIO; +} + u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg) { - int port = i915->dpio_phy_iosf_port[DPIO_PHY(pipe)]; + u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe)); u32 val = 0; vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MRD_NP, reg, &val); @@ -252,7 +264,7 @@ u32 vlv_dpio_read(struct drm_i915_private *i915, enum pipe pipe, int reg) void vlv_dpio_write(struct drm_i915_private *i915, enum pipe pipe, int reg, u32 val) { - int port = i915->dpio_phy_iosf_port[DPIO_PHY(pipe)]; + u32 port = vlv_dpio_phy_iosf_port(i915, DPIO_PHY(pipe)); vlv_sideband_rw(i915, DPIO_DEVFN, port, SB_MWR_NP, reg, &val); } -- GitLab From 5684daa71383324bcd048bc5bc15428c5556ae5e Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Thu, 10 Sep 2020 22:06:30 +0800 Subject: [PATCH 1057/1494] drm: xlnx: remove defined but not used 'scaling_factors_666' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This addresses the following gcc warning with "make W=1": drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: ‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] 245 | static const u32 scaling_factors_666[] = { | ^~~~~~~~~~~~~~~~~~~ Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Hyun Kwon <hyun.kwon@xilinx.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200910140630.1191782-1-yanaijie@huawei.com --- drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c index a455cfc1bee53..98bd48f13fd11 100644 --- a/drivers/gpu/drm/xlnx/zynqmp_disp.c +++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c @@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { ZYNQMP_DISP_AV_BUF_5BIT_SF, }; -static const u32 scaling_factors_666[] = { - ZYNQMP_DISP_AV_BUF_6BIT_SF, - ZYNQMP_DISP_AV_BUF_6BIT_SF, - ZYNQMP_DISP_AV_BUF_6BIT_SF, -}; - static const u32 scaling_factors_888[] = { ZYNQMP_DISP_AV_BUF_8BIT_SF, ZYNQMP_DISP_AV_BUF_8BIT_SF, -- GitLab From d5653a994a665c66f26a92b57a1d4dcb3639c9ea Mon Sep 17 00:00:00 2001 From: Robin Murphy <robin.murphy@arm.com> Date: Thu, 3 Sep 2020 22:04:03 +0100 Subject: [PATCH 1058/1494] drm/msm: Drop local dma_parms Since commit 9495b7e92f71 ("driver core: platform: Initialize dma_parms for platform devices"), struct platform_device already provides a dma_parms structure, so we can save allocating another one. Also the DMA segment size is simply a size, not a bitmask. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/msm_drv.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 79333842f70a1..8796b7c861ecd 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -453,15 +453,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) if (ret) goto err_msm_uninit; - if (!dev->dma_parms) { - dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), - GFP_KERNEL); - if (!dev->dma_parms) { - ret = -ENOMEM; - goto err_msm_uninit; - } - } - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dma_set_max_seg_size(dev, UINT_MAX); msm_gem_shrinker_init(ddev); -- GitLab From 763aecddcd32a3f0d695e1f550ac834dbc881c5e Mon Sep 17 00:00:00 2001 From: Jonathan Marek <jonathan@marek.ca> Date: Fri, 11 Sep 2020 11:09:37 -0400 Subject: [PATCH 1059/1494] drm/msm/dsi: remove unused clk_pre/clk_post in msm_dsi_dphy_timing The clk_pre/clk_post values in shared_timings are used instead, and these are unused. Signed-off-by: Jonathan Marek <jonathan@marek.ca> Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> (SM8250) Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index ef8672d7b1235..886a9e3b44b51 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -50,8 +50,6 @@ extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs; struct msm_dsi_dphy_timing { - u32 clk_pre; - u32 clk_post; u32 clk_zero; u32 clk_trail; u32 clk_prepare; -- GitLab From 11550636040dddadcb2ffec18c37fb2c5105a04a Mon Sep 17 00:00:00 2001 From: Jonathan Marek <jonathan@marek.ca> Date: Fri, 11 Sep 2020 11:09:38 -0400 Subject: [PATCH 1060/1494] drm/msm/dsi: add DSI config for sm8150 and sm8250 This allows DSI driver to work with sm8150 and sm8250. The sdm845 config is re-used as the config is the same. Signed-off-by: Jonathan Marek <jonathan@marek.ca> Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> (SM8250) Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dsi/dsi_cfg.c | 5 ++++- drivers/gpu/drm/msm/dsi/dsi_cfg.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index f892f2cbe8bb6..b2ff68a15791a 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -265,9 +265,12 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = { &msm8998_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_2_1, &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_4_0, + &sdm845_dsi_cfg, &msm_dsi_6g_v2_host_ops}, {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V2_4_1, &sc7180_dsi_cfg, &msm_dsi_6g_v2_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 efd469d1db459..ade9b609c7d98 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h @@ -21,6 +21,8 @@ #define MSM_DSI_6G_VER_MINOR_V2_1_0 0x20010000 #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_4_0 0x20040000 #define MSM_DSI_6G_VER_MINOR_V2_4_1 0x20040001 #define MSM_DSI_V2_VER_MINOR_8064 0x0 -- GitLab From 1ef7c99d145c2759308e53bf19f2cc971677680c Mon Sep 17 00:00:00 2001 From: Jonathan Marek <jonathan@marek.ca> Date: Fri, 11 Sep 2020 11:09:39 -0400 Subject: [PATCH 1061/1494] drm/msm/dsi: add support for 7nm DSI PHY/PLL This adds support for the 7nm ("V4") DSI PHY/PLL for sm8150 and sm8250. Implementation is based on 10nm driver, but updated based on the downstream 7nm driver. Signed-off-by: Jonathan Marek <jonathan@marek.ca> Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> (SM8250) Signed-off-by: Rob Clark <robdclark@chromium.org> --- .../devicetree/bindings/display/msm/dsi.txt | 6 +- drivers/gpu/drm/msm/Kconfig | 8 + drivers/gpu/drm/msm/Makefile | 2 + drivers/gpu/drm/msm/dsi/dsi.h | 2 + drivers/gpu/drm/msm/dsi/dsi.xml.h | 423 ++++++++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 102 ++ drivers/gpu/drm/msm/dsi/phy/dsi_phy.h | 4 + drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c | 255 +++++ drivers/gpu/drm/msm/dsi/pll/dsi_pll.c | 4 + drivers/gpu/drm/msm/dsi/pll/dsi_pll.h | 10 + drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 904 ++++++++++++++++++ 11 files changed, 1718 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt index 7884fd7a85c12..b9a64d3ff1848 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi.txt +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt @@ -90,6 +90,8 @@ Required properties: * "qcom,dsi-phy-14nm-660" * "qcom,dsi-phy-10nm" * "qcom,dsi-phy-10nm-8998" + * "qcom,dsi-phy-7nm" + * "qcom,dsi-phy-7nm-8150" - reg: Physical base address and length of the registers of PLL, PHY. Some revisions require the PHY regulator base address, whereas others require the PHY lane base address. See below for each PHY revision. @@ -98,7 +100,7 @@ Required properties: * "dsi_pll" * "dsi_phy" * "dsi_phy_regulator" - For DSI 14nm and 10nm PHYs: + For DSI 14nm, 10nm and 7nm PHYs: * "dsi_pll" * "dsi_phy" * "dsi_phy_lane" @@ -116,7 +118,7 @@ Required properties: - vcca-supply: phandle to vcca regulator device node For 14nm PHY: - vcca-supply: phandle to vcca regulator device node - For 10nm PHY: + For 10nm and 7nm PHY: - vdds-supply: phandle to vdds regulator device node Optional properties: diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 6deaa7d01654b..5c55cd0ce9f9b 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -110,3 +110,11 @@ config DRM_MSM_DSI_10NM_PHY default y help Choose this option if DSI PHY on SDM845 is used on the platform. + +config DRM_MSM_DSI_7NM_PHY + bool "Enable DSI 7nm PHY driver in MSM DRM (used by SM8150/SM8250)" + depends on DRM_MSM_DSI + default y + help + Choose this option if DSI PHY on SM8150/SM8250 is used on the + platform. diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 42f8aae28b31d..c65cdd6397a35 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -119,6 +119,7 @@ msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/phy/dsi_phy_14nm.o msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/phy/dsi_phy_10nm.o +msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/phy/dsi_phy_7nm.o ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y) msm-y += dsi/pll/dsi_pll.o @@ -126,6 +127,7 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o msm-$(CONFIG_DRM_MSM_DSI_14NM_PHY) += dsi/pll/dsi_pll_14nm.o msm-$(CONFIG_DRM_MSM_DSI_10NM_PHY) += dsi/pll/dsi_pll_10nm.o +msm-$(CONFIG_DRM_MSM_DSI_7NM_PHY) += dsi/pll/dsi_pll_7nm.o endif obj-$(CONFIG_DRM_MSM) += msm.o diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 4de771d6f0be8..78ef5d4ed922f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -30,6 +30,8 @@ enum msm_dsi_phy_type { MSM_DSI_PHY_28NM_8960, MSM_DSI_PHY_14NM, MSM_DSI_PHY_10NM, + MSM_DSI_PHY_7NM, + MSM_DSI_PHY_7NM_V4_1, MSM_DSI_PHY_MAX }; diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h index 8e536e0600709..50eb4d1b8fddf 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.xml.h +++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h @@ -1886,5 +1886,428 @@ static inline uint32_t REG_DSI_10nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x0000 #define REG_DSI_10nm_PHY_PLL_COMMON_STATUS_ONE 0x000001a0 +#define REG_DSI_7nm_PHY_CMN_REVISION_ID0 0x00000000 + +#define REG_DSI_7nm_PHY_CMN_REVISION_ID1 0x00000004 + +#define REG_DSI_7nm_PHY_CMN_REVISION_ID2 0x00000008 + +#define REG_DSI_7nm_PHY_CMN_REVISION_ID3 0x0000000c + +#define REG_DSI_7nm_PHY_CMN_CLK_CFG0 0x00000010 + +#define REG_DSI_7nm_PHY_CMN_CLK_CFG1 0x00000014 + +#define REG_DSI_7nm_PHY_CMN_GLBL_CTRL 0x00000018 + +#define REG_DSI_7nm_PHY_CMN_RBUF_CTRL 0x0000001c + +#define REG_DSI_7nm_PHY_CMN_VREG_CTRL_0 0x00000020 + +#define REG_DSI_7nm_PHY_CMN_CTRL_0 0x00000024 + +#define REG_DSI_7nm_PHY_CMN_CTRL_1 0x00000028 + +#define REG_DSI_7nm_PHY_CMN_CTRL_2 0x0000002c + +#define REG_DSI_7nm_PHY_CMN_CTRL_3 0x00000030 + +#define REG_DSI_7nm_PHY_CMN_LANE_CFG0 0x00000034 + +#define REG_DSI_7nm_PHY_CMN_LANE_CFG1 0x00000038 + +#define REG_DSI_7nm_PHY_CMN_PLL_CNTRL 0x0000003c + +#define REG_DSI_7nm_PHY_CMN_DPHY_SOT 0x00000040 + +#define REG_DSI_7nm_PHY_CMN_LANE_CTRL0 0x000000a0 + +#define REG_DSI_7nm_PHY_CMN_LANE_CTRL1 0x000000a4 + +#define REG_DSI_7nm_PHY_CMN_LANE_CTRL2 0x000000a8 + +#define REG_DSI_7nm_PHY_CMN_LANE_CTRL3 0x000000ac + +#define REG_DSI_7nm_PHY_CMN_LANE_CTRL4 0x000000b0 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0 0x000000b4 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1 0x000000b8 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2 0x000000bc + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3 0x000000c0 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4 0x000000c4 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5 0x000000c8 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6 0x000000cc + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7 0x000000d0 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8 0x000000d4 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9 0x000000d8 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10 0x000000dc + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11 0x000000e0 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12 0x000000e4 + +#define REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13 0x000000e8 + +#define REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0 0x000000ec + +#define REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_1 0x000000f0 + +#define REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL 0x000000f4 + +#define REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL 0x000000f8 + +#define REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_MID_CTRL 0x000000fc + +#define REG_DSI_7nm_PHY_CMN_GLBL_LPTX_STR_CTRL 0x00000100 + +#define REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0 0x00000104 + +#define REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_1 0x00000108 + +#define REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL 0x0000010c + +#define REG_DSI_7nm_PHY_CMN_VREG_CTRL_1 0x00000110 + +#define REG_DSI_7nm_PHY_CMN_CTRL_4 0x00000114 + +#define REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4 0x00000128 + +#define REG_DSI_7nm_PHY_CMN_PHY_STATUS 0x00000140 + +#define REG_DSI_7nm_PHY_CMN_LANE_STATUS0 0x00000148 + +#define REG_DSI_7nm_PHY_CMN_LANE_STATUS1 0x0000014c + +static inline uint32_t REG_DSI_7nm_PHY_LN(uint32_t i0) { return 0x00000000 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_CFG0(uint32_t i0) { return 0x00000000 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_CFG1(uint32_t i0) { return 0x00000004 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_CFG2(uint32_t i0) { return 0x00000008 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000000c + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_PIN_SWAP(uint32_t i0) { return 0x00000010 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_LPRX_CTRL(uint32_t i0) { return 0x00000014 + 0x80*i0; } + +static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000018 + 0x80*i0; } + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_ONE 0x00000000 + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO 0x00000004 + +#define REG_DSI_7nm_PHY_PLL_INT_LOOP_SETTINGS 0x00000008 + +#define REG_DSI_7nm_PHY_PLL_INT_LOOP_SETTINGS_TWO 0x0000000c + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE 0x00000010 + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FOUR 0x00000014 + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE 0x00000018 + +#define REG_DSI_7nm_PHY_PLL_INT_LOOP_CONTROLS 0x0000001c + +#define REG_DSI_7nm_PHY_PLL_DSM_DIVIDER 0x00000020 + +#define REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER 0x00000024 + +#define REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES 0x00000028 + +#define REG_DSI_7nm_PHY_PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x0000002c + +#define REG_DSI_7nm_PHY_PLL_CMODE 0x00000030 + +#define REG_DSI_7nm_PHY_PLL_PSM_CTRL 0x00000034 + +#define REG_DSI_7nm_PHY_PLL_RSM_CTRL 0x00000038 + +#define REG_DSI_7nm_PHY_PLL_VCO_TUNE_MAP 0x0000003c + +#define REG_DSI_7nm_PHY_PLL_PLL_CNTRL 0x00000040 + +#define REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS 0x00000044 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_TIMER_LOW 0x00000048 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_TIMER_HIGH 0x0000004c + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS 0x00000050 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_MIN 0x00000054 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_MAX 0x00000058 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_PFILT 0x0000005c + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_IFILT 0x00000060 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_TWO 0x00000064 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE 0x00000068 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x0000006c + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_ICODE_HIGH 0x00000070 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_ICODE_LOW 0x00000074 + +#define REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE 0x00000078 + +#define REG_DSI_7nm_PHY_PLL_FREQ_DETECT_THRESH 0x0000007c + +#define REG_DSI_7nm_PHY_PLL_FREQ_DET_REFCLK_HIGH 0x00000080 + +#define REG_DSI_7nm_PHY_PLL_FREQ_DET_REFCLK_LOW 0x00000084 + +#define REG_DSI_7nm_PHY_PLL_FREQ_DET_PLLCLK_HIGH 0x00000088 + +#define REG_DSI_7nm_PHY_PLL_FREQ_DET_PLLCLK_LOW 0x0000008c + +#define REG_DSI_7nm_PHY_PLL_PFILT 0x00000090 + +#define REG_DSI_7nm_PHY_PLL_IFILT 0x00000094 + +#define REG_DSI_7nm_PHY_PLL_PLL_GAIN 0x00000098 + +#define REG_DSI_7nm_PHY_PLL_ICODE_LOW 0x0000009c + +#define REG_DSI_7nm_PHY_PLL_ICODE_HIGH 0x000000a0 + +#define REG_DSI_7nm_PHY_PLL_LOCKDET 0x000000a4 + +#define REG_DSI_7nm_PHY_PLL_OUTDIV 0x000000a8 + +#define REG_DSI_7nm_PHY_PLL_FASTLOCK_CONTROL 0x000000ac + +#define REG_DSI_7nm_PHY_PLL_PASS_OUT_OVERRIDE_ONE 0x000000b0 + +#define REG_DSI_7nm_PHY_PLL_PASS_OUT_OVERRIDE_TWO 0x000000b4 + +#define REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE 0x000000b8 + +#define REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE 0x000000bc + +#define REG_DSI_7nm_PHY_PLL_RATE_CHANGE 0x000000c0 + +#define REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS 0x000000c4 + +#define REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO 0x000000c8 + +#define REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START 0x000000cc + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW 0x000000d0 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID 0x000000d4 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH 0x000000d8 + +#define REG_DSI_7nm_PHY_PLL_DEC_FRAC_MUXES 0x000000dc + +#define REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1 0x000000e0 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1 0x000000e4 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1 0x000000e8 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1 0x000000ec + +#define REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_2 0x000000f0 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_2 0x000000f4 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_2 0x000000f8 + +#define REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_2 0x000000fc + +#define REG_DSI_7nm_PHY_PLL_MASH_CONTROL 0x00000100 + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW 0x00000104 + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH 0x00000108 + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW 0x0000010c + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH 0x00000110 + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW 0x00000114 + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH 0x00000118 + +#define REG_DSI_7nm_PHY_PLL_SSC_MUX_CONTROL 0x0000011c + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1 0x00000120 + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1 0x00000124 + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1 0x00000128 + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1 0x0000012c + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1 0x00000130 + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1 0x00000134 + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_2 0x00000138 + +#define REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_2 0x0000013c + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_2 0x00000140 + +#define REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_2 0x00000144 + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_2 0x00000148 + +#define REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_2 0x0000014c + +#define REG_DSI_7nm_PHY_PLL_SSC_CONTROL 0x00000150 + +#define REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE 0x00000154 + +#define REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1 0x00000158 + +#define REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_2 0x0000015c + +#define REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1 0x00000160 + +#define REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_2 0x00000164 + +#define REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1 0x00000168 + +#define REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_2 0x0000016c + +#define REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1 0x00000170 + +#define REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_2 0x00000174 + +#define REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x00000178 + +#define REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_2 0x0000017c + +#define REG_DSI_7nm_PHY_PLL_PLL_FASTLOCK_EN_BAND 0x00000180 + +#define REG_DSI_7nm_PHY_PLL_FREQ_TUNE_ACCUM_INIT_MID 0x00000184 + +#define REG_DSI_7nm_PHY_PLL_FREQ_TUNE_ACCUM_INIT_HIGH 0x00000188 + +#define REG_DSI_7nm_PHY_PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x0000018c + +#define REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE 0x00000190 + +#define REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY 0x00000194 + +#define REG_DSI_7nm_PHY_PLL_PLL_LOCK_MIN_DELAY 0x00000198 + +#define REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS 0x0000019c + +#define REG_DSI_7nm_PHY_PLL_SPARE_AND_JPC_OVERRIDES 0x000001a0 + +#define REG_DSI_7nm_PHY_PLL_BIAS_CONTROL_1 0x000001a4 + +#define REG_DSI_7nm_PHY_PLL_BIAS_CONTROL_2 0x000001a8 + +#define REG_DSI_7nm_PHY_PLL_ALOG_OBSV_BUS_CTRL_1 0x000001ac + +#define REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE 0x000001b0 + +#define REG_DSI_7nm_PHY_PLL_COMMON_STATUS_TWO 0x000001b4 + +#define REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL 0x000001b8 + +#define REG_DSI_7nm_PHY_PLL_ICODE_ACCUM_STATUS_LOW 0x000001bc + +#define REG_DSI_7nm_PHY_PLL_ICODE_ACCUM_STATUS_HIGH 0x000001c0 + +#define REG_DSI_7nm_PHY_PLL_FD_OUT_LOW 0x000001c4 + +#define REG_DSI_7nm_PHY_PLL_FD_OUT_HIGH 0x000001c8 + +#define REG_DSI_7nm_PHY_PLL_ALOG_OBSV_BUS_STATUS_1 0x000001cc + +#define REG_DSI_7nm_PHY_PLL_PLL_MISC_CONFIG 0x000001d0 + +#define REG_DSI_7nm_PHY_PLL_FLL_CONFIG 0x000001d4 + +#define REG_DSI_7nm_PHY_PLL_FLL_FREQ_ACQ_TIME 0x000001d8 + +#define REG_DSI_7nm_PHY_PLL_FLL_CODE0 0x000001dc + +#define REG_DSI_7nm_PHY_PLL_FLL_CODE1 0x000001e0 + +#define REG_DSI_7nm_PHY_PLL_FLL_GAIN0 0x000001e4 + +#define REG_DSI_7nm_PHY_PLL_FLL_GAIN1 0x000001e8 + +#define REG_DSI_7nm_PHY_PLL_SW_RESET 0x000001ec + +#define REG_DSI_7nm_PHY_PLL_FAST_PWRUP 0x000001f0 + +#define REG_DSI_7nm_PHY_PLL_LOCKTIME0 0x000001f4 + +#define REG_DSI_7nm_PHY_PLL_LOCKTIME1 0x000001f8 + +#define REG_DSI_7nm_PHY_PLL_DEBUG_BUS_SEL 0x000001fc + +#define REG_DSI_7nm_PHY_PLL_DEBUG_BUS0 0x00000200 + +#define REG_DSI_7nm_PHY_PLL_DEBUG_BUS1 0x00000204 + +#define REG_DSI_7nm_PHY_PLL_DEBUG_BUS2 0x00000208 + +#define REG_DSI_7nm_PHY_PLL_DEBUG_BUS3 0x0000020c + +#define REG_DSI_7nm_PHY_PLL_ANALOG_FLL_CONTROL_OVERRIDES 0x00000210 + +#define REG_DSI_7nm_PHY_PLL_VCO_CONFIG 0x00000214 + +#define REG_DSI_7nm_PHY_PLL_VCO_CAL_CODE1_MODE0_STATUS 0x00000218 + +#define REG_DSI_7nm_PHY_PLL_VCO_CAL_CODE1_MODE1_STATUS 0x0000021c + +#define REG_DSI_7nm_PHY_PLL_RESET_SM_STATUS 0x00000220 + +#define REG_DSI_7nm_PHY_PLL_TDC_OFFSET 0x00000224 + +#define REG_DSI_7nm_PHY_PLL_PS3_PWRDOWN_CONTROLS 0x00000228 + +#define REG_DSI_7nm_PHY_PLL_PS4_PWRDOWN_CONTROLS 0x0000022c + +#define REG_DSI_7nm_PHY_PLL_PLL_RST_CONTROLS 0x00000230 + +#define REG_DSI_7nm_PHY_PLL_GEAR_BAND_SELECT_CONTROLS 0x00000234 + +#define REG_DSI_7nm_PHY_PLL_PSM_CLK_CONTROLS 0x00000238 + +#define REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES_2 0x0000023c + +#define REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1 0x00000240 + +#define REG_DSI_7nm_PHY_PLL_VCO_CONFIG_2 0x00000244 + +#define REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS_1 0x00000248 + +#define REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS_2 0x0000024c + +#define REG_DSI_7nm_PHY_PLL_CMODE_1 0x00000250 + +#define REG_DSI_7nm_PHY_PLL_CMODE_2 0x00000254 + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1 0x00000258 + +#define REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_2 0x0000025c + +#define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE 0x00000260 #endif /* DSI_XML */ diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 009f5b843dd1a..e8c1a727179cc 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -364,6 +364,102 @@ int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing, return 0; } +int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing, + struct msm_dsi_phy_clk_request *clk_req) +{ + const unsigned long bit_rate = clk_req->bitclk_rate; + const unsigned long esc_rate = clk_req->escclk_rate; + s32 ui, ui_x8; + s32 tmax, tmin; + s32 pcnt_clk_prep = 50; + s32 pcnt_clk_zero = 2; + s32 pcnt_clk_trail = 30; + s32 pcnt_hs_prep = 50; + s32 pcnt_hs_zero = 10; + s32 pcnt_hs_trail = 30; + s32 pcnt_hs_exit = 10; + s32 coeff = 1000; /* Precision, should avoid overflow */ + s32 hb_en; + s32 temp; + + if (!bit_rate || !esc_rate) + return -EINVAL; + + hb_en = 0; + + ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000); + ui_x8 = ui << 3; + + /* TODO: verify these calculations against latest downstream driver + * everything except clk_post/clk_pre uses calculations from v3 based + * on the downstream driver having the same calculations for v3 and v4 + */ + + temp = S_DIV_ROUND_UP(38 * coeff, ui_x8); + tmin = max_t(s32, temp, 0); + temp = (95 * coeff) / ui_x8; + tmax = max_t(s32, temp, 0); + timing->clk_prepare = linear_inter(tmax, tmin, pcnt_clk_prep, 0, false); + + temp = 300 * coeff - (timing->clk_prepare << 3) * ui; + tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1; + tmax = (tmin > 255) ? 511 : 255; + timing->clk_zero = linear_inter(tmax, tmin, pcnt_clk_zero, 0, false); + + tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8); + temp = 105 * coeff + 12 * ui - 20 * coeff; + tmax = (temp + 3 * ui) / ui_x8; + timing->clk_trail = linear_inter(tmax, tmin, pcnt_clk_trail, 0, false); + + temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8); + tmin = max_t(s32, temp, 0); + temp = (85 * coeff + 6 * ui) / ui_x8; + tmax = max_t(s32, temp, 0); + timing->hs_prepare = linear_inter(tmax, tmin, pcnt_hs_prep, 0, false); + + temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui; + tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1; + tmax = 255; + timing->hs_zero = linear_inter(tmax, tmin, pcnt_hs_zero, 0, false); + + tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1; + temp = 105 * coeff + 12 * ui - 20 * coeff; + tmax = (temp / ui_x8) - 1; + timing->hs_trail = linear_inter(tmax, tmin, pcnt_hs_trail, 0, false); + + temp = 50 * coeff + ((hb_en << 2) - 8) * ui; + timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8); + + tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1; + tmax = 255; + timing->hs_exit = linear_inter(tmax, tmin, pcnt_hs_exit, 0, false); + + /* recommended min + * = roundup((mipi_min_ns + t_hs_trail_ns)/(16*bit_clk_ns), 0) - 1 + */ + temp = 60 * coeff + 52 * ui + + (timing->hs_trail + 1) * ui_x8; + tmin = DIV_ROUND_UP(temp, 16 * ui) - 1; + tmax = 255; + timing->shared_timings.clk_post = linear_inter(tmax, tmin, 5, 0, false); + + /* recommended min + * val1 = (tlpx_ns + clk_prepare_ns + clk_zero_ns + hs_rqst_ns) + * val2 = (16 * bit_clk_ns) + * final = roundup(val1/val2, 0) - 1 + */ + temp = 52 * coeff + (timing->clk_prepare + timing->clk_zero + 1) * ui_x8 + 54 * coeff; + tmin = DIV_ROUND_UP(temp, 16 * ui) - 1; + tmax = 255; + timing->shared_timings.clk_pre = DIV_ROUND_UP((tmax - tmin) * 125, 10000) + tmin; + + DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d", + timing->shared_timings.clk_pre, timing->shared_timings.clk_post, + timing->clk_zero, timing->clk_trail, timing->clk_prepare, timing->hs_exit, + timing->hs_zero, timing->hs_prepare, timing->hs_trail, timing->hs_rqst); + + return 0; +} + void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, u32 bit_mask) { @@ -507,6 +603,12 @@ static const struct of_device_id dsi_phy_dt_match[] = { .data = &dsi_phy_10nm_cfgs }, { .compatible = "qcom,dsi-phy-10nm-8998", .data = &dsi_phy_10nm_8998_cfgs }, +#endif +#ifdef CONFIG_DRM_MSM_DSI_7NM_PHY + { .compatible = "qcom,dsi-phy-7nm", + .data = &dsi_phy_7nm_cfgs }, + { .compatible = "qcom,dsi-phy-7nm-8150", + .data = &dsi_phy_7nm_8150_cfgs }, #endif {} }; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h index 886a9e3b44b51..d2bd74b6f357a 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h @@ -48,6 +48,8 @@ extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs; extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs; +extern const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs; struct msm_dsi_dphy_timing { u32 clk_zero; @@ -100,6 +102,8 @@ int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing, struct msm_dsi_phy_clk_request *clk_req); int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing, struct msm_dsi_phy_clk_request *clk_req); +int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing, + struct msm_dsi_phy_clk_request *clk_req); void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg, u32 bit_mask); int msm_dsi_phy_init_common(struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c new file mode 100644 index 0000000000000..255b5f5ab2ce0 --- /dev/null +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_7nm.c @@ -0,0 +1,255 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * Copyright (c) 2018, The Linux Foundation + */ + +#include <linux/iopoll.h> + +#include "dsi_phy.h" +#include "dsi.xml.h" + +static int dsi_phy_hw_v4_0_is_pll_on(struct msm_dsi_phy *phy) +{ + void __iomem *base = phy->base; + u32 data = 0; + + data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL); + mb(); /* make sure read happened */ + + return (data & BIT(0)); +} + +static void dsi_phy_hw_v4_0_config_lpcdrx(struct msm_dsi_phy *phy, bool enable) +{ + void __iomem *lane_base = phy->lane_base; + int phy_lane_0 = 0; /* TODO: Support all lane swap configs */ + + /* + * LPRX and CDRX need to enabled only for physical data lane + * corresponding to the logical data lane 0 + */ + if (enable) + dsi_phy_write(lane_base + + REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0x3); + else + dsi_phy_write(lane_base + + REG_DSI_7nm_PHY_LN_LPRX_CTRL(phy_lane_0), 0); +} + +static void dsi_phy_hw_v4_0_lane_settings(struct msm_dsi_phy *phy) +{ + int i; + const u8 tx_dctrl_0[] = { 0x00, 0x00, 0x00, 0x04, 0x01 }; + const u8 tx_dctrl_1[] = { 0x40, 0x40, 0x40, 0x46, 0x41 }; + const u8 *tx_dctrl = tx_dctrl_0; + void __iomem *lane_base = phy->lane_base; + + if (phy->cfg->type == MSM_DSI_PHY_7NM_V4_1) + tx_dctrl = tx_dctrl_1; + + /* Strength ctrl settings */ + for (i = 0; i < 5; i++) { + /* + * Disable LPRX and CDRX for all lanes. And later on, it will + * be only enabled for the physical data lane corresponding + * to the logical data lane 0 + */ + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_LPRX_CTRL(i), 0); + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_PIN_SWAP(i), 0x0); + } + + dsi_phy_hw_v4_0_config_lpcdrx(phy, true); + + /* other settings */ + for (i = 0; i < 5; i++) { + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG0(i), 0x0); + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG1(i), 0x0); + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_CFG2(i), i == 4 ? 0x8a : 0xa); + dsi_phy_write(lane_base + REG_DSI_7nm_PHY_LN_TX_DCTRL(i), tx_dctrl[i]); + } +} + +static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id, + struct msm_dsi_phy_clk_request *clk_req) +{ + int ret; + u32 status; + u32 const delay_us = 5; + u32 const timeout_us = 1000; + struct msm_dsi_dphy_timing *timing = &phy->timing; + void __iomem *base = phy->base; + bool less_than_1500_mhz; + u32 vreg_ctrl_0, glbl_str_swi_cal_sel_ctrl, glbl_hstx_str_ctrl_0; + u32 glbl_rescode_top_ctrl, glbl_rescode_bot_ctrl; + u32 data; + + DBG(""); + + if (msm_dsi_dphy_timing_calc_v4(timing, clk_req)) { + DRM_DEV_ERROR(&phy->pdev->dev, + "%s: D-PHY timing calculation failed\n", __func__); + return -EINVAL; + } + + if (dsi_phy_hw_v4_0_is_pll_on(phy)) + pr_warn("PLL turned on before configuring PHY\n"); + + /* wait for REFGEN READY */ + ret = readl_poll_timeout_atomic(base + REG_DSI_7nm_PHY_CMN_PHY_STATUS, + status, (status & BIT(0)), + delay_us, timeout_us); + if (ret) { + pr_err("Ref gen not ready. Aborting\n"); + return -EINVAL; + } + + /* TODO: CPHY enable path (this is for DPHY only) */ + + /* Alter PHY configurations if data rate less than 1.5GHZ*/ + less_than_1500_mhz = (clk_req->bitclk_rate <= 1500000000); + + if (phy->cfg->type == MSM_DSI_PHY_7NM_V4_1) { + vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52; + glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00; + glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c; + glbl_str_swi_cal_sel_ctrl = 0x00; + glbl_hstx_str_ctrl_0 = 0x88; + } else { + vreg_ctrl_0 = less_than_1500_mhz ? 0x5B : 0x59; + glbl_str_swi_cal_sel_ctrl = less_than_1500_mhz ? 0x03 : 0x00; + glbl_hstx_str_ctrl_0 = less_than_1500_mhz ? 0x66 : 0x88; + glbl_rescode_top_ctrl = 0x03; + glbl_rescode_bot_ctrl = 0x3c; + } + + /* de-assert digital and pll power down */ + data = BIT(6) | BIT(5); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, data); + + /* Assert PLL core reset */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x00); + + /* turn off resync FIFO */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0x00); + + /* program CMN_CTRL_4 for minor_ver 2 chipsets*/ + data = dsi_phy_read(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0); + data = data & (0xf0); + if (data == 0x20) + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_4, 0x04); + + /* Configure PHY lane swap (TODO: we need to calculate this) */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG0, 0x21); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CFG1, 0x84); + + /* Enable LDO */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_0, vreg_ctrl_0); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_VREG_CTRL_1, 0x5c); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x00); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_STR_SWI_CAL_SEL_CTRL, + glbl_str_swi_cal_sel_ctrl); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_HSTX_STR_CTRL_0, + glbl_hstx_str_ctrl_0); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_PEMPH_CTRL_0, 0x00); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_TOP_CTRL, + glbl_rescode_top_ctrl); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_RESCODE_OFFSET_BOT_CTRL, + glbl_rescode_bot_ctrl); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_GLBL_LPTX_STR_CTRL, 0x55); + + /* Remove power down from all blocks */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_0, 0x7f); + + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0, 0x1f); + + /* Select full-rate mode */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_CTRL_2, 0x40); + + ret = msm_dsi_pll_set_usecase(phy->pll, phy->usecase); + if (ret) { + DRM_DEV_ERROR(&phy->pdev->dev, "%s: set pll usecase failed, %d\n", + __func__, ret); + return ret; + } + + /* DSI PHY timings */ + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_0, 0x00); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_1, timing->clk_zero); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_2, timing->clk_prepare); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_3, timing->clk_trail); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_4, timing->hs_exit); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_5, timing->hs_zero); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_6, timing->hs_prepare); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_7, timing->hs_trail); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_8, timing->hs_rqst); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_9, 0x02); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_10, 0x04); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_11, 0x00); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_12, + timing->shared_timings.clk_pre); + dsi_phy_write(base + REG_DSI_7nm_PHY_CMN_TIMING_CTRL_13, + timing->shared_timings.clk_post); + + /* DSI lane settings */ + dsi_phy_hw_v4_0_lane_settings(phy); + + DBG("DSI%d PHY enabled", phy->id); + + return 0; +} + +static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) +{ + /* TODO */ +} + +static int dsi_7nm_phy_init(struct msm_dsi_phy *phy) +{ + struct platform_device *pdev = phy->pdev; + + phy->lane_base = msm_ioremap(pdev, "dsi_phy_lane", + "DSI_PHY_LANE"); + if (IS_ERR(phy->lane_base)) { + DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", + __func__); + return -ENOMEM; + } + + return 0; +} + +const struct msm_dsi_phy_cfg dsi_phy_7nm_cfgs = { + .type = MSM_DSI_PHY_7NM_V4_1, + .src_pll_truthtable = { {false, false}, {true, false} }, + .reg_cfg = { + .num = 1, + .regs = { + {"vdds", 36000, 32}, + }, + }, + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .init = dsi_7nm_phy_init, + }, + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, +}; + +const struct msm_dsi_phy_cfg dsi_phy_7nm_8150_cfgs = { + .type = MSM_DSI_PHY_7NM, + .src_pll_truthtable = { {false, false}, {true, false} }, + .reg_cfg = { + .num = 1, + .regs = { + {"vdds", 36000, 32}, + }, + }, + .ops = { + .enable = dsi_7nm_phy_enable, + .disable = dsi_7nm_phy_disable, + .init = dsi_7nm_phy_init, + }, + .io_start = { 0xae94400, 0xae96400 }, + .num_dsi_phy = 2, +}; diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c index 4a4aa3c61d710..a45fe95aff494 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c @@ -161,6 +161,10 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev, case MSM_DSI_PHY_10NM: pll = msm_dsi_pll_10nm_init(pdev, id); break; + case MSM_DSI_PHY_7NM: + case MSM_DSI_PHY_7NM_V4_1: + pll = msm_dsi_pll_7nm_init(pdev, id); + break; default: pll = ERR_PTR(-ENXIO); break; diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h index c6a3623f905da..3405982a092c4 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h @@ -116,5 +116,15 @@ msm_dsi_pll_10nm_init(struct platform_device *pdev, int id) return ERR_PTR(-ENODEV); } #endif +#ifdef CONFIG_DRM_MSM_DSI_7NM_PHY +struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id); +#else +static inline struct msm_dsi_pll * +msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) +{ + return ERR_PTR(-ENODEV); +} +#endif + #endif /* __DSI_PLL_H__ */ diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c new file mode 100644 index 0000000000000..029cc8bf5a046 --- /dev/null +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c @@ -0,0 +1,904 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * Copyright (c) 2018, The Linux Foundation + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/iopoll.h> + +#include "dsi_pll.h" +#include "dsi.xml.h" + +/* + * DSI PLL 7nm - clock diagram (eg: DSI0): TODO: updated CPHY diagram + * + * dsi0_pll_out_div_clk dsi0_pll_bit_clk + * | | + * | | + * +---------+ | +----------+ | +----+ + * dsi0vco_clk ---| out_div |--o--| divl_3_0 |--o--| /8 |-- dsi0_phy_pll_out_byteclk + * +---------+ | +----------+ | +----+ + * | | + * | | dsi0_pll_by_2_bit_clk + * | | | + * | | +----+ | |\ dsi0_pclk_mux + * | |--| /2 |--o--| \ | + * | | +----+ | \ | +---------+ + * | --------------| |--o--| div_7_4 |-- dsi0_phy_pll_out_dsiclk + * |------------------------------| / +---------+ + * | +-----+ | / + * -----------| /4? |--o----------|/ + * +-----+ | | + * | |dsiclk_sel + * | + * dsi0_pll_post_out_div_clk + */ + +#define DSI_BYTE_PLL_CLK 0 +#define DSI_PIXEL_PLL_CLK 1 +#define NUM_PROVIDED_CLKS 2 + +#define VCO_REF_CLK_RATE 19200000 + +struct dsi_pll_regs { + u32 pll_prop_gain_rate; + u32 pll_lockdet_rate; + u32 decimal_div_start; + u32 frac_div_start_low; + u32 frac_div_start_mid; + u32 frac_div_start_high; + u32 pll_clock_inverters; + u32 ssc_stepsize_low; + u32 ssc_stepsize_high; + u32 ssc_div_per_low; + u32 ssc_div_per_high; + u32 ssc_adjper_low; + u32 ssc_adjper_high; + u32 ssc_control; +}; + +struct dsi_pll_config { + u32 ref_freq; + bool div_override; + u32 output_div; + bool ignore_frac; + bool disable_prescaler; + bool enable_ssc; + bool ssc_center; + u32 dec_bits; + u32 frac_bits; + u32 lock_timer; + u32 ssc_freq; + u32 ssc_offset; + u32 ssc_adj_per; + u32 thresh_cycles; + u32 refclk_cycles; +}; + +struct pll_7nm_cached_state { + unsigned long vco_rate; + u8 bit_clk_div; + u8 pix_clk_div; + u8 pll_out_div; + u8 pll_mux; +}; + +struct dsi_pll_7nm { + struct msm_dsi_pll base; + + int id; + struct platform_device *pdev; + + void __iomem *phy_cmn_mmio; + void __iomem *mmio; + + u64 vco_ref_clk_rate; + u64 vco_current_rate; + + /* protects REG_DSI_7nm_PHY_CMN_CLK_CFG0 register */ + spinlock_t postdiv_lock; + + int vco_delay; + struct dsi_pll_config pll_configuration; + struct dsi_pll_regs reg_setup; + + /* private clocks: */ + struct clk_hw *out_div_clk_hw; + struct clk_hw *bit_clk_hw; + struct clk_hw *byte_clk_hw; + struct clk_hw *by_2_bit_clk_hw; + struct clk_hw *post_out_div_clk_hw; + struct clk_hw *pclk_mux_hw; + struct clk_hw *out_dsiclk_hw; + + /* clock-provider: */ + struct clk_hw_onecell_data *hw_data; + + struct pll_7nm_cached_state cached_state; + + enum msm_dsi_phy_usecase uc; + struct dsi_pll_7nm *slave; +}; + +#define to_pll_7nm(x) container_of(x, struct dsi_pll_7nm, base) + +/* + * Global list of private DSI PLL struct pointers. We need this for Dual DSI + * mode, where the master PLL's clk_ops needs access the slave's private data + */ +static struct dsi_pll_7nm *pll_7nm_list[DSI_MAX]; + +static void dsi_pll_setup_config(struct dsi_pll_7nm *pll) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + + config->ref_freq = pll->vco_ref_clk_rate; + config->output_div = 1; + config->dec_bits = 8; + config->frac_bits = 18; + config->lock_timer = 64; + config->ssc_freq = 31500; + config->ssc_offset = 4800; + config->ssc_adj_per = 2; + config->thresh_cycles = 32; + config->refclk_cycles = 256; + + config->div_override = false; + config->ignore_frac = false; + config->disable_prescaler = false; + + /* TODO: ssc enable */ + config->enable_ssc = false; + config->ssc_center = 0; +} + +static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + struct dsi_pll_regs *regs = &pll->reg_setup; + u64 fref = pll->vco_ref_clk_rate; + u64 pll_freq; + u64 divider; + u64 dec, dec_multiple; + u32 frac; + u64 multiplier; + + pll_freq = pll->vco_current_rate; + + if (config->disable_prescaler) + divider = fref; + else + divider = fref * 2; + + multiplier = 1 << config->frac_bits; + dec_multiple = div_u64(pll_freq * multiplier, divider); + div_u64_rem(dec_multiple, multiplier, &frac); + + dec = div_u64(dec_multiple, multiplier); + + if (pll->base.type != MSM_DSI_PHY_7NM_V4_1) + regs->pll_clock_inverters = 0x28; + else if (pll_freq <= 1000000000ULL) + regs->pll_clock_inverters = 0xa0; + else if (pll_freq <= 2500000000ULL) + regs->pll_clock_inverters = 0x20; + else if (pll_freq <= 3020000000ULL) + regs->pll_clock_inverters = 0x00; + else + regs->pll_clock_inverters = 0x40; + + regs->pll_lockdet_rate = config->lock_timer; + regs->decimal_div_start = dec; + regs->frac_div_start_low = (frac & 0xff); + regs->frac_div_start_mid = (frac & 0xff00) >> 8; + regs->frac_div_start_high = (frac & 0x30000) >> 16; +} + +#define SSC_CENTER BIT(0) +#define SSC_EN BIT(1) + +static void dsi_pll_calc_ssc(struct dsi_pll_7nm *pll) +{ + struct dsi_pll_config *config = &pll->pll_configuration; + struct dsi_pll_regs *regs = &pll->reg_setup; + u32 ssc_per; + u32 ssc_mod; + u64 ssc_step_size; + u64 frac; + + if (!config->enable_ssc) { + DBG("SSC not enabled\n"); + return; + } + + ssc_per = DIV_ROUND_CLOSEST(config->ref_freq, config->ssc_freq) / 2 - 1; + ssc_mod = (ssc_per + 1) % (config->ssc_adj_per + 1); + ssc_per -= ssc_mod; + + frac = regs->frac_div_start_low | + (regs->frac_div_start_mid << 8) | + (regs->frac_div_start_high << 16); + ssc_step_size = regs->decimal_div_start; + ssc_step_size *= (1 << config->frac_bits); + ssc_step_size += frac; + ssc_step_size *= config->ssc_offset; + ssc_step_size *= (config->ssc_adj_per + 1); + ssc_step_size = div_u64(ssc_step_size, (ssc_per + 1)); + ssc_step_size = DIV_ROUND_CLOSEST_ULL(ssc_step_size, 1000000); + + regs->ssc_div_per_low = ssc_per & 0xFF; + regs->ssc_div_per_high = (ssc_per & 0xFF00) >> 8; + regs->ssc_stepsize_low = (u32)(ssc_step_size & 0xFF); + regs->ssc_stepsize_high = (u32)((ssc_step_size & 0xFF00) >> 8); + regs->ssc_adjper_low = config->ssc_adj_per & 0xFF; + regs->ssc_adjper_high = (config->ssc_adj_per & 0xFF00) >> 8; + + regs->ssc_control = config->ssc_center ? SSC_CENTER : 0; + + pr_debug("SCC: Dec:%d, frac:%llu, frac_bits:%d\n", + regs->decimal_div_start, frac, config->frac_bits); + pr_debug("SSC: div_per:0x%X, stepsize:0x%X, adjper:0x%X\n", + ssc_per, (u32)ssc_step_size, config->ssc_adj_per); +} + +static void dsi_pll_ssc_commit(struct dsi_pll_7nm *pll) +{ + void __iomem *base = pll->mmio; + struct dsi_pll_regs *regs = &pll->reg_setup; + + if (pll->pll_configuration.enable_ssc) { + pr_debug("SSC is enabled\n"); + + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_LOW_1, + regs->ssc_stepsize_low); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_STEPSIZE_HIGH_1, + regs->ssc_stepsize_high); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_LOW_1, + regs->ssc_div_per_low); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_DIV_PER_HIGH_1, + regs->ssc_div_per_high); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_LOW_1, + regs->ssc_adjper_low); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_ADJPER_HIGH_1, + regs->ssc_adjper_high); + pll_write(base + REG_DSI_7nm_PHY_PLL_SSC_CONTROL, + SSC_EN | regs->ssc_control); + } +} + +static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) +{ + void __iomem *base = pll->mmio; + u8 analog_controls_five_1 = 0x01, vco_config_1 = 0x00; + + if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) { + if (pll->vco_current_rate >= 3100000000ULL) + analog_controls_five_1 = 0x03; + + if (pll->vco_current_rate < 1520000000ULL) + vco_config_1 = 0x08; + else if (pll->vco_current_rate < 2990000000ULL) + vco_config_1 = 0x01; + } + + pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE_1, + analog_controls_five_1); + pll_write(base + REG_DSI_7nm_PHY_PLL_VCO_CONFIG_1, vco_config_1); + pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_FIVE, 0x01); + pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_TWO, 0x03); + pll_write(base + REG_DSI_7nm_PHY_PLL_ANALOG_CONTROLS_THREE, 0x00); + pll_write(base + REG_DSI_7nm_PHY_PLL_DSM_DIVIDER, 0x00); + pll_write(base + REG_DSI_7nm_PHY_PLL_FEEDBACK_DIVIDER, 0x4e); + pll_write(base + REG_DSI_7nm_PHY_PLL_CALIBRATION_SETTINGS, 0x40); + pll_write(base + REG_DSI_7nm_PHY_PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba); + pll_write(base + REG_DSI_7nm_PHY_PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c); + pll_write(base + REG_DSI_7nm_PHY_PLL_OUTDIV, 0x00); + pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_OVERRIDE, 0x00); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_DIGITAL_TIMERS_TWO, 0x08); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_PROP_GAIN_RATE_1, 0x0a); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_BAND_SEL_RATE_1, 0xc0); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x84); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_OVERRIDE, 0x80); + pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x29); + pll_write(base + REG_DSI_7nm_PHY_PLL_PFILT, 0x2f); + pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, 0x2a); + pll_write(base + REG_DSI_7nm_PHY_PLL_IFILT, + pll->base.type == MSM_DSI_PHY_7NM_V4_1 ? 0x3f : 0x22); + + if (pll->base.type == MSM_DSI_PHY_7NM_V4_1) { + pll_write(base + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22); + if (pll->slave) + pll_write(pll->slave->mmio + REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE, 0x22); + } +} + +static void dsi_pll_commit(struct dsi_pll_7nm *pll) +{ + void __iomem *base = pll->mmio; + struct dsi_pll_regs *reg = &pll->reg_setup; + + pll_write(base + REG_DSI_7nm_PHY_PLL_CORE_INPUT_OVERRIDE, 0x12); + pll_write(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1, reg->decimal_div_start); + pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1, reg->frac_div_start_low); + pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1, reg->frac_div_start_mid); + pll_write(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1, reg->frac_div_start_high); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCKDET_RATE_1, 0x40); + pll_write(base + REG_DSI_7nm_PHY_PLL_PLL_LOCK_DELAY, 0x06); + pll_write(base + REG_DSI_7nm_PHY_PLL_CMODE_1, 0x10); /* TODO: 0x00 for CPHY */ + pll_write(base + REG_DSI_7nm_PHY_PLL_CLOCK_INVERTERS, reg->pll_clock_inverters); +} + +static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + + DBG("DSI PLL%d rate=%lu, parent's=%lu", pll_7nm->id, rate, + parent_rate); + + pll_7nm->vco_current_rate = rate; + pll_7nm->vco_ref_clk_rate = VCO_REF_CLK_RATE; + + dsi_pll_setup_config(pll_7nm); + + dsi_pll_calc_dec_frac(pll_7nm); + + dsi_pll_calc_ssc(pll_7nm); + + dsi_pll_commit(pll_7nm); + + dsi_pll_config_hzindep_reg(pll_7nm); + + dsi_pll_ssc_commit(pll_7nm); + + /* flush, ensure all register writes are done*/ + wmb(); + + return 0; +} + +static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll) +{ + int rc; + u32 status = 0; + u32 const delay_us = 100; + u32 const timeout_us = 5000; + + rc = readl_poll_timeout_atomic(pll->mmio + + REG_DSI_7nm_PHY_PLL_COMMON_STATUS_ONE, + status, + ((status & BIT(0)) > 0), + delay_us, + timeout_us); + if (rc) + pr_err("DSI PLL(%d) lock failed, status=0x%08x\n", + pll->id, status); + + return rc; +} + +static void dsi_pll_disable_pll_bias(struct dsi_pll_7nm *pll) +{ + u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0); + + pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0); + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data & ~BIT(5)); + ndelay(250); +} + +static void dsi_pll_enable_pll_bias(struct dsi_pll_7nm *pll) +{ + u32 data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0); + + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_0, data | BIT(5)); + pll_write(pll->mmio + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES, 0xc0); + ndelay(250); +} + +static void dsi_pll_disable_global_clk(struct dsi_pll_7nm *pll) +{ + u32 data; + + data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, data & ~BIT(5)); +} + +static void dsi_pll_enable_global_clk(struct dsi_pll_7nm *pll) +{ + u32 data; + + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CTRL_3, 0x04); + + data = pll_read(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_CLK_CFG1, + data | BIT(5) | BIT(4)); +} + +static void dsi_pll_phy_dig_reset(struct dsi_pll_7nm *pll) +{ + /* + * Reset the PHY digital domain. This would be needed when + * coming out of a CX or analog rail power collapse while + * ensuring that the pads maintain LP00 or LP11 state + */ + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, BIT(0)); + wmb(); /* Ensure that the reset is deasserted */ + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE4, 0x0); + wmb(); /* Ensure that the reset is deasserted */ +} + +static int dsi_pll_7nm_vco_prepare(struct clk_hw *hw) +{ + struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + int rc; + + dsi_pll_enable_pll_bias(pll_7nm); + if (pll_7nm->slave) + dsi_pll_enable_pll_bias(pll_7nm->slave); + + /* Start PLL */ + pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0x01); + + /* + * ensure all PLL configurations are written prior to checking + * for PLL lock. + */ + wmb(); + + /* Check for PLL lock */ + rc = dsi_pll_7nm_lock_status(pll_7nm); + if (rc) { + pr_err("PLL(%d) lock failed\n", pll_7nm->id); + goto error; + } + + pll->pll_on = true; + + /* + * assert power on reset for PHY digital in case the PLL is + * enabled after CX of analog domain power collapse. This needs + * to be done before enabling the global clk. + */ + dsi_pll_phy_dig_reset(pll_7nm); + if (pll_7nm->slave) + dsi_pll_phy_dig_reset(pll_7nm->slave); + + dsi_pll_enable_global_clk(pll_7nm); + if (pll_7nm->slave) + dsi_pll_enable_global_clk(pll_7nm->slave); + +error: + return rc; +} + +static void dsi_pll_disable_sub(struct dsi_pll_7nm *pll) +{ + pll_write(pll->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_RBUF_CTRL, 0); + dsi_pll_disable_pll_bias(pll); +} + +static void dsi_pll_7nm_vco_unprepare(struct clk_hw *hw) +{ + struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + + /* + * To avoid any stray glitches while abruptly powering down the PLL + * make sure to gate the clock using the clock enable bit before + * powering down the PLL + */ + dsi_pll_disable_global_clk(pll_7nm); + pll_write(pll_7nm->phy_cmn_mmio + REG_DSI_7nm_PHY_CMN_PLL_CNTRL, 0); + dsi_pll_disable_sub(pll_7nm); + if (pll_7nm->slave) { + dsi_pll_disable_global_clk(pll_7nm->slave); + dsi_pll_disable_sub(pll_7nm->slave); + } + /* flush, ensure all register writes are done */ + wmb(); + pll->pll_on = false; +} + +static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct msm_dsi_pll *pll = hw_clk_to_pll(hw); + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + void __iomem *base = pll_7nm->mmio; + u64 ref_clk = pll_7nm->vco_ref_clk_rate; + u64 vco_rate = 0x0; + u64 multiplier; + u32 frac; + u32 dec; + u64 pll_freq, tmp64; + + dec = pll_read(base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1); + dec &= 0xff; + + frac = pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_LOW_1); + frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_MID_1) & + 0xff) << 8); + frac |= ((pll_read(base + REG_DSI_7nm_PHY_PLL_FRAC_DIV_START_HIGH_1) & + 0x3) << 16); + + /* + * TODO: + * 1. Assumes prescaler is disabled + * 2. Multiplier is 2^18. it should be 2^(num_of_frac_bits) + */ + multiplier = 1 << 18; + pll_freq = dec * (ref_clk * 2); + tmp64 = (ref_clk * 2 * frac); + pll_freq += div_u64(tmp64, multiplier); + + vco_rate = pll_freq; + + DBG("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x", + pll_7nm->id, (unsigned long)vco_rate, dec, frac); + + return (unsigned long)vco_rate; +} + +static const struct clk_ops clk_ops_dsi_pll_7nm_vco = { + .round_rate = msm_dsi_pll_helper_clk_round_rate, + .set_rate = dsi_pll_7nm_vco_set_rate, + .recalc_rate = dsi_pll_7nm_vco_recalc_rate, + .prepare = dsi_pll_7nm_vco_prepare, + .unprepare = dsi_pll_7nm_vco_unprepare, +}; + +/* + * PLL Callbacks + */ + +static void dsi_pll_7nm_save_state(struct msm_dsi_pll *pll) +{ + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + struct pll_7nm_cached_state *cached = &pll_7nm->cached_state; + void __iomem *phy_base = pll_7nm->phy_cmn_mmio; + u32 cmn_clk_cfg0, cmn_clk_cfg1; + + cached->pll_out_div = pll_read(pll_7nm->mmio + + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); + cached->pll_out_div &= 0x3; + + cmn_clk_cfg0 = pll_read(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; + + cmn_clk_cfg1 = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + cached->pll_mux = cmn_clk_cfg1 & 0x3; + + DBG("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x", + pll_7nm->id, cached->pll_out_div, cached->bit_clk_div, + cached->pix_clk_div, cached->pll_mux); +} + +static int dsi_pll_7nm_restore_state(struct msm_dsi_pll *pll) +{ + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + struct pll_7nm_cached_state *cached = &pll_7nm->cached_state; + void __iomem *phy_base = pll_7nm->phy_cmn_mmio; + u32 val; + + val = pll_read(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE); + val &= ~0x3; + val |= cached->pll_out_div; + pll_write(pll_7nm->mmio + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, val); + + pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG0, + cached->bit_clk_div | (cached->pix_clk_div << 4)); + + val = pll_read(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1); + val &= ~0x3; + val |= cached->pll_mux; + pll_write(phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, val); + + DBG("DSI PLL%d", pll_7nm->id); + + return 0; +} + +static int dsi_pll_7nm_set_usecase(struct msm_dsi_pll *pll, + enum msm_dsi_phy_usecase uc) +{ + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + void __iomem *base = pll_7nm->phy_cmn_mmio; + u32 data = 0x0; /* internal PLL */ + + DBG("DSI PLL%d", pll_7nm->id); + + switch (uc) { + case MSM_DSI_PHY_STANDALONE: + break; + case MSM_DSI_PHY_MASTER: + pll_7nm->slave = pll_7nm_list[(pll_7nm->id + 1) % DSI_MAX]; + break; + case MSM_DSI_PHY_SLAVE: + data = 0x1; /* external PLL */ + break; + default: + return -EINVAL; + } + + /* set PLL src */ + pll_write(base + REG_DSI_7nm_PHY_CMN_CLK_CFG1, (data << 2)); + + pll_7nm->uc = uc; + + return 0; +} + +static int dsi_pll_7nm_get_provider(struct msm_dsi_pll *pll, + struct clk **byte_clk_provider, + struct clk **pixel_clk_provider) +{ + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + struct clk_hw_onecell_data *hw_data = pll_7nm->hw_data; + + DBG("DSI PLL%d", pll_7nm->id); + + if (byte_clk_provider) + *byte_clk_provider = hw_data->hws[DSI_BYTE_PLL_CLK]->clk; + if (pixel_clk_provider) + *pixel_clk_provider = hw_data->hws[DSI_PIXEL_PLL_CLK]->clk; + + return 0; +} + +static void dsi_pll_7nm_destroy(struct msm_dsi_pll *pll) +{ + struct dsi_pll_7nm *pll_7nm = to_pll_7nm(pll); + struct device *dev = &pll_7nm->pdev->dev; + + DBG("DSI PLL%d", pll_7nm->id); + of_clk_del_provider(dev->of_node); + + clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw); + clk_hw_unregister_mux(pll_7nm->pclk_mux_hw); + clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw); + clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw); + clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw); + clk_hw_unregister_divider(pll_7nm->bit_clk_hw); + clk_hw_unregister_divider(pll_7nm->out_div_clk_hw); + clk_hw_unregister(&pll_7nm->base.clk_hw); +} + +/* + * The post dividers and mux clocks are created using the standard divider and + * mux API. Unlike the 14nm PHY, the slave PLL doesn't need its dividers/mux + * state to follow the master PLL's divider/mux state. Therefore, we don't + * require special clock ops that also configure the slave PLL registers + */ +static int pll_7nm_register(struct dsi_pll_7nm *pll_7nm) +{ + char clk_name[32], parent[32], vco_name[32]; + char parent2[32], parent3[32], parent4[32]; + struct clk_init_data vco_init = { + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .name = vco_name, + .flags = CLK_IGNORE_UNUSED, + .ops = &clk_ops_dsi_pll_7nm_vco, + }; + struct device *dev = &pll_7nm->pdev->dev; + struct clk_hw_onecell_data *hw_data; + struct clk_hw *hw; + int ret; + + DBG("DSI%d", pll_7nm->id); + + hw_data = devm_kzalloc(dev, sizeof(*hw_data) + + NUM_PROVIDED_CLKS * sizeof(struct clk_hw *), + GFP_KERNEL); + if (!hw_data) + return -ENOMEM; + + snprintf(vco_name, 32, "dsi%dvco_clk", pll_7nm->id); + pll_7nm->base.clk_hw.init = &vco_init; + + ret = clk_hw_register(dev, &pll_7nm->base.clk_hw); + if (ret) + return ret; + + snprintf(clk_name, 32, "dsi%d_pll_out_div_clk", pll_7nm->id); + snprintf(parent, 32, "dsi%dvco_clk", pll_7nm->id); + + hw = clk_hw_register_divider(dev, clk_name, + parent, CLK_SET_RATE_PARENT, + pll_7nm->mmio + + REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE, + 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_base_clk_hw; + } + + pll_7nm->out_div_clk_hw = hw; + + snprintf(clk_name, 32, "dsi%d_pll_bit_clk", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id); + + /* BIT CLK: DIV_CTRL_3_0 */ + hw = clk_hw_register_divider(dev, clk_name, parent, + CLK_SET_RATE_PARENT, + pll_7nm->phy_cmn_mmio + + REG_DSI_7nm_PHY_CMN_CLK_CFG0, + 0, 4, CLK_DIVIDER_ONE_BASED, + &pll_7nm->postdiv_lock); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_out_div_clk_hw; + } + + pll_7nm->bit_clk_hw = hw; + + snprintf(clk_name, 32, "dsi%d_phy_pll_out_byteclk", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id); + + /* DSI Byte clock = VCO_CLK / OUT_DIV / BIT_DIV / 8 */ + hw = clk_hw_register_fixed_factor(dev, clk_name, parent, + CLK_SET_RATE_PARENT, 1, 8); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_bit_clk_hw; + } + + pll_7nm->byte_clk_hw = hw; + hw_data->hws[DSI_BYTE_PLL_CLK] = hw; + + snprintf(clk_name, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id); + + hw = clk_hw_register_fixed_factor(dev, clk_name, parent, + 0, 1, 2); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_byte_clk_hw; + } + + pll_7nm->by_2_bit_clk_hw = hw; + + snprintf(clk_name, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pll_out_div_clk", pll_7nm->id); + + hw = clk_hw_register_fixed_factor(dev, clk_name, parent, + 0, 1, 4); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_by_2_bit_clk_hw; + } + + pll_7nm->post_out_div_clk_hw = hw; + + snprintf(clk_name, 32, "dsi%d_pclk_mux", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pll_bit_clk", pll_7nm->id); + snprintf(parent2, 32, "dsi%d_pll_by_2_bit_clk", pll_7nm->id); + snprintf(parent3, 32, "dsi%d_pll_out_div_clk", pll_7nm->id); + snprintf(parent4, 32, "dsi%d_pll_post_out_div_clk", pll_7nm->id); + + hw = clk_hw_register_mux(dev, clk_name, + ((const char *[]){ + parent, parent2, parent3, parent4 + }), 4, 0, pll_7nm->phy_cmn_mmio + + REG_DSI_7nm_PHY_CMN_CLK_CFG1, + 0, 2, 0, NULL); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_post_out_div_clk_hw; + } + + pll_7nm->pclk_mux_hw = hw; + + snprintf(clk_name, 32, "dsi%d_phy_pll_out_dsiclk", pll_7nm->id); + snprintf(parent, 32, "dsi%d_pclk_mux", pll_7nm->id); + + /* PIX CLK DIV : DIV_CTRL_7_4*/ + hw = clk_hw_register_divider(dev, clk_name, parent, + 0, pll_7nm->phy_cmn_mmio + + REG_DSI_7nm_PHY_CMN_CLK_CFG0, + 4, 4, CLK_DIVIDER_ONE_BASED, + &pll_7nm->postdiv_lock); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_pclk_mux_hw; + } + + pll_7nm->out_dsiclk_hw = hw; + hw_data->hws[DSI_PIXEL_PLL_CLK] = hw; + + hw_data->num = NUM_PROVIDED_CLKS; + pll_7nm->hw_data = hw_data; + + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + pll_7nm->hw_data); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret); + goto err_dsiclk_hw; + } + + return 0; + +err_dsiclk_hw: + clk_hw_unregister_divider(pll_7nm->out_dsiclk_hw); +err_pclk_mux_hw: + clk_hw_unregister_mux(pll_7nm->pclk_mux_hw); +err_post_out_div_clk_hw: + clk_hw_unregister_fixed_factor(pll_7nm->post_out_div_clk_hw); +err_by_2_bit_clk_hw: + clk_hw_unregister_fixed_factor(pll_7nm->by_2_bit_clk_hw); +err_byte_clk_hw: + clk_hw_unregister_fixed_factor(pll_7nm->byte_clk_hw); +err_bit_clk_hw: + clk_hw_unregister_divider(pll_7nm->bit_clk_hw); +err_out_div_clk_hw: + clk_hw_unregister_divider(pll_7nm->out_div_clk_hw); +err_base_clk_hw: + clk_hw_unregister(&pll_7nm->base.clk_hw); + + return ret; +} + +struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) +{ + struct dsi_pll_7nm *pll_7nm; + struct msm_dsi_pll *pll; + int ret; + + pll_7nm = devm_kzalloc(&pdev->dev, sizeof(*pll_7nm), GFP_KERNEL); + if (!pll_7nm) + return ERR_PTR(-ENOMEM); + + DBG("DSI PLL%d", id); + + pll_7nm->pdev = pdev; + pll_7nm->id = id; + pll_7nm_list[id] = pll_7nm; + + pll_7nm->phy_cmn_mmio = msm_ioremap(pdev, "dsi_phy", "DSI_PHY"); + if (IS_ERR_OR_NULL(pll_7nm->phy_cmn_mmio)) { + DRM_DEV_ERROR(&pdev->dev, "failed to map CMN PHY base\n"); + return ERR_PTR(-ENOMEM); + } + + pll_7nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL"); + if (IS_ERR_OR_NULL(pll_7nm->mmio)) { + DRM_DEV_ERROR(&pdev->dev, "failed to map PLL base\n"); + return ERR_PTR(-ENOMEM); + } + + spin_lock_init(&pll_7nm->postdiv_lock); + + pll = &pll_7nm->base; + pll->min_rate = 1000000000UL; + pll->max_rate = 3500000000UL; + if (pll->type == MSM_DSI_PHY_7NM_V4_1) { + pll->min_rate = 600000000UL; + pll->max_rate = 5000000000UL; + /* workaround for max rate overflowing on 32-bit builds: */ + pll->max_rate = max(pll->max_rate, 0xffffffffUL); + } + pll->get_provider = dsi_pll_7nm_get_provider; + pll->destroy = dsi_pll_7nm_destroy; + pll->save_state = dsi_pll_7nm_save_state; + pll->restore_state = dsi_pll_7nm_restore_state; + pll->set_usecase = dsi_pll_7nm_set_usecase; + + pll_7nm->vco_delay = 1; + + ret = pll_7nm_register(pll_7nm); + if (ret) { + DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret); + return ERR_PTR(ret); + } + + /* TODO: Remove this when we have proper display handover support */ + msm_dsi_pll_save_state(pll); + + return pll; +} -- GitLab From ec1cb6e4408abe5fb723872d265fefa939f1a2ba Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Tue, 1 Sep 2020 08:41:56 -0700 Subject: [PATCH 1062/1494] drm/msm/gpu: Add suspend/resume tracepoints Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++++ drivers/gpu/drm/msm/msm_gpu.c | 2 ++ drivers/gpu/drm/msm/msm_gpu_trace.h | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 74bc27eb4203c..a7f63be9cdd00 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -931,6 +931,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) gpu->needs_hw_init = true; + trace_msm_gpu_resume(0); + ret = a6xx_gmu_resume(a6xx_gpu); if (ret) return ret; @@ -945,6 +947,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + trace_msm_gpu_suspend(0); + devfreq_suspend_device(gpu->devfreq.devfreq); return a6xx_gmu_stop(a6xx_gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index cec6ec1d3aa73..ce68ff0732a50 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -202,6 +202,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu) int ret; DBG("%s", gpu->name); + trace_msm_gpu_resume(0); ret = enable_pwrrail(gpu); if (ret) @@ -227,6 +228,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu) int ret; DBG("%s", gpu->name); + trace_msm_gpu_suspend(0); devfreq_suspend_device(gpu->devfreq.devfreq); diff --git a/drivers/gpu/drm/msm/msm_gpu_trace.h b/drivers/gpu/drm/msm/msm_gpu_trace.h index 1079fe5512798..03e0c2536b94b 100644 --- a/drivers/gpu/drm/msm/msm_gpu_trace.h +++ b/drivers/gpu/drm/msm/msm_gpu_trace.h @@ -140,6 +140,32 @@ TRACE_EVENT(msm_gem_purge_vmaps, TP_printk("Purging %u vmaps", __entry->unmapped) ); + +TRACE_EVENT(msm_gpu_suspend, + TP_PROTO(int dummy), + TP_ARGS(dummy), + TP_STRUCT__entry( + __field(u32, dummy) + ), + TP_fast_assign( + __entry->dummy = dummy; + ), + TP_printk("%u", __entry->dummy) +); + + +TRACE_EVENT(msm_gpu_resume, + TP_PROTO(int dummy), + TP_ARGS(dummy), + TP_STRUCT__entry( + __field(u32, dummy) + ), + TP_fast_assign( + __entry->dummy = dummy; + ), + TP_printk("%u", __entry->dummy) +); + #endif #undef TRACE_INCLUDE_PATH -- GitLab From 0a48db562c6264da2ae8013491efd6e8dc780520 Mon Sep 17 00:00:00 2001 From: Luca Weiss <luca@z3ntu.xyz> Date: Fri, 11 Sep 2020 18:08:53 +0200 Subject: [PATCH 1063/1494] drm/msm/adreno: fix probe without iommu The function iommu_domain_alloc returns NULL on platforms without IOMMU such as msm8974. This resulted in PTR_ERR(-ENODEV) being assigned to gpu->aspace so the correct code path wasn't taken. Fixes: ccac7ce373c1 ("drm/msm: Refactor address space initialization") Signed-off-by: Luca Weiss <luca@z3ntu.xyz> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 459f10a3710b7..3e6de5d26025b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -189,10 +189,16 @@ struct msm_gem_address_space * adreno_iommu_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) { - struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type); - struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu); + struct iommu_domain *iommu; + struct msm_mmu *mmu; struct msm_gem_address_space *aspace; + iommu = iommu_domain_alloc(&platform_bus_type); + if (!iommu) + return NULL; + + mmu = msm_iommu_new(&pdev->dev, iommu); + aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, 0xffffffff - SZ_16M); -- GitLab From 08d3ab4b46339bc6f97e83b54a3fb4f8bf8f4cd9 Mon Sep 17 00:00:00 2001 From: Zhenzhong Duan <zhenzhong.duan@gmail.com> Date: Sat, 12 Sep 2020 18:25:58 +0800 Subject: [PATCH 1064/1494] drm/msm/a6xx: fix a potential overflow issue It's allocating an array of a6xx_gpu_state_obj structure rathor than its pointers. This patch fix it. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@gmail.com> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index b12f5b4a1bea9..e9ede19193b0e 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -875,7 +875,7 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, int i; a6xx_state->indexed_regs = state_kcalloc(a6xx_state, count, - sizeof(a6xx_state->indexed_regs)); + sizeof(*a6xx_state->indexed_regs)); if (!a6xx_state->indexed_regs) return; -- GitLab From a3367f5ffe9a49d1184815be7b841c9d11ec7bce Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 17 Aug 2020 15:01:26 -0700 Subject: [PATCH 1065/1494] drm/msm: Remove dangling submitqueue references Currently it doesn't matter, since we free the ctx immediately. But when we start refcnt'ing the ctx, we don't want old dangling list entries to hang around. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/msm_submitqueue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index a1d94be7883a0..90c9d84e6155a 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -49,8 +49,10 @@ 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_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) { + list_del(&entry->node); msm_submitqueue_put(entry); + } } int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, -- GitLab From 2fc7b1561fbe502f7a08f3df7e0d0cecee985966 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 17 Aug 2020 15:01:30 -0700 Subject: [PATCH 1066/1494] drm/msm: Add private interface for adreno-smmu This interface will be used for drm/msm to coordinate with the qcom_adreno_smmu_impl to enable/disable TTBR0 translation. Once TTBR0 translation is enabled, the GPU's CP (Command Processor) will directly switch TTBR0 pgtables (and do the necessary TLB inv) synchronized to the GPU's operation. But help from the SMMU driver is needed to initially bootstrap TTBR0 translation, which cannot be done from the GPU. Since this is a very special case, a private interface is used to avoid adding highly driver specific things to the public iommu interface. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- include/linux/adreno-smmu-priv.h | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/linux/adreno-smmu-priv.h diff --git a/include/linux/adreno-smmu-priv.h b/include/linux/adreno-smmu-priv.h new file mode 100644 index 0000000000000..a889f28afb424 --- /dev/null +++ b/include/linux/adreno-smmu-priv.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 Google, Inc + */ + +#ifndef __ADRENO_SMMU_PRIV_H +#define __ADRENO_SMMU_PRIV_H + +#include <linux/io-pgtable.h> + +/** + * struct adreno_smmu_priv - private interface between adreno-smmu and GPU + * + * @cookie: An opque token provided by adreno-smmu and passed + * back into the callbacks + * @get_ttbr1_cfg: Get the TTBR1 config for the GPUs context-bank + * @set_ttbr0_cfg: Set the TTBR0 config for the GPUs context bank. A + * NULL config disables TTBR0 translation, otherwise + * TTBR0 translation is enabled with the specified cfg + * + * The GPU driver (drm/msm) and adreno-smmu work together for controlling + * the GPU's SMMU instance. This is by necessity, as the GPU is directly + * updating the SMMU for context switches, while on the other hand we do + * not want to duplicate all of the initial setup logic from arm-smmu. + * + * This private interface is used for the two drivers to coordinate. The + * cookie and callback functions are populated when the GPU driver attaches + * it's domain. + */ +struct adreno_smmu_priv { + const void *cookie; + const struct io_pgtable_cfg *(*get_ttbr1_cfg)(const void *cookie); + int (*set_ttbr0_cfg)(const void *cookie, const struct io_pgtable_cfg *cfg); +}; + +#endif /* __ADRENO_SMMU_PRIV_H */ \ No newline at end of file -- GitLab From 69a9313b6617745bd841e1357e894abc85b9573d Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 17 Aug 2020 15:01:31 -0700 Subject: [PATCH 1067/1494] drm/msm/gpu: Add dev_to_gpu() helper In a later patch, the drvdata will not directly be 'struct msm_gpu *', so add a helper to reduce the churn. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/adreno/adreno_device.c | 10 ++++------ drivers/gpu/drm/msm/msm_gpu.c | 6 +++--- drivers/gpu/drm/msm/msm_gpu.h | 5 +++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 9eeb46bf2a5dc..26664e1b30c0c 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -282,7 +282,7 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) int ret; if (pdev) - gpu = platform_get_drvdata(pdev); + gpu = dev_to_gpu(&pdev->dev); if (!gpu) { dev_err_once(dev->dev, "no GPU device was found\n"); @@ -425,7 +425,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) static void adreno_unbind(struct device *dev, struct device *master, void *data) { - struct msm_gpu *gpu = dev_get_drvdata(dev); + struct msm_gpu *gpu = dev_to_gpu(dev); pm_runtime_force_suspend(dev); gpu->funcs->destroy(gpu); @@ -490,16 +490,14 @@ static const struct of_device_id dt_match[] = { #ifdef CONFIG_PM static int adreno_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct msm_gpu *gpu = platform_get_drvdata(pdev); + struct msm_gpu *gpu = dev_to_gpu(dev); return gpu->funcs->pm_resume(gpu); } static int adreno_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct msm_gpu *gpu = platform_get_drvdata(pdev); + struct msm_gpu *gpu = dev_to_gpu(dev); return gpu->funcs->pm_suspend(gpu); } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index ce68ff0732a50..7fb7abfb503d6 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -24,7 +24,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) { - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + struct msm_gpu *gpu = dev_to_gpu(dev); struct dev_pm_opp *opp; opp = devfreq_recommended_opp(dev, freq, flags); @@ -47,7 +47,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, static int msm_devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *status) { - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + struct msm_gpu *gpu = dev_to_gpu(dev); ktime_t time; if (gpu->funcs->gpu_get_freq) @@ -66,7 +66,7 @@ static int msm_devfreq_get_dev_status(struct device *dev, static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) { - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); + struct msm_gpu *gpu = dev_to_gpu(dev); if (gpu->funcs->gpu_get_freq) *freq = gpu->funcs->gpu_get_freq(gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 37cffac4cbe34..da1ae2263047b 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -144,6 +144,11 @@ struct msm_gpu { bool hw_apriv; }; +static inline struct msm_gpu *dev_to_gpu(struct device *dev) +{ + return dev_get_drvdata(dev); +} + /* It turns out that all targets use the same ringbuffer size */ #define MSM_GPU_RINGBUFFER_SZ SZ_32K #define MSM_GPU_RINGBUFFER_BLKSIZE 32 -- GitLab From 9cba4056a112785bf25e582fc6e7baa8346fe684 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 17 Aug 2020 15:01:32 -0700 Subject: [PATCH 1068/1494] drm/msm: Set adreno_smmu as gpu's drvdata This will be populated by adreno-smmu, to provide a way for coordinating enabling/disabling TTBR0 translation. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/adreno/adreno_device.c | 2 -- drivers/gpu/drm/msm/msm_gpu.c | 2 +- drivers/gpu/drm/msm/msm_gpu.h | 6 +++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 26664e1b30c0c..58e03b20e1c7a 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -417,8 +417,6 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(gpu); } - dev_set_drvdata(dev, gpu); - return 0; } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 7fb7abfb503d6..f241b216aff52 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -896,7 +896,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->gpu_cx = NULL; gpu->pdev = pdev; - platform_set_drvdata(pdev, gpu); + platform_set_drvdata(pdev, &gpu->adreno_smmu); msm_devfreq_init(gpu); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index da1ae2263047b..1f65aec57a8fe 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -7,6 +7,7 @@ #ifndef __MSM_GPU_H__ #define __MSM_GPU_H__ +#include <linux/adreno-smmu-priv.h> #include <linux/clk.h> #include <linux/interconnect.h> #include <linux/pm_opp.h> @@ -74,6 +75,8 @@ struct msm_gpu { struct platform_device *pdev; const struct msm_gpu_funcs *funcs; + struct adreno_smmu_priv adreno_smmu; + /* performance counters (hw & sw): */ spinlock_t perf_lock; bool perfcntr_active; @@ -146,7 +149,8 @@ struct msm_gpu { static inline struct msm_gpu *dev_to_gpu(struct device *dev) { - return dev_get_drvdata(dev); + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev); + return container_of(adreno_smmu, struct msm_gpu, adreno_smmu); } /* It turns out that all targets use the same ringbuffer size */ -- GitLab From cf655d615931b905bbb40f7b5387eb0efd1742e0 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:36 -0700 Subject: [PATCH 1069/1494] drm/msm: Add a context pointer to the submitqueue Each submitqueue is attached to a context. Add a pointer to the context to the submitqueue at create time and refcount it so that it stays around through the life of the queue. Co-developed-by: Rob Clark <robdclark@chromium.org> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/msm_drv.c | 3 ++- drivers/gpu/drm/msm/msm_drv.h | 20 ++++++++++++++++++++ drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_submit.c | 6 +++--- drivers/gpu/drm/msm/msm_gpu.h | 1 + drivers/gpu/drm/msm/msm_submitqueue.c | 3 +++ 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 8796b7c861ecd..8f00abb720de5 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -586,6 +586,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file) if (!ctx) return -ENOMEM; + kref_init(&ctx->ref); msm_submitqueue_init(dev, ctx); ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL; @@ -607,7 +608,7 @@ static int msm_open(struct drm_device *dev, struct drm_file *file) static void context_close(struct msm_file_private *ctx) { msm_submitqueue_close(ctx); - kfree(ctx); + msm_file_private_put(ctx); } static void msm_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index af259b0573ea0..4561bfb5e745a 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -57,6 +57,7 @@ struct msm_file_private { struct list_head submitqueues; int queueid; struct msm_gem_address_space *aspace; + struct kref ref; }; enum msm_mdp_plane_property { @@ -428,6 +429,25 @@ void msm_submitqueue_close(struct msm_file_private *ctx); void msm_submitqueue_destroy(struct kref *kref); +static inline void __msm_file_private_destroy(struct kref *kref) +{ + struct msm_file_private *ctx = container_of(kref, + struct msm_file_private, ref); + + kfree(ctx); +} + +static inline void msm_file_private_put(struct msm_file_private *ctx) +{ + kref_put(&ctx->ref, __msm_file_private_destroy); +} + +static inline struct msm_file_private *msm_file_private_get( + struct msm_file_private *ctx) +{ + kref_get(&ctx->ref); + return ctx; +} #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 972490b14ba5e..9c573c4269cb5 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -142,6 +142,7 @@ struct msm_gem_submit { bool valid; /* true if no cmdstream patching needed */ bool in_rb; /* "sudo" mode, copy cmds into RB */ struct msm_ringbuffer *ring; + struct msm_file_private *ctx; unsigned int nr_cmds; unsigned int nr_bos; u32 ident; /* A "identifier" for the submit for logging */ diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 8cb9aa15ff90e..1464b04d25d31 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -27,7 +27,7 @@ #define BO_PINNED 0x2000 static struct msm_gem_submit *submit_create(struct drm_device *dev, - struct msm_gpu *gpu, struct msm_gem_address_space *aspace, + struct msm_gpu *gpu, struct msm_gpu_submitqueue *queue, uint32_t nr_bos, uint32_t nr_cmds) { @@ -43,7 +43,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, return NULL; submit->dev = dev; - submit->aspace = aspace; + submit->aspace = queue->ctx->aspace; submit->gpu = gpu; submit->fence = NULL; submit->cmd = (void *)&submit->bos[nr_bos]; @@ -677,7 +677,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } } - submit = submit_create(dev, gpu, ctx->aspace, queue, args->nr_bos, + submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds); if (!submit) { ret = -ENOMEM; diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 1f65aec57a8fe..c4ce462c30c5e 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -193,6 +193,7 @@ struct msm_gpu_submitqueue { u32 flags; u32 prio; int faults; + struct msm_file_private *ctx; struct list_head node; struct kref ref; }; diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 90c9d84e6155a..c3d206105d285 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -12,6 +12,8 @@ void msm_submitqueue_destroy(struct kref *kref) struct msm_gpu_submitqueue *queue = container_of(kref, struct msm_gpu_submitqueue, ref); + msm_file_private_put(queue->ctx); + kfree(queue); } @@ -83,6 +85,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->id = ctx->queueid++; if (id) -- GitLab From 15eb9ad073c035499b4abd7456822c8696ac1941 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:37 -0700 Subject: [PATCH 1070/1494] drm/msm: Drop context arg to gpu->submit() Now that we can get the ctx from the submitqueue, the extra arg is redundant. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> [split out of previous patch to reduce churny noise] Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 +++++------- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 5 ++--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 5 ++--- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 3 +-- drivers/gpu/drm/msm/msm_gem_submit.c | 2 +- drivers/gpu/drm/msm/msm_gpu.c | 9 ++++----- drivers/gpu/drm/msm/msm_gpu.h | 6 ++---- 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index ce3c0b5c167b5..616d9e7980588 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -43,8 +43,7 @@ static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr); } -static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx) +static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct msm_drm_private *priv = gpu->dev->dev_private; struct msm_ringbuffer *ring = submit->ring; @@ -57,7 +56,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == ctx) + if (priv->lastctx == submit->queue->ctx) break; /* fall-thru */ case MSM_SUBMIT_CMD_BUF: @@ -103,8 +102,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit msm_gpu_retire(gpu); } -static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx) +static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); @@ -114,7 +112,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { priv->lastctx = NULL; - a5xx_submit_in_rb(gpu, submit, ctx); + a5xx_submit_in_rb(gpu, submit); return; } @@ -148,7 +146,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == ctx) + if (priv->lastctx == submit->queue->ctx) break; /* fall-thru */ case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index a7f63be9cdd00..bc32e8264e18d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -81,8 +81,7 @@ static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter, OUT_RING(ring, upper_32_bits(iova)); } -static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx) +static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; struct msm_drm_private *priv = gpu->dev->dev_private; @@ -115,7 +114,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_IB_TARGET_BUF: break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - if (priv->lastctx == ctx) + if (priv->lastctx == submit->queue->ctx) break; /* fall-thru */ case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 3e6de5d26025b..ce079e95dd9fc 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -440,8 +440,7 @@ void adreno_recover(struct msm_gpu *gpu) } } -void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx) +void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct msm_drm_private *priv = gpu->dev->dev_private; @@ -455,7 +454,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, break; case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: /* ignore if there has not been a ctx switch: */ - if (priv->lastctx == ctx) + if (priv->lastctx == submit->queue->ctx) break; /* fall-thru */ case MSM_SUBMIT_CMD_BUF: diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index e55abae365b5a..848632758450c 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -269,8 +269,7 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova); int adreno_hw_init(struct msm_gpu *gpu); void adreno_recover(struct msm_gpu *gpu); -void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx); +void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit); void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring); bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring); #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 1464b04d25d31..aa5c60a7132d8 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -785,7 +785,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, } } - msm_gpu_submit(gpu, submit, ctx); + msm_gpu_submit(gpu, submit); args->fence = submit->fence->seqno; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index f241b216aff52..d1be345149830 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -524,7 +524,7 @@ static void recover_worker(struct work_struct *work) struct msm_ringbuffer *ring = gpu->rb[i]; list_for_each_entry(submit, &ring->submits, node) - gpu->funcs->submit(gpu, submit, NULL); + gpu->funcs->submit(gpu, submit); } } @@ -751,8 +751,7 @@ void msm_gpu_retire(struct msm_gpu *gpu) } /* add bo's to gpu's ring, and kick gpu: */ -void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx) +void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { struct drm_device *dev = gpu->dev; struct msm_drm_private *priv = dev->dev_private; @@ -792,8 +791,8 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence); } - gpu->funcs->submit(gpu, submit, ctx); - priv->lastctx = ctx; + gpu->funcs->submit(gpu, submit); + priv->lastctx = submit->queue->ctx; hangcheck_timer_reset(gpu); } diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index c4ce462c30c5e..5cf696169f934 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -46,8 +46,7 @@ struct msm_gpu_funcs { int (*hw_init)(struct msm_gpu *gpu); int (*pm_suspend)(struct msm_gpu *gpu); int (*pm_resume)(struct msm_gpu *gpu); - void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx); + void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit); void (*flush)(struct msm_gpu *gpu, struct msm_ringbuffer *ring); irqreturn_t (*irq)(struct msm_gpu *irq); struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu); @@ -293,8 +292,7 @@ int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime, uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs); void msm_gpu_retire(struct msm_gpu *gpu); -void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, - struct msm_file_private *ctx); +void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit); int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, -- GitLab From e3c64c7221f6d85a3ba4db39a220432933d99a64 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:38 -0700 Subject: [PATCH 1071/1494] drm/msm: Set the global virtual address range from the IOMMU domain Use the aperture settings from the IOMMU domain to set up the virtual address range for the GPU. This allows us to transparently deal with IOMMU side features (like split pagetables). Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 13 +++++++++++-- drivers/gpu/drm/msm/msm_iommu.c | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index ce079e95dd9fc..a833dd0ab7516 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -192,6 +192,7 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, struct iommu_domain *iommu; struct msm_mmu *mmu; struct msm_gem_address_space *aspace; + u64 start, size; iommu = iommu_domain_alloc(&platform_bus_type); if (!iommu) @@ -199,8 +200,16 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, mmu = msm_iommu_new(&pdev->dev, iommu); - aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M, - 0xffffffff - SZ_16M); + /* + * Use the aperture start or SZ_16M, whichever is greater. This will + * ensure that we align with the allocated pagetable range while still + * allowing room in the lower 32 bits for GMEM and whatnot + */ + start = max_t(u64, SZ_16M, iommu->geometry.aperture_start); + size = iommu->geometry.aperture_end - start + 1; + + aspace = msm_gem_address_space_create(mmu, "gpu", + start & GENMASK(48, 0), size); if (IS_ERR(aspace) && !IS_ERR(mmu)) mmu->funcs->destroy(mmu); diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 3a381a9674c92..1b6635504069a 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -36,6 +36,10 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, struct msm_iommu *iommu = to_msm_iommu(mmu); size_t ret; + /* The arm-smmu driver expects the addresses to be sign extended */ + if (iova & BIT_ULL(48)) + iova |= GENMASK_ULL(63, 49); + ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); WARN_ON(!ret); @@ -46,6 +50,9 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len) { struct msm_iommu *iommu = to_msm_iommu(mmu); + if (iova & BIT_ULL(48)) + iova |= GENMASK_ULL(63, 49); + iommu_unmap(iommu->domain, iova, len); return 0; -- GitLab From b145c6e65eb05e123097d726aa9d4f5b8f11c401 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:39 -0700 Subject: [PATCH 1072/1494] drm/msm: Add support to create a local pagetable Add support to create a io-pgtable for use by targets that support per-instance pagetables. In order to support per-instance pagetables the GPU SMMU device needs to have the qcom,adreno-smmu compatible string and split pagetables enabled. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/msm_gpummu.c | 2 +- drivers/gpu/drm/msm/msm_iommu.c | 199 ++++++++++++++++++++++++++++++- drivers/gpu/drm/msm/msm_mmu.h | 16 ++- 4 files changed, 215 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5c55cd0ce9f9b..5ad8c3486ef32 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -8,6 +8,7 @@ config DRM_MSM depends on MMU depends on INTERCONNECT || !INTERCONNECT depends on QCOM_OCMEM || QCOM_OCMEM=n + select IOMMU_IO_PGTABLE select QCOM_MDT_LOADER if ARCH_QCOM select REGULATOR select DRM_KMS_HELPER diff --git a/drivers/gpu/drm/msm/msm_gpummu.c b/drivers/gpu/drm/msm/msm_gpummu.c index 310a31b05faa9..aab121f4beb76 100644 --- a/drivers/gpu/drm/msm/msm_gpummu.c +++ b/drivers/gpu/drm/msm/msm_gpummu.c @@ -102,7 +102,7 @@ struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu) } gpummu->gpu = gpu; - msm_mmu_init(&gpummu->base, dev, &funcs); + msm_mmu_init(&gpummu->base, dev, &funcs, MSM_MMU_GPUMMU); return &gpummu->base; } diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 1b6635504069a..697cc0a059d63 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -4,15 +4,210 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include <linux/adreno-smmu-priv.h> +#include <linux/io-pgtable.h> #include "msm_drv.h" #include "msm_mmu.h" struct msm_iommu { struct msm_mmu base; struct iommu_domain *domain; + atomic_t pagetables; }; + #define to_msm_iommu(x) container_of(x, struct msm_iommu, base) +struct msm_iommu_pagetable { + struct msm_mmu base; + struct msm_mmu *parent; + struct io_pgtable_ops *pgtbl_ops; + phys_addr_t ttbr; + u32 asid; +}; +static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu) +{ + return container_of(mmu, struct msm_iommu_pagetable, base); +} + +static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova, + size_t size) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + size_t unmapped = 0; + + /* Unmap the block one page at a time */ + while (size) { + unmapped += ops->unmap(ops, iova, 4096, NULL); + iova += 4096; + size -= 4096; + } + + iommu_flush_tlb_all(to_msm_iommu(pagetable->parent)->domain); + + return (unmapped == size) ? 0 : -EINVAL; +} + +static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova, + struct sg_table *sgt, size_t len, int prot) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct io_pgtable_ops *ops = pagetable->pgtbl_ops; + struct scatterlist *sg; + size_t mapped = 0; + u64 addr = iova; + unsigned int i; + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + size_t size = sg->length; + phys_addr_t phys = sg_phys(sg); + + /* Map the block one page at a time */ + while (size) { + if (ops->map(ops, addr, phys, 4096, prot, GFP_KERNEL)) { + msm_iommu_pagetable_unmap(mmu, iova, mapped); + return -EINVAL; + } + + phys += 4096; + addr += 4096; + size -= 4096; + mapped += 4096; + } + } + + return 0; +} + +static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu) +{ + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu); + struct msm_iommu *iommu = to_msm_iommu(pagetable->parent); + struct adreno_smmu_priv *adreno_smmu = + dev_get_drvdata(pagetable->parent->dev); + + /* + * If this is the last attached pagetable for the parent, + * disable TTBR0 in the arm-smmu driver + */ + if (atomic_dec_return(&iommu->pagetables) == 0) + adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL); + + free_io_pgtable_ops(pagetable->pgtbl_ops); + kfree(pagetable); +} + +int msm_iommu_pagetable_params(struct msm_mmu *mmu, + phys_addr_t *ttbr, int *asid) +{ + struct msm_iommu_pagetable *pagetable; + + if (mmu->type != MSM_MMU_IOMMU_PAGETABLE) + return -EINVAL; + + pagetable = to_pagetable(mmu); + + if (ttbr) + *ttbr = pagetable->ttbr; + + if (asid) + *asid = pagetable->asid; + + return 0; +} + +static const struct msm_mmu_funcs pagetable_funcs = { + .map = msm_iommu_pagetable_map, + .unmap = msm_iommu_pagetable_unmap, + .destroy = msm_iommu_pagetable_destroy, +}; + +static void msm_iommu_tlb_flush_all(void *cookie) +{ +} + +static void msm_iommu_tlb_flush_walk(unsigned long iova, size_t size, + size_t granule, void *cookie) +{ +} + +static void msm_iommu_tlb_add_page(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t granule, void *cookie) +{ +} + +static const struct iommu_flush_ops null_tlb_ops = { + .tlb_flush_all = msm_iommu_tlb_flush_all, + .tlb_flush_walk = msm_iommu_tlb_flush_walk, + .tlb_flush_leaf = msm_iommu_tlb_flush_walk, + .tlb_add_page = msm_iommu_tlb_add_page, +}; + +struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) +{ + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(parent->dev); + struct msm_iommu *iommu = to_msm_iommu(parent); + struct msm_iommu_pagetable *pagetable; + const struct io_pgtable_cfg *ttbr1_cfg = NULL; + struct io_pgtable_cfg ttbr0_cfg; + int ret; + + /* Get the pagetable configuration from the domain */ + if (adreno_smmu->cookie) + ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); + if (!ttbr1_cfg) + return ERR_PTR(-ENODEV); + + pagetable = kzalloc(sizeof(*pagetable), GFP_KERNEL); + if (!pagetable) + return ERR_PTR(-ENOMEM); + + msm_mmu_init(&pagetable->base, parent->dev, &pagetable_funcs, + MSM_MMU_IOMMU_PAGETABLE); + + /* Clone the TTBR1 cfg as starting point for TTBR0 cfg: */ + ttbr0_cfg = *ttbr1_cfg; + + /* The incoming cfg will have the TTBR1 quirk enabled */ + ttbr0_cfg.quirks &= ~IO_PGTABLE_QUIRK_ARM_TTBR1; + ttbr0_cfg.tlb = &null_tlb_ops; + + pagetable->pgtbl_ops = alloc_io_pgtable_ops(ARM_64_LPAE_S1, + &ttbr0_cfg, iommu->domain); + + if (!pagetable->pgtbl_ops) { + kfree(pagetable); + return ERR_PTR(-ENOMEM); + } + + /* + * 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) { + ret = adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &ttbr0_cfg); + if (ret) { + free_io_pgtable_ops(pagetable->pgtbl_ops); + kfree(pagetable); + return ERR_PTR(ret); + } + } + + /* Needed later for TLB flush */ + pagetable->parent = parent; + pagetable->ttbr = ttbr0_cfg.arm_lpae_s1_cfg.ttbr; + + /* + * TODO we would like each set of page tables to have a unique ASID + * to optimize TLB invalidation. But iommu_flush_tlb_all() will + * end up flushing the ASID used for TTBR1 pagetables, which is not + * what we want. So for now just use the same ASID as TTBR1. + */ + pagetable->asid = 0; + + return &pagetable->base; +} + static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *arg) { @@ -85,9 +280,11 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) return ERR_PTR(-ENOMEM); iommu->domain = domain; - msm_mmu_init(&iommu->base, dev, &funcs); + msm_mmu_init(&iommu->base, dev, &funcs, MSM_MMU_IOMMU); iommu_set_fault_handler(domain, msm_fault_handler, iommu); + atomic_set(&iommu->pagetables, 0); + ret = iommu_attach_device(iommu->domain, dev); if (ret) { kfree(iommu); diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index 3a534ee59bf63..61ade89d9e481 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -17,18 +17,26 @@ struct msm_mmu_funcs { void (*destroy)(struct msm_mmu *mmu); }; +enum msm_mmu_type { + MSM_MMU_GPUMMU, + MSM_MMU_IOMMU, + MSM_MMU_IOMMU_PAGETABLE, +}; + struct msm_mmu { const struct msm_mmu_funcs *funcs; struct device *dev; int (*handler)(void *arg, unsigned long iova, int flags); void *arg; + enum msm_mmu_type type; }; static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev, - const struct msm_mmu_funcs *funcs) + const struct msm_mmu_funcs *funcs, enum msm_mmu_type type) { mmu->dev = dev; mmu->funcs = funcs; + mmu->type = type; } struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain); @@ -41,7 +49,13 @@ 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); + void msm_gpummu_params(struct msm_mmu *mmu, dma_addr_t *pt_base, dma_addr_t *tran_error); + +int msm_iommu_pagetable_params(struct msm_mmu *mmu, phys_addr_t *ttbr, + int *asid); + #endif /* __MSM_MMU_H__ */ -- GitLab From 933415e24bd0dcb29f837040df20e677626054f8 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:40 -0700 Subject: [PATCH 1073/1494] drm/msm: Add support for private address space instances Add support for allocating private address space instances. Targets that support per-context pagetables should implement their own function to allocate private address spaces. The default will return a pointer to the global address space. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/msm_drv.c | 13 +++++++------ drivers/gpu/drm/msm/msm_drv.h | 5 +++++ drivers/gpu/drm/msm/msm_gem_vma.c | 9 +++++++++ drivers/gpu/drm/msm/msm_gpu.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/msm/msm_gpu.h | 5 +++++ 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 8f00abb720de5..e460c78e4d797 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -589,7 +589,7 @@ static int context_init(struct drm_device *dev, struct drm_file *file) kref_init(&ctx->ref); msm_submitqueue_init(dev, ctx); - ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL; + ctx->aspace = msm_gpu_create_private_address_space(priv->gpu); file->driver_priv = ctx; return 0; @@ -772,18 +772,19 @@ static int msm_ioctl_gem_cpu_fini(struct drm_device *dev, void *data, } static int msm_ioctl_gem_info_iova(struct drm_device *dev, - struct drm_gem_object *obj, uint64_t *iova) + struct drm_file *file, struct drm_gem_object *obj, + uint64_t *iova) { - struct msm_drm_private *priv = dev->dev_private; + struct msm_file_private *ctx = file->driver_priv; - if (!priv->gpu) + if (!ctx->aspace) return -EINVAL; /* * Don't pin the memory here - just get an address so that userspace can * be productive */ - return msm_gem_get_iova(obj, priv->gpu->aspace, iova); + return msm_gem_get_iova(obj, ctx->aspace, iova); } static int msm_ioctl_gem_info(struct drm_device *dev, void *data, @@ -822,7 +823,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, args->value = msm_gem_mmap_offset(obj); break; case MSM_INFO_GET_IOVA: - ret = msm_ioctl_gem_info_iova(dev, obj, &args->value); + ret = msm_ioctl_gem_info_iova(dev, file, obj, &args->value); break; case MSM_INFO_SET_NAME: /* length check should leave room for terminating null: */ diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 4561bfb5e745a..2ca9c3c038451 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -249,6 +249,10 @@ int msm_gem_map_vma(struct msm_gem_address_space *aspace, void msm_gem_close_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma); + +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 msm_gem_address_space * @@ -434,6 +438,7 @@ static inline void __msm_file_private_destroy(struct kref *kref) struct msm_file_private *ctx = container_of(kref, struct msm_file_private, ref); + msm_gem_address_space_put(ctx->aspace); kfree(ctx); } diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 5f6a11211b645..29cc1305cf37d 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -27,6 +27,15 @@ void msm_gem_address_space_put(struct msm_gem_address_space *aspace) kref_put(&aspace->kref, msm_gem_address_space_destroy); } +struct msm_gem_address_space * +msm_gem_address_space_get(struct msm_gem_address_space *aspace) +{ + if (!IS_ERR_OR_NULL(aspace)) + kref_get(&aspace->kref); + + return aspace; +} + /* Actually unmap memory for the vma */ void msm_gem_purge_vma(struct msm_gem_address_space *aspace, struct msm_gem_vma *vma) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index d1be345149830..9455c0b713e44 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -827,6 +827,28 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu) return 0; } +/* 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 msm_gem_address_space *aspace = NULL; + + if (!gpu) + return NULL; + + /* + * 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_OR_NULL(aspace)) + aspace = msm_gem_address_space_get(gpu->aspace); + + return aspace; +} + 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) diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 5cf696169f934..04a2f7539712f 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -66,6 +66,8 @@ struct msm_gpu_funcs { void (*gpu_set_freq)(struct msm_gpu *gpu, struct dev_pm_opp *opp); 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 msm_gpu { @@ -298,6 +300,9 @@ 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); + void msm_gpu_cleanup(struct msm_gpu *gpu); struct msm_gpu *adreno_load_gpu(struct drm_device *dev); -- GitLab From 84c31ee16f903b481e7d4b94e2fc931d373494a0 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 17 Aug 2020 15:01:41 -0700 Subject: [PATCH 1074/1494] drm/msm/a6xx: Add support for per-instance pagetables Add support for using per-instance pagetables if all the dependencies are available. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Akhil P Oommen <akhilpo@codeaurora.org> --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 62 +++++++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 + drivers/gpu/drm/msm/msm_ringbuffer.h | 1 + 3 files changed, 64 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index bc32e8264e18d..a3a8d6fd06bbf 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -81,6 +81,49 @@ static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter, OUT_RING(ring, upper_32_bits(iova)); } +static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu, + struct msm_ringbuffer *ring, struct msm_file_private *ctx) +{ + phys_addr_t ttbr; + u32 asid; + u64 memptr = rbmemptr(ring, ttbr0); + + if (ctx == a6xx_gpu->cur_ctx) + return; + + if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid)) + return; + + /* Execute the table update */ + OUT_PKT7(ring, CP_SMMU_TABLE_UPDATE, 4); + OUT_RING(ring, CP_SMMU_TABLE_UPDATE_0_TTBR0_LO(lower_32_bits(ttbr))); + + OUT_RING(ring, + CP_SMMU_TABLE_UPDATE_1_TTBR0_HI(upper_32_bits(ttbr)) | + CP_SMMU_TABLE_UPDATE_1_ASID(asid)); + OUT_RING(ring, CP_SMMU_TABLE_UPDATE_2_CONTEXTIDR(0)); + OUT_RING(ring, CP_SMMU_TABLE_UPDATE_3_CONTEXTBANK(0)); + + /* + * Write the new TTBR0 to the memstore. This is good for debugging. + */ + OUT_PKT7(ring, CP_MEM_WRITE, 4); + 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, lower_32_bits(ttbr)); + OUT_RING(ring, (asid << 16) | upper_32_bits(ttbr)); + + /* + * And finally, trigger a uche flush to be sure there isn't anything + * lingering in that part of the GPU + */ + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, 0x31); + + a6xx_gpu->cur_ctx = ctx; +} + static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) { unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT; @@ -90,6 +133,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) struct msm_ringbuffer *ring = submit->ring; unsigned int i; + a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx); + get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP_0_LO, rbmemptr_stats(ring, index, cpcycles_start)); @@ -704,6 +749,8 @@ static int a6xx_hw_init(struct msm_gpu *gpu) /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; + a6xx_gpu->cur_ctx = NULL; + /* Enable the SQE_to start the CP engine */ gpu_write(gpu, REG_A6XX_CP_SQE_CNTL, 1); @@ -1020,6 +1067,20 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) return (unsigned long)busy_time; } +static struct msm_gem_address_space * +a6xx_create_private_address_space(struct msm_gpu *gpu) +{ + struct msm_mmu *mmu; + + mmu = msm_iommu_pagetable_create(gpu->aspace->mmu); + + if (IS_ERR(mmu)) + return ERR_CAST(mmu); + + return msm_gem_address_space_create(mmu, + "gpu", 0x100000000ULL, 0x1ffffffffULL); +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -1043,6 +1104,7 @@ static const struct adreno_gpu_funcs funcs = { .gpu_state_put = a6xx_gpu_state_put, #endif .create_address_space = adreno_iommu_create_address_space, + .create_private_address_space = a6xx_create_private_address_space, }, .get_timestamp = a6xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index 03ba60d5b07f8..da22d7549d9b4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -19,6 +19,7 @@ struct a6xx_gpu { uint64_t sqe_iova; struct msm_ringbuffer *cur_ring; + struct msm_file_private *cur_ctx; struct a6xx_gmu gmu; }; diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h index 7764373d0ed2b..0987d6bf848cf 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.h +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h @@ -31,6 +31,7 @@ struct msm_rbmemptrs { volatile uint32_t fence; volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT]; + volatile u64 ttbr0; }; struct msm_ringbuffer { -- GitLab From 25faf2f2e06565d5cd0b97f77364fbe38f14ef71 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 17 Aug 2020 15:01:45 -0700 Subject: [PATCH 1075/1494] drm/msm: Show process names in gem_describe In $debugfs/gem we already show any vma(s) associated with an object. Also show process names if the vma's address space is a per-process address space. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 25 +++++++++++++++++++++---- drivers/gpu/drm/msm/msm_gem.h | 5 +++++ drivers/gpu/drm/msm/msm_gem_vma.c | 1 + drivers/gpu/drm/msm/msm_gpu.c | 8 +++++--- drivers/gpu/drm/msm/msm_gpu.h | 2 +- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index e460c78e4d797..abf5799d9a22b 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -589,7 +589,7 @@ 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); + ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current); file->driver_priv = ctx; return 0; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 3cb7aeb93fd3b..76a6c5271e578 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -842,11 +842,28 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) seq_puts(m, " vmas:"); - list_for_each_entry(vma, &msm_obj->vmas, list) - seq_printf(m, " [%s: %08llx,%s,inuse=%d]", - vma->aspace != NULL ? vma->aspace->name : NULL, - vma->iova, vma->mapped ? "mapped" : "unmapped", + list_for_each_entry(vma, &msm_obj->vmas, list) { + const char *name, *comm; + if (vma->aspace) { + struct msm_gem_address_space *aspace = vma->aspace; + struct task_struct *task = + get_pid_task(aspace->pid, PIDTYPE_PID); + if (task) { + comm = kstrdup(task->comm, GFP_KERNEL); + } else { + comm = NULL; + } + name = aspace->name; + } else { + name = comm = NULL; + } + seq_printf(m, " [%s%s%s: aspace=%p, %08llx,%s,inuse=%d]", + name, comm ? ":" : "", comm ? comm : "", + vma->aspace, vma->iova, + vma->mapped ? "mapped" : "unmapped", vma->inuse); + kfree(comm); + } seq_puts(m, "\n"); } diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 9c573c4269cb5..7b1c7a5f8eef4 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -24,6 +24,11 @@ struct msm_gem_address_space { spinlock_t lock; /* Protects drm_mm node allocation/removal */ struct msm_mmu *mmu; struct kref kref; + + /* For address spaces associated with a specific process, this + * will be non-NULL: + */ + struct pid *pid; }; struct msm_gem_vma { diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 29cc1305cf37d..80a8a266d68f9 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -17,6 +17,7 @@ msm_gem_address_space_destroy(struct kref *kref) drm_mm_takedown(&aspace->mm); if (aspace->mmu) aspace->mmu->funcs->destroy(aspace->mmu); + put_pid(aspace->pid); kfree(aspace); } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 9455c0b713e44..29c8d73c9a039 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -829,10 +829,9 @@ 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) +msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *task) { struct msm_gem_address_space *aspace = NULL; - if (!gpu) return NULL; @@ -840,8 +839,11 @@ msm_gpu_create_private_address_space(struct msm_gpu *gpu) * If the target doesn't support private address spaces then return * the global one */ - if (gpu->funcs->create_private_address_space) + 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 (IS_ERR_OR_NULL(aspace)) aspace = msm_gem_address_space_get(gpu->aspace); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 04a2f7539712f..5ee358b480e6e 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -301,7 +301,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, const char *name, struct msm_gpu_config *config); struct msm_gem_address_space * -msm_gpu_create_private_address_space(struct msm_gpu *gpu); +msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *task); void msm_gpu_cleanup(struct msm_gpu *gpu); -- GitLab From 8b465f01eed14df18ecd3ef99e896e8d158227c5 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:53:16 +0200 Subject: [PATCH 1076/1494] drm/mediatek: mtk_dpi: Rename bridge to next_bridge This is really a cosmetic change just to make a bit more readable the code after convert the driver to drm_bridge. The bridge variable name will be used by the encoder drm_bridge, and the chained bridge will be named next_bridge. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_dpi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 5b2026f3291d9..a66728ed6c526 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -64,7 +64,7 @@ enum mtk_dpi_out_color_format { struct mtk_dpi { struct mtk_ddp_comp ddp_comp; struct drm_encoder encoder; - struct drm_bridge *bridge; + struct drm_bridge *next_bridge; void __iomem *regs; struct device *dev; struct clk *engine_clk; @@ -609,7 +609,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->ddp_comp); - ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL, 0); + ret = drm_bridge_attach(&dpi->encoder, dpi->next_bridge, NULL, 0); if (ret) { dev_err(dev, "Failed to attach bridge: %d\n", ret); goto err_cleanup; @@ -769,11 +769,11 @@ static int mtk_dpi_probe(struct platform_device *pdev) } ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, - NULL, &dpi->bridge); + NULL, &dpi->next_bridge); if (ret) return ret; - dev_info(dev, "Found bridge node: %pOF\n", dpi->bridge->of_node); + dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node); comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); if (comp_id < 0) { -- GitLab From f89c696e7f635487481eee0d196ab49730ce8664 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Wed, 26 Aug 2020 10:53:17 +0200 Subject: [PATCH 1077/1494] drm/mediatek: mtk_dpi: Convert to bridge driver Convert mtk_dpi to a bridge driver with built-in encoder support for compatibility with existing component drivers. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/gpu/drm/mediatek/mtk_dpi.c | 71 ++++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index a66728ed6c526..cf11c4850b405 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -64,6 +64,7 @@ enum mtk_dpi_out_color_format { struct mtk_dpi { struct mtk_ddp_comp ddp_comp; struct drm_encoder encoder; + struct drm_bridge bridge; struct drm_bridge *next_bridge; void __iomem *regs; struct device *dev; @@ -83,9 +84,9 @@ struct mtk_dpi { int refcount; }; -static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e) +static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b) { - return container_of(e, struct mtk_dpi, encoder); + return container_of(b, struct mtk_dpi, bridge); } enum mtk_dpi_polarity { @@ -521,50 +522,53 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, return 0; } -static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder) { - return true; + drm_encoder_cleanup(encoder); } -static void mtk_dpi_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = { + .destroy = mtk_dpi_encoder_destroy, +}; + +static int mtk_dpi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) { - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + + return drm_bridge_attach(bridge->encoder, dpi->next_bridge, + &dpi->bridge, flags); +} + +static void mtk_dpi_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct mtk_dpi *dpi = bridge_to_dpi(bridge); drm_mode_copy(&dpi->mode, adjusted_mode); } -static void mtk_dpi_encoder_disable(struct drm_encoder *encoder) +static void mtk_dpi_bridge_disable(struct drm_bridge *bridge) { - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); + struct mtk_dpi *dpi = bridge_to_dpi(bridge); mtk_dpi_power_off(dpi); } -static void mtk_dpi_encoder_enable(struct drm_encoder *encoder) +static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) { - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); + struct mtk_dpi *dpi = bridge_to_dpi(bridge); mtk_dpi_power_on(dpi); mtk_dpi_set_display_mode(dpi, &dpi->mode); } -static int mtk_dpi_atomic_check(struct drm_encoder *encoder, - struct drm_crtc_state *crtc_state, - struct drm_connector_state *conn_state) -{ - return 0; -} - -static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs = { - .mode_fixup = mtk_dpi_encoder_mode_fixup, - .mode_set = mtk_dpi_encoder_mode_set, - .disable = mtk_dpi_encoder_disable, - .enable = mtk_dpi_encoder_enable, - .atomic_check = mtk_dpi_atomic_check, +static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = { + .attach = mtk_dpi_bridge_attach, + .mode_set = mtk_dpi_bridge_mode_set, + .disable = mtk_dpi_bridge_disable, + .enable = mtk_dpi_bridge_enable, }; static void mtk_dpi_start(struct mtk_ddp_comp *comp) @@ -605,11 +609,10 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) dev_err(dev, "Failed to initialize decoder: %d\n", ret); goto err_unregister; } - drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->ddp_comp); - ret = drm_bridge_attach(&dpi->encoder, dpi->next_bridge, NULL, 0); + ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL, 0); if (ret) { dev_err(dev, "Failed to attach bridge: %d\n", ret); goto err_cleanup; @@ -790,8 +793,15 @@ static int mtk_dpi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dpi); + dpi->bridge.funcs = &mtk_dpi_bridge_funcs; + dpi->bridge.of_node = dev->of_node; + dpi->bridge.type = DRM_MODE_CONNECTOR_DPI; + + drm_bridge_add(&dpi->bridge); + ret = component_add(dev, &mtk_dpi_component_ops); if (ret) { + drm_bridge_remove(&dpi->bridge); dev_err(dev, "Failed to add component: %d\n", ret); return ret; } @@ -801,7 +811,10 @@ static int mtk_dpi_probe(struct platform_device *pdev) static int mtk_dpi_remove(struct platform_device *pdev) { + struct mtk_dpi *dpi = platform_get_drvdata(pdev); + component_del(&pdev->dev, &mtk_dpi_component_ops); + drm_bridge_remove(&dpi->bridge); return 0; } -- GitLab From d88656f475d9eba9b23fa71ab59b225459776d6f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Fri, 11 Sep 2020 09:59:22 +0200 Subject: [PATCH 1078/1494] drm/vboxvideo: Use drm_gem_vram_vmap() interfaces VRAM helpers support ref counting for pin and vmap operations, no need to avoid these operations by employing the internal kmap interface. Just use drm_gem_vram_vmap() and let it handle the details. Also unexport the kmap interfaces from VRAM helpers. Vboxvideo was the last user of these internal functions. v2: * fixed a comma in commit description Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Tested-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200911075922.19317-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_vram_helper.c | 56 +-------------------------- drivers/gpu/drm/vboxvideo/vbox_mode.c | 10 +++-- include/drm/drm_gem_vram_helper.h | 3 -- 3 files changed, 8 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 5f10aa7aa0999..11e396c5048a0 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -97,8 +97,8 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; * hardware's draing engine. * * To access a buffer object's memory from the DRM driver, call - * drm_gem_vram_kmap(). It (optionally) maps the buffer into kernel address - * space and returns the memory address. Use drm_gem_vram_kunmap() to + * drm_gem_vram_vmap(). It maps the buffer into kernel address + * space and returns the memory address. Use drm_gem_vram_vunmap() to * release the mapping. */ @@ -437,39 +437,6 @@ static void *drm_gem_vram_kmap_locked(struct drm_gem_vram_object *gbo, return kmap->virtual; } -/** - * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space - * @gbo: the GEM VRAM object - * @map: establish a mapping if necessary - * @is_iomem: returns true if the mapped memory is I/O memory, or false \ - otherwise; can be NULL - * - * This function maps the buffer object into the kernel's address space - * or returns the current mapping. If the parameter map is false, the - * function only queries the current mapping, but does not establish a - * new one. - * - * Returns: - * The buffers virtual address if mapped, or - * NULL if not mapped, or - * an ERR_PTR()-encoded error code otherwise. - */ -void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, - bool *is_iomem) -{ - int ret; - void *virtual; - - ret = ttm_bo_reserve(&gbo->bo, true, false, NULL); - if (ret) - return ERR_PTR(ret); - virtual = drm_gem_vram_kmap_locked(gbo, map, is_iomem); - ttm_bo_unreserve(&gbo->bo); - - return virtual; -} -EXPORT_SYMBOL(drm_gem_vram_kmap); - static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo) { if (WARN_ON_ONCE(!gbo->kmap_use_count)) @@ -485,22 +452,6 @@ static void drm_gem_vram_kunmap_locked(struct drm_gem_vram_object *gbo) */ } -/** - * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object - * @gbo: the GEM VRAM object - */ -void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo) -{ - int ret; - - ret = ttm_bo_reserve(&gbo->bo, false, false, NULL); - if (WARN_ONCE(ret, "ttm_bo_reserve_failed(): ret=%d\n", ret)) - return; - drm_gem_vram_kunmap_locked(gbo); - ttm_bo_unreserve(&gbo->bo); -} -EXPORT_SYMBOL(drm_gem_vram_kunmap); - /** * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address * space @@ -512,9 +463,6 @@ EXPORT_SYMBOL(drm_gem_vram_kunmap); * permanently. Call drm_gem_vram_vunmap() with the returned address to * unmap and unpin the GEM VRAM object. * - * If you have special requirements for the pinning or mapping operations, - * call drm_gem_vram_pin() and drm_gem_vram_kmap() directly. - * * Returns: * The buffer's virtual address on success, or * an ERR_PTR()-encoded error code otherwise. diff --git a/drivers/gpu/drm/vboxvideo/vbox_mode.c b/drivers/gpu/drm/vboxvideo/vbox_mode.c index d9a5af62af890..4fcc0a542b8a6 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_mode.c +++ b/drivers/gpu/drm/vboxvideo/vbox_mode.c @@ -397,11 +397,13 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, vbox_crtc->cursor_enabled = true; - /* pinning is done in prepare/cleanup framebuffer */ - src = drm_gem_vram_kmap(gbo, true, NULL); + src = drm_gem_vram_vmap(gbo); if (IS_ERR(src)) { + /* + * BUG: we should have pinned the BO in prepare_fb(). + */ mutex_unlock(&vbox->hw_mutex); - DRM_WARN("Could not kmap cursor bo, skipping update\n"); + DRM_WARN("Could not map cursor bo, skipping update\n"); return; } @@ -414,7 +416,7 @@ static void vbox_cursor_atomic_update(struct drm_plane *plane, data_size = width * height * 4 + mask_size; copy_cursor_image(src, vbox->cursor_data, width, height, mask_size); - drm_gem_vram_kunmap(gbo); + drm_gem_vram_vunmap(gbo, src); flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE | VBOX_MOUSE_POINTER_ALPHA; diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index a5e477bf96ccd..62cc6e6c3a4fd 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -100,9 +100,6 @@ u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo); s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo); int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag); int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo); -void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map, - bool *is_iomem); -void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo); void *drm_gem_vram_vmap(struct drm_gem_vram_object *gbo); void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo, void *vaddr); -- GitLab From da62cb7230f0871c30dc9789071f63229158d261 Mon Sep 17 00:00:00 2001 From: Jia Yang <jiayang5@huawei.com> Date: Tue, 14 Jul 2020 10:32:36 +0200 Subject: [PATCH 1079/1494] drm: fix double free for gbo in drm_gem_vram_init and drm_gem_vram_create I got a use-after-free report when doing some fuzz test: If ttm_bo_init() fails, the "gbo" and "gbo->bo.base" will be freed by ttm_buffer_object_destroy() in ttm_bo_init(). But then drm_gem_vram_create() and drm_gem_vram_init() will free "gbo" and "gbo->bo.base" again. BUG: KMSAN: use-after-free in drm_vma_offset_remove+0xb3/0x150 CPU: 0 PID: 24282 Comm: syz-executor.1 Tainted: G B W 5.7.0-rc4-msan #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack dump_stack+0x1c9/0x220 kmsan_report+0xf7/0x1e0 __msan_warning+0x58/0xa0 drm_vma_offset_remove+0xb3/0x150 drm_gem_free_mmap_offset drm_gem_object_release+0x159/0x180 drm_gem_vram_init drm_gem_vram_create+0x7c5/0x990 drm_gem_vram_fill_create_dumb drm_gem_vram_driver_dumb_create+0x238/0x590 drm_mode_create_dumb drm_mode_create_dumb_ioctl+0x41d/0x450 drm_ioctl_kernel+0x5a4/0x710 drm_ioctl+0xc6f/0x1240 vfs_ioctl ksys_ioctl __do_sys_ioctl __se_sys_ioctl+0x2e9/0x410 __x64_sys_ioctl+0x4a/0x70 do_syscall_64+0xb8/0x160 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x4689b9 Code: fd e0 fa ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 cb e0 fa ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007f368fa4dc98 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 000000000076bf00 RCX: 00000000004689b9 RDX: 0000000020000240 RSI: 00000000c02064b2 RDI: 0000000000000003 RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00000000004d17e0 R14: 00007f368fa4e6d4 R15: 000000000076bf0c Uninit was created at: kmsan_save_stack_with_flags kmsan_internal_poison_shadow+0x66/0xd0 kmsan_slab_free+0x6e/0xb0 slab_free_freelist_hook slab_free kfree+0x571/0x30a0 drm_gem_vram_destroy ttm_buffer_object_destroy+0xc8/0x130 ttm_bo_release kref_put ttm_bo_put+0x117d/0x23e0 ttm_bo_init_reserved+0x11c0/0x11d0 ttm_bo_init+0x289/0x3f0 drm_gem_vram_init drm_gem_vram_create+0x775/0x990 drm_gem_vram_fill_create_dumb drm_gem_vram_driver_dumb_create+0x238/0x590 drm_mode_create_dumb drm_mode_create_dumb_ioctl+0x41d/0x450 drm_ioctl_kernel+0x5a4/0x710 drm_ioctl+0xc6f/0x1240 vfs_ioctl ksys_ioctl __do_sys_ioctl __se_sys_ioctl+0x2e9/0x410 __x64_sys_ioctl+0x4a/0x70 do_syscall_64+0xb8/0x160 entry_SYSCALL_64_after_hwframe+0x44/0xa9 If ttm_bo_init() fails, the "gbo" will be freed by ttm_buffer_object_destroy() in ttm_bo_init(). But then drm_gem_vram_create() and drm_gem_vram_init() will free "gbo" again. Reported-by: Hulk Robot <hulkci@huawei.com> Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> Signed-off-by: Jia Yang <jiayang5@huawei.com> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20200714083238.28479-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_vram_helper.c | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 11e396c5048a0..4291f0b71021b 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -167,6 +167,10 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, } } +/* + * Note that on error, drm_gem_vram_init will free the buffer object. + */ + static int drm_gem_vram_init(struct drm_device *dev, struct drm_gem_vram_object *gbo, size_t size, unsigned long pg_align) @@ -176,15 +180,19 @@ static int drm_gem_vram_init(struct drm_device *dev, int ret; size_t acc_size; - if (WARN_ONCE(!vmm, "VRAM MM not initialized")) + if (WARN_ONCE(!vmm, "VRAM MM not initialized")) { + kfree(gbo); return -EINVAL; + } bdev = &vmm->bdev; gbo->bo.base.funcs = &drm_gem_vram_object_funcs; ret = drm_gem_object_init(dev, &gbo->bo.base, size); - if (ret) + if (ret) { + kfree(gbo); return ret; + } acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); @@ -196,13 +204,13 @@ static int drm_gem_vram_init(struct drm_device *dev, &gbo->placement, pg_align, false, acc_size, NULL, NULL, ttm_buffer_object_destroy); if (ret) - goto err_drm_gem_object_release; + /* + * A failing ttm_bo_init will call ttm_buffer_object_destroy + * to release gbo->bo.base and kfree gbo. + */ + return ret; return 0; - -err_drm_gem_object_release: - drm_gem_object_release(&gbo->bo.base); - return ret; } /** @@ -236,13 +244,9 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, ret = drm_gem_vram_init(dev, gbo, size, pg_align); if (ret < 0) - goto err_kfree; + return ERR_PTR(ret); return gbo; - -err_kfree: - kfree(gbo); - return ERR_PTR(ret); } EXPORT_SYMBOL(drm_gem_vram_create); -- GitLab From 0f7071c2d468b703dcc9e99cc403eb7dd4ec32ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 8 Sep 2020 17:02:07 +0300 Subject: [PATCH 1080/1494] drm/i915: Kill unused savePCH_PORT_HOTPLUG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't save/restore PCH_PORT_HOTPLUG so no point in reseving space for the value. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200908140210.31048-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ef75acda9bff6..c5acbba30e356 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -543,7 +543,6 @@ struct i915_suspend_saved_registers { u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF3[3]; - u32 savePCH_PORT_HOTPLUG; u16 saveGCDGMBUS; }; -- GitLab From e8fac46c783a444dd0d140bb84eae3247dfebb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 8 Sep 2020 17:02:08 +0300 Subject: [PATCH 1081/1494] drm/i915: Nuke the magic FBC_CONTROL save/restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FBC_CONTROL save restore is there just to preserve the compression interval setting. Since commit a68ce21ba0c4 ("drm/i915/fbc: Store the fbc1 compression interval in the params") we've been explicitly setting the interval to a specific value, so the sace/restore is now entirely pointless. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200908140210.31048-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_suspend.c | 8 -------- 2 files changed, 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c5acbba30e356..312974d1ffab6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -537,7 +537,6 @@ struct intel_gmbus { struct i915_suspend_saved_registers { u32 saveDSPARB; - u32 saveFBC_CONTROL; u32 saveCACHE_MODE_0; u32 saveMI_ARB_STATE; u32 saveSWF0[16]; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 09026c4db7d05..33ee3796c8497 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -40,10 +40,6 @@ static void i915_save_display(struct drm_i915_private *dev_priv) if (INTEL_GEN(dev_priv) <= 4) dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); - /* save FBC interval */ - if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) - dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); - if (IS_GEN(dev_priv, 4)) pci_read_config_word(pdev, GCDGMBUS, &dev_priv->regfile.saveGCDGMBUS); @@ -64,10 +60,6 @@ static void i915_restore_display(struct drm_i915_private *dev_priv) /* only restore FBC info on the platform that supports FBC*/ intel_fbc_global_disable(dev_priv); - /* restore FBC interval */ - if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) - I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); - intel_vga_redisable(dev_priv); intel_gmbus_reset(dev_priv); -- GitLab From b41e58ffe49172eb260e95c217d3e1f0f7432ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 8 Sep 2020 17:02:09 +0300 Subject: [PATCH 1082/1494] drm/i915: Nuke MI_ARB_STATE save/restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally added in commit 1f84e550a870 ("drm/i915 more registers for S3 (DSPCLK_GATE_D, CACHE_MODE_0, MI_ARB_STATE)") to fix some underruns. I suspect that was due to the trickle feed settings getting clobbered during suspend. We've been disabling trickle feed explicitly since commit 20f949670f51 ("drm/i915: Disable trickle feed via MI_ARB_STATE for the gen4") so this magic save/restore should no longer be needed. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200908140210.31048-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_suspend.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 312974d1ffab6..3b5166bb8b268 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -538,7 +538,6 @@ struct intel_gmbus { struct i915_suspend_saved_registers { u32 saveDSPARB; u32 saveCACHE_MODE_0; - u32 saveMI_ARB_STATE; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF3[3]; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 33ee3796c8497..80d9d2747640a 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -75,9 +75,6 @@ int i915_save_state(struct drm_i915_private *dev_priv) if (INTEL_GEN(dev_priv) < 7) dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); - /* Memory Arbitration state */ - dev_priv->regfile.saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); - /* Scratch space */ if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { @@ -112,9 +109,6 @@ int i915_restore_state(struct drm_i915_private *dev_priv) I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | 0xffff0000); - /* Memory arbitration state */ - I915_WRITE(MI_ARB_STATE, dev_priv->regfile.saveMI_ARB_STATE | 0xffff0000); - /* Scratch space */ if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { -- GitLab From 8dec2fc11b8cdad7d2b5679ebf0b742d511eacae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 8 Sep 2020 17:02:10 +0300 Subject: [PATCH 1083/1494] drm/i915: Nuke CACHE_MODE_0 save/restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CACHE_MODE_0 save/restore was added without explanation in commit 1f84e550a870 ("drm/i915 more registers for S3 (DSPCLK_GATE_D, CACHE_MODE_0, MI_ARB_STATE)"). If there are any bits we care about those should be set explicitly during some appropriate init function. Let's assume it's all good and just nuke this magic save/restore. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200908140210.31048-4-ville.syrjala@linux.intel.com Acked-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_suspend.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3b5166bb8b268..151f11f14b063 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -537,7 +537,6 @@ struct intel_gmbus { struct i915_suspend_saved_registers { u32 saveDSPARB; - u32 saveCACHE_MODE_0; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF3[3]; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 80d9d2747640a..7b64e71372700 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -71,10 +71,6 @@ int i915_save_state(struct drm_i915_private *dev_priv) i915_save_display(dev_priv); - /* Cache mode state */ - if (INTEL_GEN(dev_priv) < 7) - dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); - /* Scratch space */ if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { @@ -104,11 +100,6 @@ int i915_restore_state(struct drm_i915_private *dev_priv) i915_restore_display(dev_priv); - /* Cache mode state */ - if (INTEL_GEN(dev_priv) < 7) - I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 | - 0xffff0000); - /* Scratch space */ if (IS_GEN(dev_priv, 2) && IS_MOBILE(dev_priv)) { for (i = 0; i < 7; i++) { -- GitLab From 23d3e3799fb031f5eff5855c3df8e58e3a40001b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Thu, 6 Feb 2020 22:12:03 +0200 Subject: [PATCH 1084/1494] drm/i915: Fix g4x+ sprite dotclock limit for upscaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even if we're not doing downscaling we should account for some of the extra dotclock limitations for g4x+ sprites. In particular we must never exceed the 90% rule, and with RGB that limits actually drops to 80%. So instead of bailing out when upscaling let's clamp the scaling factor appropriately and go through the rest of calculation normally. By luck we already did the full calculations for the 1:1 case. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200206201204.31704-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/display/intel_sprite.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 5ac0dbf0e03d7..dcc26fdce5d1c 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1626,8 +1626,7 @@ static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, hscale = drm_rect_calc_hscale(&plane_state->uapi.src, &plane_state->uapi.dst, 0, INT_MAX); - if (hscale < 0x10000) - return pixel_rate; + hscale = max(hscale, 0x10000u); /* Decimation steps at 2x,4x,8x,16x */ decimate = ilog2(hscale >> 16); -- GitLab From 4de962300b883cc4aaafd7b625cbd497a299e6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Thu, 6 Feb 2020 22:12:04 +0200 Subject: [PATCH 1085/1494] drm/i915: Use fb->format->is_yuv for the g4x+ sprite RGB vs. YUV check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit g4x+ sprites have an extra cdclk limitation listed for RGB formats. For some random reason I chose to use cpp>=4 as the check for that. While that does actually work let's deobfuscate it by checking for !is_yuv instead. I suspect is_yuv didn't exist way back when I originally write the code. Also drop the duplicate comment. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200206201204.31704-2-ville.syrjala@linux.intel.com Acked-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/display/intel_sprite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index dcc26fdce5d1c..63040cb0d4e10 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -1639,8 +1639,8 @@ static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state, limit -= decimate; /* -10% for RGB */ - if (fb->format->cpp[0] >= 4) - limit--; /* -10% for RGB */ + if (!fb->format->is_yuv) + limit--; /* * We should also do -10% if sprite scaling is enabled -- GitLab From 09e872d558ba6a7f4468c4e8cdf0cd5a99bfc175 Mon Sep 17 00:00:00 2001 From: chunhui dai <chunhui.dai@mediatek.com> Date: Fri, 4 Sep 2020 12:59:59 +0200 Subject: [PATCH 1086/1494] drm/mediatek: Disable tmds on mt2701 Without that patch if you use specific resolutions like 1280x1024, I can see distortion in the output. It seems as if the frequency for updating the pixel of the image is out of sync. For initialization tmds needs to be active, but can be disabled after init to fix blurry display Signed-off-by: chunhui dai <chunhui.dai@mediatek.com> Signed-off-by: Frank Wunderlich <frank-w@public-files.de> Tested-by: Frank Wunderlich <frank-w@public-files.de> Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org> --- drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c | 1 + drivers/phy/mediatek/phy-mtk-hdmi.c | 3 +++ drivers/phy/mediatek/phy-mtk-hdmi.h | 1 + 3 files changed, 5 insertions(+) diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c index a6cb1dea3d0ce..b74c65a1762c7 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt2701.c @@ -238,6 +238,7 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy) struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = { .flags = CLK_SET_RATE_GATE, + .pll_default_off = true, .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops, .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds, .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds, diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c index 8fc83f01a7206..47c029d4b270b 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c @@ -184,6 +184,9 @@ static int mtk_hdmi_phy_probe(struct platform_device *pdev) return PTR_ERR(phy_provider); } + if (hdmi_phy->conf->pll_default_off) + hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy); + return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, hdmi_phy->pll); } diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.h b/drivers/phy/mediatek/phy-mtk-hdmi.h index b13e1d5f8e785..dcf9bb13699b3 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.h +++ b/drivers/phy/mediatek/phy-mtk-hdmi.h @@ -21,6 +21,7 @@ struct mtk_hdmi_phy; struct mtk_hdmi_phy_conf { unsigned long flags; + bool pll_default_off; const struct clk_ops *hdmi_phy_clk_ops; void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy); void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy); -- GitLab From 5c8d1244c03e1e57bad56907d42b5afe79054318 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi <rodrigo.vivi@intel.com> Date: Mon, 14 Sep 2020 15:03:18 -0400 Subject: [PATCH 1087/1494] drm/i915: Update DRIVER_DATE to 20200914 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 151f11f14b063..19fd9aaa8cf1c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -108,8 +108,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20200824" -#define DRIVER_TIMESTAMP 1598293597 +#define DRIVER_DATE "20200914" +#define DRIVER_TIMESTAMP 1600110197 struct drm_i915_gem_object; -- GitLab From ac03de1f5e8380a8f16728407619d9e5a4a351b0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi <rodrigo.vivi@intel.com> Date: Mon, 14 Sep 2020 15:34:23 -0400 Subject: [PATCH 1088/1494] drm/i915: Update DRIVER_DATE to 20200914 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 19fd9aaa8cf1c..61d7a6114628d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -109,7 +109,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" #define DRIVER_DATE "20200914" -#define DRIVER_TIMESTAMP 1600110197 +#define DRIVER_TIMESTAMP 1600112063 struct drm_i915_gem_object; -- GitLab From 4b31a9c77bf87f9d9e957f7a42f84c57a407e1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Mon, 7 Sep 2020 15:00:24 +0300 Subject: [PATCH 1089/1494] drm/atomic-helper: Extract drm_atomic_helper_calc_timestamping_constants() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put the vblank timestamping constants update loop into its own function. It has no business living inside drm_atomic_helper_update_legacy_modeset_state() so we'll be wanting to move it out entirely. As a first step we'll still call it from drm_atomic_helper_update_legacy_modeset_state(). v2: Drop comment about 'legacy state' in the new function Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907120026.6360-1-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_atomic_helper.c | 21 ++++++++++++++++++++- include/drm/drm_atomic_helper.h | 3 +++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9e1ad493e6891..191d09ee4c7f9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1186,13 +1186,32 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, crtc->x = new_plane_state->src_x >> 16; crtc->y = new_plane_state->src_y >> 16; } + } + + drm_atomic_helper_calc_timestamping_constants(old_state); +} +EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); + +/** + * drm_atomic_helper_calc_timestamping_constants - update vblank timestamping constants + * @state: atomic state object + * + * Updates the timestamping constants used for precise vblank timestamps + * by calling drm_calc_timestamping_constants() for all enabled crtcs in @state. + */ +void drm_atomic_helper_calc_timestamping_constants(struct drm_atomic_state *state) +{ + struct drm_crtc_state *new_crtc_state; + struct drm_crtc *crtc; + int i; + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->enable) drm_calc_timestamping_constants(crtc, &new_crtc_state->adjusted_mode); } } -EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); +EXPORT_SYMBOL(drm_atomic_helper_calc_timestamping_constants); static void crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index b268180c97eb9..85df04c8e62f8 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -74,6 +74,9 @@ void drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, struct drm_atomic_state *old_state); +void +drm_atomic_helper_calc_timestamping_constants(struct drm_atomic_state *state); + void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, struct drm_atomic_state *state); void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, -- GitLab From 441959ebc9056326d80af2d06adf4b80e0288a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Mon, 7 Sep 2020 15:00:25 +0300 Subject: [PATCH 1090/1494] drm/atomic-helper: Remove the timestamping constant update from drm_atomic_helper_update_legacy_modeset_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The timestamping constants have nothing to do with any legacy state so should not be updated from drm_atomic_helper_update_legacy_modeset_state(). Let's make everyone call drm_atomic_helper_calc_timestamping_constants() directly instead of relying on drm_atomic_helper_update_legacy_modeset_state() to call it. @@ expression S; @@ - drm_atomic_helper_calc_timestamping_constants(S); @@ expression D, S; @@ drm_atomic_helper_update_legacy_modeset_state(D, S); + drm_atomic_helper_calc_timestamping_constants(S); v2: Update drm_crtc_vblank_helper_get_vblank_timestamp{,_internal}() docs (Daniel) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907120026.6360-2-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/drm_atomic_helper.c | 7 ++----- drivers/gpu/drm/drm_vblank.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/nouveau/dispnv50/disp.c | 1 + 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ec29376667df2..b24c14bfab31d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7496,6 +7496,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) bool mode_set_reset_required = false; drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_atomic_helper_calc_timestamping_constants(state); dm_state = dm_atomic_get_new_state(state); if (dm_state && dm_state->context) { diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 191d09ee4c7f9..f9170b4b22e7e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1115,9 +1115,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) * @old_state: atomic state object with old state structures * * This function updates all the various legacy modeset state pointers in - * connectors, encoders and CRTCs. It also updates the timestamping constants - * used for precise vblank timestamps by calling - * drm_calc_timestamping_constants(). + * connectors, encoders and CRTCs. * * Drivers can use this for building their own atomic commit if they don't have * a pure helper-based modeset implementation. @@ -1187,8 +1185,6 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev, crtc->y = new_plane_state->src_y >> 16; } } - - drm_atomic_helper_calc_timestamping_constants(old_state); } EXPORT_SYMBOL(drm_atomic_helper_update_legacy_modeset_state); @@ -1295,6 +1291,7 @@ void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev, disable_outputs(dev, old_state); drm_atomic_helper_update_legacy_modeset_state(dev, old_state); + drm_atomic_helper_calc_timestamping_constants(old_state); crtc_set_mode(dev, old_state); } diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index b18e1efbbae1a..f135b79593dd2 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -674,7 +674,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * * Note that atomic drivers must call drm_calc_timestamping_constants() before * enabling a CRTC. The atomic helpers already take care of that in - * drm_atomic_helper_update_legacy_modeset_state(). + * drm_atomic_helper_calc_timestamping_constants(). * * Returns: * @@ -819,7 +819,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal); * * Note that atomic drivers must call drm_calc_timestamping_constants() before * enabling a CRTC. The atomic helpers already take care of that in - * drm_atomic_helper_update_legacy_modeset_state(). + * drm_atomic_helper_calc_timestamping_constants(). * * Returns: * diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ddb588f863f8c..c0f01bdd60377 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -15577,6 +15577,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) if (state->modeset) { drm_atomic_helper_update_legacy_modeset_state(dev, &state->base); + drm_atomic_helper_calc_timestamping_constants(&state->base); intel_set_cdclk_pre_plane_update(state); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 852e1b56f3a7c..b111fe24a06bd 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -2069,6 +2069,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_wait_for_fences(dev, state, false); drm_atomic_helper_wait_for_dependencies(state); drm_atomic_helper_update_legacy_modeset_state(dev, state); + drm_atomic_helper_calc_timestamping_constants(state); if (atom->lock_core) mutex_lock(&disp->mutex); -- GitLab From 79628c543e152502b0ee9c9fe5f6b56879e49c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Mon, 7 Sep 2020 15:00:26 +0300 Subject: [PATCH 1091/1494] drm/i915: Drop the drm_atomic_helper_calc_timestamping_constants() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We update the timestamping constants per-crtc explicitly in intel_crtc_update_active_timings(). Furtermore the helper will use uapi.adjusted_mode whereas we want hw.adjusted_mode. Thus let's drop the helper call an rely on what we already have in intel_crtc_update_active_timings(). We can now also drop the hw.adjusted_mode -> uapi.adjusted_mode copy hack that was added to keep the helper from deriving the timestamping constants from the wrong thing. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200907120026.6360-3-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_display.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c0f01bdd60377..345eceec24fe7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -13471,12 +13471,6 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config) "hw max bpp: %i, pipe bpp: %i, dithering: %i\n", base_bpp, pipe_config->pipe_bpp, pipe_config->dither); - /* - * Make drm_calc_timestamping_constants in - * drm_atomic_helper_update_legacy_modeset_state() happy - */ - pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode; - return 0; } @@ -15577,7 +15571,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) if (state->modeset) { drm_atomic_helper_update_legacy_modeset_state(dev, &state->base); - drm_atomic_helper_calc_timestamping_constants(&state->base); intel_set_cdclk_pre_plane_update(state); -- GitLab From 37054fc81443cc6a8c3a38395f384412b8373d82 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Sat, 12 Sep 2020 21:56:39 +0200 Subject: [PATCH 1092/1494] gpu/drm: ingenic: Add option to mmap GEM buffers cached Ingenic SoCs are most notably used in cheap chinese handheld gaming consoles. There, the games and applications generally render in software directly into GEM buffers. Traditionally, GEM buffers are mapped write-combine. Writes to the buffer are accelerated, and reads are slow. Application doing lots of alpha-blending paint inside shadow buffers, which is then memcpy'd into the final GEM buffer. On recent Ingenic SoCs however, it is much faster to have a fully cached GEM buffer, in which applications paint directly, and whose data is invalidated before scanout, than having a write-combine GEM buffer, even when alpha blending is not used. Add an optional 'cached_gem_buffers' parameter to the ingenic-drm driver to allow GEM buffers to be mapped fully-cached, in order to speed up software rendering. v2: Use standard noncoherent DMA APIs v3: Use damage clips instead of invalidating full frames v4: Avoid dma_pgprot() which is not exported. Using vm_get_page_prot() is enough in this case. v5: - Avoid calling drm_gem_cma_prime_mmap(). It has the side effect that an extra object reference is obtained, which causes our dumb buffers to never be freed. It should have been drm_gem_cma_mmap_obj(). However, our custom mmap function only differs with one flag, so we can cleanly handle both modes in ingenic_drm_gem_mmap(). - Call drm_gem_vm_close() if drm_mmap_attrs() failed, just like in drm_gem_cma_mmap_obj(). Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200912195639.176001-1-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 114 +++++++++++++++++++++- drivers/gpu/drm/ingenic/ingenic-drm.h | 4 + drivers/gpu/drm/ingenic/ingenic-ipu.c | 12 ++- 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a3d1617d7c67e..937d080f5d06a 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -9,6 +9,8 @@ #include <linux/component.h> #include <linux/clk.h> #include <linux/dma-mapping.h> +#include <linux/dma-noncoherent.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -19,6 +21,7 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h> @@ -76,6 +79,11 @@ static const u32 ingenic_drm_primary_formats[] = { DRM_FORMAT_XRGB8888, }; +static bool ingenic_drm_cached_gem_buf; +module_param_named(cached_gem_buffers, ingenic_drm_cached_gem_buf, bool, 0400); +MODULE_PARM_DESC(cached_gem_buffers, + "Enable fully cached GEM buffers [default=false]"); + static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -338,6 +346,8 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, plane->state->fb->format->format != state->fb->format->format)) crtc_state->mode_changed = true; + drm_atomic_helper_check_plane_damage(state->state, state); + return 0; } @@ -440,6 +450,38 @@ void ingenic_drm_plane_config(struct device *dev, } } +void ingenic_drm_sync_data(struct device *dev, + struct drm_plane_state *old_state, + struct drm_plane_state *state) +{ + const struct drm_format_info *finfo = state->fb->format; + struct ingenic_drm *priv = dev_get_drvdata(dev); + struct drm_atomic_helper_damage_iter iter; + unsigned int offset, i; + struct drm_rect clip; + dma_addr_t paddr; + void *addr; + + if (!ingenic_drm_cached_gem_buf) + return; + + drm_atomic_helper_damage_iter_init(&iter, old_state, state); + + drm_atomic_for_each_plane_damage(&iter, &clip) { + for (i = 0; i < finfo->num_planes; i++) { + paddr = drm_fb_cma_get_gem_addr(state->fb, state, i); + addr = phys_to_virt(paddr); + + /* Ignore x1/x2 values, invalidate complete lines */ + offset = clip.y1 * state->fb->pitches[i]; + + dma_cache_sync(priv->dev, addr + offset, + (clip.y2 - clip.y1) * state->fb->pitches[i], + DMA_TO_DEVICE); + } + } +} + static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *oldstate) { @@ -450,6 +492,8 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, dma_addr_t addr; if (state && state->fb) { + ingenic_drm_sync_data(priv->dev, oldstate, state); + addr = drm_fb_cma_get_gem_addr(state->fb, state, 0); width = state->src_w >> 16; height = state->src_h >> 16; @@ -605,7 +649,69 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0); } -DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); +static struct drm_framebuffer * +ingenic_drm_gem_fb_create(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + if (ingenic_drm_cached_gem_buf) + return drm_gem_fb_create_with_dirty(dev, file, mode_cmd); + + return drm_gem_fb_create(dev, file, mode_cmd); +} + +static int ingenic_drm_gem_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma) +{ + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); + struct device *dev = cma_obj->base.dev->dev; + unsigned long attrs; + int ret; + + if (ingenic_drm_cached_gem_buf) + attrs = DMA_ATTR_NON_CONSISTENT; + else + attrs = DMA_ATTR_WRITE_COMBINE; + + /* + * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the + * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map + * the whole buffer. + */ + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_pgoff = 0; + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + + ret = dma_mmap_attrs(dev, vma, cma_obj->vaddr, cma_obj->paddr, + vma->vm_end - vma->vm_start, attrs); + if (ret) + drm_gem_vm_close(vma); + + return ret; +} + +static int ingenic_drm_gem_cma_mmap(struct file *filp, + struct vm_area_struct *vma) +{ + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + return ingenic_drm_gem_mmap(vma->vm_private_data, vma); +} + +static const struct file_operations ingenic_drm_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, + .mmap = ingenic_drm_gem_cma_mmap, +}; static struct drm_driver ingenic_drm_driver_data = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, @@ -669,7 +775,7 @@ static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = }; static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = { - .fb_create = drm_gem_fb_create, + .fb_create = ingenic_drm_gem_fb_create, .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, @@ -796,6 +902,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } + drm_plane_enable_fb_damage_clips(&priv->f1); + drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1, @@ -821,6 +929,8 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } + drm_plane_enable_fb_damage_clips(&priv->f0); + if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) { ret = component_bind_all(dev, drm); if (ret) { diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.h b/drivers/gpu/drm/ingenic/ingenic-drm.h index 43f7d959cff7e..df99f0f75d393 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm.h +++ b/drivers/gpu/drm/ingenic/ingenic-drm.h @@ -168,6 +168,10 @@ void ingenic_drm_plane_config(struct device *dev, struct drm_plane *plane, u32 fourcc); void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane); +void ingenic_drm_sync_data(struct device *dev, + struct drm_plane_state *old_state, + struct drm_plane_state *state); + extern struct platform_driver *ingenic_ipu_driver_ptr; #endif /* DRIVERS_GPU_DRM_INGENIC_INGENIC_DRM_H */ diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index fc8c6e970ee31..38c83e8cc6a54 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -20,6 +20,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> @@ -316,6 +317,8 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, JZ_IPU_CTRL_CHIP_EN | JZ_IPU_CTRL_LCDC_SEL); } + ingenic_drm_sync_data(ipu->master, oldstate, state); + /* New addresses will be committed in vblank handler... */ ipu->addr_y = drm_fb_cma_get_gem_addr(state->fb, state, 0); if (finfo->num_planes > 1) @@ -534,7 +537,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, if (!state->crtc || !crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay) - return 0; + goto out_check_damage; /* Plane must be fully visible */ if (state->crtc_x < 0 || state->crtc_y < 0 || @@ -551,7 +554,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, return -EINVAL; if (!osd_changed(state, plane->state)) - return 0; + goto out_check_damage; crtc_state->mode_changed = true; @@ -578,6 +581,9 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, ipu->denom_w = denom_w; ipu->denom_h = denom_h; +out_check_damage: + drm_atomic_helper_check_plane_damage(state->state, state); + return 0; } @@ -759,6 +765,8 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d) return err; } + drm_plane_enable_fb_damage_clips(plane); + /* * Sharpness settings range is [0,32] * 0 : nearest-neighbor -- GitLab From d6005d3dde75f7e4f21822c12446553dd7a69bb2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 8 Sep 2020 09:07:21 +0200 Subject: [PATCH 1093/1494] drm/virtio: use drmm_mode_config_init Use managed init call to simplify cleanup. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200908070723.6394-2-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 11 +++++++---- drivers/gpu/drm/virtio/virtgpu_drv.h | 2 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 6 +++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index effea07abe62d..f84b7e61311bc 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -325,11 +325,14 @@ static const struct drm_mode_config_funcs virtio_gpu_mode_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) +int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) { - int i; + int i, ret; + + ret = drmm_mode_config_init(vgdev->ddev); + if (ret) + return ret; - drm_mode_config_init(vgdev->ddev); vgdev->ddev->mode_config.quirk_addfb_prefer_host_byte_order = true; vgdev->ddev->mode_config.funcs = &virtio_gpu_mode_funcs; @@ -343,6 +346,7 @@ void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) vgdev_output_init(vgdev, i); drm_mode_config_reset(vgdev->ddev); + return 0; } void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) @@ -351,5 +355,4 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) for (i = 0 ; i < vgdev->num_scanouts; ++i) kfree(vgdev->outputs[i].edid); - drm_mode_config_cleanup(vgdev->ddev); } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index a52b7a39f286e..55c34b4fc3e99 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -352,7 +352,7 @@ virtio_gpu_cmd_resource_assign_uuid(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_array *objs); /* virtgpu_display.c */ -void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); +int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev); /* virtgpu_plane.c */ diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 06af537b0091d..eed57a9313098 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -186,7 +186,11 @@ int virtio_gpu_init(struct drm_device *dev) num_capsets, &num_capsets); DRM_INFO("number of cap sets: %d\n", num_capsets); - virtio_gpu_modeset_init(vgdev); + ret = virtio_gpu_modeset_init(vgdev); + if (ret) { + DRM_ERROR("modeset init failed\n"); + goto err_scanouts; + } virtio_device_ready(vgdev->vdev); -- GitLab From b7170f9457f282783b6f3843e2b30d619449837c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 8 Sep 2020 09:07:22 +0200 Subject: [PATCH 1094/1494] drm/virtio: return virtio_gpu_queue errors In case queuing virtio commands fails (can happen when the device got unplugged) pass up the error. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200908070723.6394-3-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_vq.c | 38 +++++++++++++++-------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 7436705ba5a22..d0f7f494c610b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -320,13 +320,13 @@ static struct sg_table *vmalloc_to_sgt(char *data, uint32_t size, int *sg_ents) return sgt; } -static void virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, - struct virtio_gpu_vbuffer *vbuf, - struct virtio_gpu_fence *fence, - int elemcnt, - struct scatterlist **sgs, - int outcnt, - int incnt) +static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf, + struct virtio_gpu_fence *fence, + int elemcnt, + struct scatterlist **sgs, + int outcnt, + int incnt) { struct virtqueue *vq = vgdev->ctrlq.vq; int ret, idx; @@ -335,7 +335,7 @@ static void virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, if (fence && vbuf->objs) virtio_gpu_array_unlock_resv(vbuf->objs); free_vbuf(vgdev, vbuf); - return; + return -1; } if (vgdev->has_indirect) @@ -373,15 +373,16 @@ static void virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, spin_unlock(&vgdev->ctrlq.qlock); drm_dev_exit(idx); + return 0; } -static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, - struct virtio_gpu_vbuffer *vbuf, - struct virtio_gpu_fence *fence) +static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf, + struct virtio_gpu_fence *fence) { struct scatterlist *sgs[3], vcmd, vout, vresp; struct sg_table *sgt = NULL; - int elemcnt = 0, outcnt = 0, incnt = 0; + int elemcnt = 0, outcnt = 0, incnt = 0, ret; /* set up vcmd */ sg_init_one(&vcmd, vbuf->buf, vbuf->size); @@ -398,7 +399,7 @@ static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, if (!sgt) { if (fence && vbuf->objs) virtio_gpu_array_unlock_resv(vbuf->objs); - return; + return -1; } elemcnt += sg_ents; @@ -419,13 +420,14 @@ static void virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, incnt++; } - virtio_gpu_queue_ctrl_sgs(vgdev, vbuf, fence, elemcnt, sgs, outcnt, - incnt); + ret = virtio_gpu_queue_ctrl_sgs(vgdev, vbuf, fence, elemcnt, sgs, outcnt, + incnt); if (sgt) { sg_free_table(sgt); kfree(sgt); } + return ret; } void virtio_gpu_notify(struct virtio_gpu_device *vgdev) @@ -444,10 +446,10 @@ void virtio_gpu_notify(struct virtio_gpu_device *vgdev) virtqueue_notify(vgdev->ctrlq.vq); } -static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev, - struct virtio_gpu_vbuffer *vbuf) +static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) { - virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, NULL); + return virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, NULL); } static void virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev, -- GitLab From 9fe6bda9823ea90c22ad47436293413d5fd58991 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 8 Sep 2020 09:07:23 +0200 Subject: [PATCH 1095/1494] drm/virtio: add virtio_gpu_cmd_unref_resource error handling Usually we wait for the host to complete the unref request, then cleanup the guest-side state of the object in the completion callback. When submitting the unref command failed the completion callback will not be called though, so cleanup right away. Fixes a WARN on stale mm entries on driver shutdown. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/20200908070723.6394-4-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_vq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index d0f7f494c610b..a7550044b8b2e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -536,6 +536,7 @@ void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev, { struct virtio_gpu_resource_unref *cmd_p; struct virtio_gpu_vbuffer *vbuf; + int ret; cmd_p = virtio_gpu_alloc_cmd_cb(vgdev, &vbuf, sizeof(*cmd_p), virtio_gpu_cmd_unref_cb); @@ -545,7 +546,9 @@ void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev, cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); vbuf->resp_cb_data = bo; - virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + ret = virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + if (ret < 0) + virtio_gpu_cleanup_object(bo); } void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev, -- GitLab From da27bd41d0ebcc21bff308236bbf5595ce85b67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Thu, 10 Sep 2020 00:38:23 +0300 Subject: [PATCH 1096/1494] drm/i915: Reduce INTEL_DISPLAY_ENABLED to just removing the outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having a mode where the display hardware is present but we try to pretend it isn't just leads to massive headaches when trying to reason what the fallout might be from skipping some random bits of programming. Let's just neuter INTEL_DISPLAY_ENABLED so that we treat the hardware as fully present, except we just don't register any outputs. That's still rather sketchy if the outputs are already enabled when the driver is loaded. I think the simplest solution would be to probe everything as normal and just return disconnected" from all .detect() hooks. That would avoid anything automagically enabling those outputs, but the driver could then shut things down using the normal codepaths. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200909213824.12390-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/display/intel_bios.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_fbdev.c | 3 +-- drivers/gpu/drm/i915/display/intel_gmbus.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index a0a41ec5c3419..c110cd9e8a73c 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2133,7 +2133,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv) INIT_LIST_HEAD(&dev_priv->vbt.display_devices); - if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) { + if (!HAS_DISPLAY(dev_priv)) { drm_dbg_kms(&dev_priv->drm, "Skipping VBT init due to disabled display.\n"); return; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ec148a8da2c29..bacaf713eed4a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -17882,7 +17882,7 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) if (i915_inject_probe_failure(i915)) return -ENODEV; - if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) { + if (HAS_DISPLAY(i915)) { ret = drm_vblank_init(&i915->drm, INTEL_NUM_PIPES(i915)); if (ret) @@ -17956,7 +17956,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915) INTEL_NUM_PIPES(i915), INTEL_NUM_PIPES(i915) > 1 ? "s" : ""); - if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) { + if (HAS_DISPLAY(i915)) { for_each_pipe(i915, pipe) { ret = intel_crtc_init(i915, pipe); if (ret) { @@ -18045,7 +18045,7 @@ int intel_modeset_init(struct drm_i915_private *i915) intel_overlay_setup(i915); - if (!HAS_DISPLAY(i915) || !INTEL_DISPLAY_ENABLED(i915)) + if (!HAS_DISPLAY(i915)) return 0; ret = intel_fbdev_init(&i915->drm); @@ -19018,7 +19018,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv) BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder)); - if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) + if (!HAS_DISPLAY(dev_priv)) return NULL; error = kzalloc(sizeof(*error), GFP_ATOMIC); diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index bd39eb6a21b8b..842c04e632147 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -451,8 +451,7 @@ int intel_fbdev_init(struct drm_device *dev) struct intel_fbdev *ifbdev; int ret; - if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv) || - !INTEL_DISPLAY_ENABLED(dev_priv))) + if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv))) return -ENODEV; ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index a8d119b6b45c8..e6b8d6dfb598e 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -834,7 +834,7 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) unsigned int pin; int ret; - if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) + if (!HAS_DISPLAY(dev_priv)) return 0; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 94e00e4506834..acc32066cec35 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -677,7 +677,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) drm_err(&dev_priv->drm, "Failed to register driver for userspace access!\n"); - if (HAS_DISPLAY(dev_priv) && INTEL_DISPLAY_ENABLED(dev_priv)) { + if (HAS_DISPLAY(dev_priv)) { /* Must be done after probing outputs */ intel_opregion_register(dev_priv); acpi_video_register(); @@ -700,7 +700,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv) * We need to coordinate the hotplugs with the asynchronous fbdev * configuration, for which we use the fbdev->async_cookie. */ - if (HAS_DISPLAY(dev_priv) && INTEL_DISPLAY_ENABLED(dev_priv)) + if (HAS_DISPLAY(dev_priv)) drm_kms_helper_poll_init(dev); intel_power_domains_enable(dev_priv); -- GitLab From b81dddb909b4fa4498d96b2bf7748ae1e86e5e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Thu, 10 Sep 2020 19:42:56 +0300 Subject: [PATCH 1097/1494] drm/i915: Reduce INTEL_DISPLAY_ENABLED to just treat outputs as disconnected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the display hardware is all there even when INTEL_DISPLAY_ENABLED return false we have to be capable of shutting it down cleanly so as to not anger the hw. To that end let's reduce the effect of !INTEL_DISPLAY_ENABLE to just treating all outputs as disconnected. Should prevent anyone from automagically enabling any of them, while still allowing us to cleanly shut them down. v2: Put the check into the right place for CRT Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200910164256.25983-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula <jani.nikula@intel.com> --- drivers/gpu/drm/i915/display/icl_dsi.c | 1 + drivers/gpu/drm/i915/display/intel_crt.c | 3 +++ drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 3 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 4 ++++ drivers/gpu/drm/i915/display/intel_dvo.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +++ drivers/gpu/drm/i915/display/intel_lvds.c | 8 +------- drivers/gpu/drm/i915/display/intel_panel.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_panel.h | 2 ++ drivers/gpu/drm/i915/display/intel_sdvo.c | 6 +++++- drivers/gpu/drm/i915/display/intel_tv.c | 3 +++ drivers/gpu/drm/i915/display/vlv_dsi.c | 1 + 13 files changed, 44 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index f4053dd6bde90..520715b7d5b55 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1646,6 +1646,7 @@ static const struct drm_encoder_funcs gen11_dsi_encoder_funcs = { }; static const struct drm_connector_funcs gen11_dsi_connector_funcs = { + .detect = intel_panel_detect, .late_register = intel_connector_register, .early_unregister = intel_connector_unregister, .destroy = intel_connector_destroy, diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 5b4510ce56935..4934edd51cb0b 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -833,6 +833,9 @@ intel_crt_detect(struct drm_connector *connector, connector->base.id, connector->name, force); + if (!INTEL_DISPLAY_ENABLED(dev_priv)) + return connector_status_disconnected; + if (dev_priv->params.load_detect_test) { wakeref = intel_display_power_get(dev_priv, intel_encoder->power_domain); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index bacaf713eed4a..5611a3d955940 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -16893,7 +16893,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv) intel_pps_init(dev_priv); - if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv)) + if (!HAS_DISPLAY(dev_priv)) return; if (IS_ROCKETLAKE(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8a673d0d70515..1a8185f8fb8ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6103,6 +6103,9 @@ intel_dp_detect(struct drm_connector *connector, drm_WARN_ON(&dev_priv->drm, !drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); + if (!INTEL_DISPLAY_ENABLED(dev_priv)) + return connector_status_disconnected; + /* Can't disconnect eDP */ if (intel_dp_is_edp(intel_dp)) status = edp_detect(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index b6424bf5d544d..64d885539e94a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -719,9 +719,13 @@ static int intel_dp_mst_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force) { + struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; + if (!INTEL_DISPLAY_ENABLED(i915)) + return connector_status_disconnected; + if (drm_connector_is_unregistered(connector)) return connector_status_disconnected; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 307ed8ae9a19f..237dbb1ba0eeb 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -313,9 +313,15 @@ static void intel_dvo_pre_enable(struct intel_atomic_state *state, static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector, bool force) { + struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_dvo *intel_dvo = intel_attached_dvo(to_intel_connector(connector)); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + + if (!INTEL_DISPLAY_ENABLED(i915)) + return connector_status_disconnected; + return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev); } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 0978b0d8f4c67..04f59516d5f31 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2673,6 +2673,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + if (!INTEL_DISPLAY_ENABLED(dev_priv)) + return connector_status_disconnected; + wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); if (INTEL_GEN(dev_priv) >= 11 && diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 1888611244db7..e65c2de522c3c 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -456,12 +456,6 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, return 0; } -static enum drm_connector_status -intel_lvds_detect(struct drm_connector *connector, bool force) -{ - return connector_status_connected; -} - /* * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. */ @@ -490,7 +484,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs }; static const struct drm_connector_funcs intel_lvds_connector_funcs = { - .detect = intel_lvds_detect, + .detect = intel_panel_detect, .fill_modes = drm_helper_probe_single_connector_modes, .atomic_get_property = intel_digital_connector_atomic_get_property, .atomic_set_property = intel_digital_connector_atomic_set_property, diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 2eb1a3a93df19..9f23bac0d7924 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -2095,6 +2095,17 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel) } } +enum drm_connector_status +intel_panel_detect(struct drm_connector *connector, bool force) +{ + struct drm_i915_private *i915 = to_i915(connector->dev); + + if (!INTEL_DISPLAY_ENABLED(i915)) + return connector_status_disconnected; + + return connector_status_connected; +} + int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode, struct drm_display_mode *downclock_mode) diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 968b95281cb41..5b813fe90557c 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -23,6 +23,8 @@ int intel_panel_init(struct intel_panel *panel, struct drm_display_mode *fixed_mode, struct drm_display_mode *downclock_mode); void intel_panel_fini(struct intel_panel *panel); +enum drm_connector_status +intel_panel_detect(struct drm_connector *connector, bool force); void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, struct drm_display_mode *adjusted_mode); int intel_pch_panel_fitting(struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 5e9fb349c8292..4eaa4aa86ecdf 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2084,14 +2084,18 @@ intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector, bool force) { - u16 response; + struct drm_i915_private *i915 = to_i915(connector->dev); struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); enum drm_connector_status ret; + u16 response; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + if (!INTEL_DISPLAY_ENABLED(i915)) + return connector_status_disconnected; + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ATTACHED_DISPLAYS, &response, 2)) diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 777032d9697b5..7a7b99b015a50 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1706,6 +1706,9 @@ intel_tv_detect(struct drm_connector *connector, drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] force=%d\n", connector->base.id, connector->name, force); + if (!INTEL_DISPLAY_ENABLED(i915)) + return connector_status_disconnected; + if (force) { struct intel_load_detect_pipe tmp; int ret; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 052e0b31a2dad..5e5522923b1e4 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1585,6 +1585,7 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs }; static const struct drm_connector_funcs intel_dsi_connector_funcs = { + .detect = intel_panel_detect, .late_register = intel_connector_register, .early_unregister = intel_connector_unregister, .destroy = intel_connector_destroy, -- GitLab From 46f206304db0311b0920479f42accaa7cb472fdc Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Thu, 27 Aug 2020 10:59:11 +0200 Subject: [PATCH 1098/1494] drm/bridge: ps8640: Rework power state handling The get_edid() callback can be triggered anytime by an ioctl, i.e drm_mode_getconnector (ioctl) -> drm_helper_probe_single_connector_modes -> drm_bridge_connector_get_modes -> ps8640_bridge_get_edid Actually if the bridge pre_enable() function was not called before get_edid(), the driver will not be able to get the EDID properly and display will not work until a second get_edid() call is issued and if pre_enable() is called before. The side effect of this, for example, is that you see anything when `Frecon` starts, neither the splash screen, until the graphical session manager starts. To fix this we need to make sure that all we need is enabled before reading the EDID. This means the following: 1. If get_edid() is called before having the device powered we need to power on the device. In such case, the driver will power off again the device. 2. If get_edid() is called after having the device powered, all should just work. We added a powered flag in order to avoid recurrent calls to ps8640_bridge_poweron() and unneeded delays. 3. This seems to be specific for this device, but we need to make sure the panel is powered on before do a power on cycle on this device. Otherwise the device fails to retrieve the EDID. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Tested-by: Bilal Wasim <bwasim.lkml@gmail.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200827085911.944899-2-enric.balletbo@collabora.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 68 ++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 9f7b7a9c53c52..7bd0affa057a5 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -65,6 +65,7 @@ struct ps8640 { struct regulator_bulk_data supplies[2]; struct gpio_desc *gpio_reset; struct gpio_desc *gpio_powerdown; + bool powered; }; static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e) @@ -91,13 +92,15 @@ static int ps8640_bridge_vdo_control(struct ps8640 *ps_bridge, return 0; } -static void ps8640_pre_enable(struct drm_bridge *bridge) +static void ps8640_bridge_poweron(struct ps8640 *ps_bridge) { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); struct i2c_client *client = ps_bridge->page[PAGE2_TOP_CNTL]; unsigned long timeout; int ret, status; + if (ps_bridge->powered) + return; + ret = regulator_bulk_enable(ARRAY_SIZE(ps_bridge->supplies), ps_bridge->supplies); if (ret < 0) { @@ -152,10 +155,6 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) goto err_regulators_disable; } - ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE); - if (ret) - goto err_regulators_disable; - /* Switch access edp panel's edid through i2c */ ret = i2c_smbus_write_byte_data(client, PAGE2_I2C_BYPASS, I2C_BYPASS_EN); @@ -164,6 +163,8 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) goto err_regulators_disable; } + ps_bridge->powered = true; + return; err_regulators_disable: @@ -171,12 +172,12 @@ static void ps8640_pre_enable(struct drm_bridge *bridge) ps_bridge->supplies); } -static void ps8640_post_disable(struct drm_bridge *bridge) +static void ps8640_bridge_poweroff(struct ps8640 *ps_bridge) { - struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); int ret; - ps8640_bridge_vdo_control(ps_bridge, DISABLE); + if (!ps_bridge->powered) + return; gpiod_set_value(ps_bridge->gpio_reset, 1); gpiod_set_value(ps_bridge->gpio_powerdown, 1); @@ -184,6 +185,28 @@ static void ps8640_post_disable(struct drm_bridge *bridge) ps_bridge->supplies); if (ret < 0) DRM_ERROR("cannot disable regulators %d\n", ret); + + ps_bridge->powered = false; +} + +static void ps8640_pre_enable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + int ret; + + ps8640_bridge_poweron(ps_bridge); + + ret = ps8640_bridge_vdo_control(ps_bridge, ENABLE); + if (ret < 0) + ps8640_bridge_poweroff(ps_bridge); +} + +static void ps8640_post_disable(struct drm_bridge *bridge) +{ + struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + + ps8640_bridge_vdo_control(ps_bridge, DISABLE); + ps8640_bridge_poweroff(ps_bridge); } static int ps8640_bridge_attach(struct drm_bridge *bridge, @@ -249,9 +272,34 @@ static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge, struct drm_connector *connector) { struct ps8640 *ps_bridge = bridge_to_ps8640(bridge); + bool poweroff = !ps_bridge->powered; + struct edid *edid; + + /* + * When we end calling get_edid() triggered by an ioctl, i.e + * + * drm_mode_getconnector (ioctl) + * -> drm_helper_probe_single_connector_modes + * -> drm_bridge_connector_get_modes + * -> ps8640_bridge_get_edid + * + * We need to make sure that what we need is enabled before reading + * EDID, for this chip, we need to do a full poweron, otherwise it will + * fail. + */ + drm_bridge_chain_pre_enable(bridge); - return drm_get_edid(connector, + edid = drm_get_edid(connector, ps_bridge->page[PAGE0_DP_CNTL]->adapter); + + /* + * If we call the get_edid() function without having enabled the chip + * before, return the chip to its original power state. + */ + if (poweroff) + drm_bridge_chain_post_disable(bridge); + + return edid; } static const struct drm_bridge_funcs ps8640_bridge_funcs = { -- GitLab From 0fe438cec9e1d263a831e62a0499e14ee228fb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 11 Sep 2020 15:06:53 +0200 Subject: [PATCH 1099/1494] drm/ttm: remove default caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As far as I can tell this was never used either and we just always fallback to the order cached > wc > uncached anyway. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/390142/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 1 - drivers/gpu/drm/drm_gem_vram_helper.c | 3 +-- drivers/gpu/drm/nouveau/nouveau_ttm.c | 21 +++++++------------ drivers/gpu/drm/qxl/qxl_ttm.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 6 ++---- drivers/gpu/drm/ttm/ttm_bo.c | 3 --- drivers/gpu/drm/ttm/ttm_range_manager.c | 2 -- drivers/gpu/drm/ttm/ttm_resource.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 1 - include/drm/ttm/ttm_bo_driver.h | 2 -- include/drm/ttm/ttm_resource.h | 3 --- 15 files changed, 14 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 2b1b7c136343d..12d6a018e60b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -96,7 +96,6 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) man->use_tt = true; man->func = &amdgpu_gtt_mgr_func; man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; ttm_resource_manager_init(man, gtt_size >> PAGE_SHIFT); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 6fc3af082f6fd..15ce752b127c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -68,7 +68,7 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, uint64_t size) { return ttm_range_man_init(&adev->mman.bdev, type, - TTM_PL_FLAG_UNCACHED, TTM_PL_FLAG_UNCACHED, + TTM_PL_FLAG_UNCACHED, false, size >> PAGE_SHIFT); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index b2adc2abc5810..f809d84ccda20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -180,7 +180,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) int ret; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT); diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 4291f0b71021b..fff42bb56646b 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1058,8 +1058,7 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, ret = ttm_range_man_init(&vmm->bdev, TTM_PL_VRAM, TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, - TTM_PL_FLAG_WC, false, - vram_size >> PAGE_SHIFT); + false, vram_size >> PAGE_SHIFT); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index a62f37b1131ca..cf18f75cd0f1a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -203,12 +203,9 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) return -ENOMEM; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - if (type & NVIF_MEM_UNCACHED) { + if (type & NVIF_MEM_UNCACHED) man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; - } man->func = &nouveau_vram_manager; @@ -220,7 +217,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) } else { return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_VRAM, TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, - TTM_PL_FLAG_WC, false, + false, drm->gem.vram_available >> PAGE_SHIFT); } } @@ -245,16 +242,14 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) { struct ttm_resource_manager *man; unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; - unsigned available_caching, default_caching; const struct ttm_resource_manager_func *func = NULL; - if (drm->agp.bridge) { + unsigned available_caching; + + if (drm->agp.bridge) available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - default_caching = TTM_PL_FLAG_WC; - } else { + else available_caching = TTM_PL_MASK_CACHING; - default_caching = TTM_PL_FLAG_CACHED; - } if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) func = &nouveau_gart_manager; @@ -262,8 +257,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) func = &nv04_gart_manager; else return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, - available_caching, default_caching, - true, + available_caching, true, size_pages); man = kzalloc(sizeof(*man), GFP_KERNEL); @@ -272,7 +266,6 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) man->func = func; man->available_caching = available_caching; - man->default_caching = default_caching; man->use_tt = true; ttm_resource_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 5ffc8b752f01b..d39d7994ea349 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -203,7 +203,7 @@ static int qxl_ttm_init_mem_type(struct qxl_device *qdev, uint64_t size) { return ttm_range_man_init(&qdev->mman.bdev, type, TTM_PL_MASK_CACHING, - TTM_PL_FLAG_CACHED, false, size); + false, size); } int qxl_ttm_init(struct qxl_device *qdev) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 602a591a53dc7..b8e60b3630d7f 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -70,16 +70,14 @@ static int radeon_ttm_init_vram(struct radeon_device *rdev) { return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_VRAM, TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, - TTM_PL_FLAG_WC, false, - rdev->mc.real_vram_size >> PAGE_SHIFT); + false, rdev->mc.real_vram_size >> PAGE_SHIFT); } static int radeon_ttm_init_gtt(struct radeon_device *rdev) { return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_TT, TTM_PL_MASK_CACHING, - TTM_PL_FLAG_CACHED, true, - rdev->mc.gtt_size >> PAGE_SHIFT); + true, rdev->mc.gtt_size >> PAGE_SHIFT); } static void radeon_evict_flags(struct ttm_buffer_object *bo, diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e2bfe3a13c63d..43c0a5f09d671 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -876,8 +876,6 @@ static uint32_t ttm_bo_select_caching(struct ttm_resource_manager *man, if ((cur_placement & caching) != 0) result |= (cur_placement & caching); - else if ((man->default_caching & caching) != 0) - result |= man->default_caching; else if ((TTM_PL_FLAG_CACHED & caching) != 0) result |= TTM_PL_FLAG_CACHED; else if ((TTM_PL_FLAG_WC & caching) != 0) @@ -1435,7 +1433,6 @@ static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) */ man->use_tt = true; man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; ttm_resource_manager_init(man, 0); ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man); diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index 770c8988c1397..c80d9fa022f79 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -115,7 +115,6 @@ static const struct ttm_resource_manager_func ttm_range_manager_func; int ttm_range_man_init(struct ttm_bo_device *bdev, unsigned type, uint32_t available_caching, - uint32_t default_caching, bool use_tt, unsigned long p_size) { @@ -128,7 +127,6 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, man = &rman->manager; man->available_caching = available_caching; - man->default_caching = default_caching; man->use_tt = use_tt; man->func = &ttm_range_manager_func; diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 3a4602f9a03bd..80e10c28f3e84 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -141,7 +141,6 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, drm_printf(p, " use_tt: %d\n", man->use_tt); drm_printf(p, " size: %llu\n", man->size); drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); - drm_printf(p, " default_caching: 0x%08X\n", man->default_caching); if (man->func && man->func->debug) (*man->func->debug)(man, p); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index e600128860656..1020c991fd9b9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -627,8 +627,8 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) ret = vmw_thp_init(dev_priv); #else ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, - TTM_PL_FLAG_CACHED, TTM_PL_FLAG_CACHED, - false, dev_priv->vram_size >> PAGE_SHIFT); + TTM_PL_FLAG_CACHED, false, + dev_priv->vram_size >> PAGE_SHIFT); #endif ttm_resource_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index bb76acb5b0fcf..2d81a276b301d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -113,7 +113,6 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) man->func = &vmw_gmrid_manager_func; man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; /* TODO: This is most likely not correct */ man->use_tt = true; ttm_resource_manager_init(man, 0); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 3c00a9e7cfcc8..b6cf5763c9373 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -132,7 +132,6 @@ int vmw_thp_init(struct vmw_private *dev_priv) man = &rman->manager; man->available_caching = TTM_PL_FLAG_CACHED; - man->default_caching = TTM_PL_FLAG_CACHED; ttm_resource_manager_init(man, dev_priv->vram_size >> PAGE_SHIFT); diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 303a89d1066d0..bf000d69e5339 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -690,7 +690,6 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); * @bdev: ttm device * @type: memory manager type * @available_caching: TTM_PL_FLAG_* for allowed caching modes - * @default_caching: default caching mode * @use_tt: if the memory manager uses tt * @p_size: size of area to be managed in pages. * @@ -700,7 +699,6 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); int ttm_range_man_init(struct ttm_bo_device *bdev, unsigned type, uint32_t available_caching, - uint32_t default_caching, bool use_tt, unsigned long p_size); diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 7b8a3157fbb32..a6ae4bf9c3e1d 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -110,8 +110,6 @@ struct ttm_resource_manager_func { * @size: Size of the managed region. * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, * as defined in ttm_placement_common.h - * @default_caching: The default caching policy used for a buffer object - * placed in this memory type if the user doesn't provide one. * @func: structure pointer implementing the range manager. See above * @move_lock: lock for move fence * static information. bdev::driver::io_mem_free is never used. @@ -128,7 +126,6 @@ struct ttm_resource_manager { bool use_tt; uint64_t size; uint32_t available_caching; - uint32_t default_caching; const struct ttm_resource_manager_func *func; spinlock_t move_lock; -- GitLab From 5839172f09806f828319bdb2af97ca3c6cfcb432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 11 Sep 2020 15:36:30 +0200 Subject: [PATCH 1100/1494] drm/nouveau: explicitly specify caching to use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of letting TTM masking the caching bits specify directly what the driver needs. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/390206 --- drivers/gpu/drm/nouveau/nouveau_bo.c | 28 +++++++++++++++++++++------ drivers/gpu/drm/nouveau/nouveau_ttm.c | 19 +++--------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 97e1908eada07..b062ea8afffd8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -340,18 +340,33 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, } static void -set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain, - uint32_t flags) +set_placement_list(struct nouveau_drm *drm, struct ttm_place *pl, unsigned *n, + uint32_t domain, uint32_t flags) { *n = 0; if (domain & NOUVEAU_GEM_DOMAIN_VRAM) { + struct nvif_mmu *mmu = &drm->client.mmu; + const u8 type = mmu->type[drm->ttm.type_vram].type; + pl[*n].mem_type = TTM_PL_VRAM; - pl[(*n)++].flags = flags; + pl[*n].flags = flags & ~TTM_PL_FLAG_CACHED; + + /* Some BARs do not support being ioremapped WC */ + if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA && + type & NVIF_MEM_UNCACHED) + pl[*n].flags &= ~TTM_PL_FLAG_WC; + + (*n)++; } if (domain & NOUVEAU_GEM_DOMAIN_GART) { pl[*n].mem_type = TTM_PL_TT; - pl[(*n)++].flags = flags; + pl[*n].flags = flags; + + if (drm->agp.bridge) + pl[*n].flags &= ~TTM_PL_FLAG_CACHED; + + (*n)++; } if (domain & NOUVEAU_GEM_DOMAIN_CPU) { pl[*n].mem_type = TTM_PL_SYSTEM; @@ -397,17 +412,18 @@ void nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain, uint32_t busy) { + struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct ttm_placement *pl = &nvbo->placement; uint32_t flags = (nvbo->force_coherent ? TTM_PL_FLAG_UNCACHED : TTM_PL_MASK_CACHING) | (nvbo->pin_refcnt ? TTM_PL_FLAG_NO_EVICT : 0); pl->placement = nvbo->placements; - set_placement_list(nvbo->placements, &pl->num_placement, + set_placement_list(drm, nvbo->placements, &pl->num_placement, domain, flags); pl->busy_placement = nvbo->busy_placements; - set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, + set_placement_list(drm, nvbo->busy_placements, &pl->num_busy_placement, domain | busy, flags); set_placement_range(nvbo, domain); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index cf18f75cd0f1a..1b00f32b38498 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -194,19 +194,13 @@ nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind) static int nouveau_ttm_init_vram(struct nouveau_drm *drm) { - struct nvif_mmu *mmu = &drm->client.mmu; if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - /* Some BARs do not support being ioremapped WC */ - const u8 type = mmu->type[drm->ttm.type_vram].type; struct ttm_resource_manager *man = kzalloc(sizeof(*man), GFP_KERNEL); + if (!man) return -ENOMEM; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - - if (type & NVIF_MEM_UNCACHED) - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->func = &nouveau_vram_manager; ttm_resource_manager_init(man, @@ -243,13 +237,6 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) struct ttm_resource_manager *man; unsigned long size_pages = drm->gem.gart_available >> PAGE_SHIFT; const struct ttm_resource_manager_func *func = NULL; - unsigned available_caching; - - if (drm->agp.bridge) - available_caching = TTM_PL_FLAG_UNCACHED | - TTM_PL_FLAG_WC; - else - available_caching = TTM_PL_MASK_CACHING; if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) func = &nouveau_gart_manager; @@ -257,7 +244,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) func = &nv04_gart_manager; else return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, - available_caching, true, + TTM_PL_MASK_CACHING, true, size_pages); man = kzalloc(sizeof(*man), GFP_KERNEL); @@ -265,7 +252,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) return -ENOMEM; man->func = func; - man->available_caching = available_caching; + man->available_caching = TTM_PL_MASK_CACHING; man->use_tt = true; ttm_resource_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); -- GitLab From 9c3006a4cc1b165652a07727caf7926054f9aa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Fri, 11 Sep 2020 16:01:21 +0200 Subject: [PATCH 1101/1494] drm/ttm: remove available_caching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of letting TTM make an educated guess based on some mask all drivers should just specify what caching they want for their CPU mappings. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/390207/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 -- drivers/gpu/drm/drm_gem_vram_helper.c | 1 - drivers/gpu/drm/nouveau/nouveau_ttm.c | 9 ++------- drivers/gpu/drm/qxl/qxl_ttm.c | 3 +-- drivers/gpu/drm/radeon/radeon_ttm.c | 2 -- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++------ drivers/gpu/drm/ttm/ttm_range_manager.c | 5 +---- drivers/gpu/drm/ttm/ttm_resource.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +---- drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 10 +++------- include/drm/ttm/ttm_bo_driver.h | 5 +---- include/drm/ttm/ttm_resource.h | 3 --- 15 files changed, 11 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 12d6a018e60b3..f203e4a6a3f2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -95,7 +95,6 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size) man->use_tt = true; man->func = &amdgpu_gtt_mgr_func; - man->available_caching = TTM_PL_MASK_CACHING; ttm_resource_manager_init(man, gtt_size >> PAGE_SHIFT); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 15ce752b127c9..c2678e021f955 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -68,7 +68,6 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, uint64_t size) { return ttm_range_man_init(&adev->mman.bdev, type, - TTM_PL_FLAG_UNCACHED, false, size >> PAGE_SHIFT); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index f809d84ccda20..01c1171afbe02 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -179,8 +179,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) struct ttm_resource_manager *man = &mgr->manager; int ret; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; - ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT); man->func = &amdgpu_vram_mgr_func; diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index fff42bb56646b..f96321509d7eb 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1057,7 +1057,6 @@ static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev, return ret; ret = ttm_range_man_init(&vmm->bdev, TTM_PL_VRAM, - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, false, vram_size >> PAGE_SHIFT); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 1b00f32b38498..4273417534410 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -200,7 +200,6 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) if (!man) return -ENOMEM; - man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->func = &nouveau_vram_manager; ttm_resource_manager_init(man, @@ -209,9 +208,7 @@ nouveau_ttm_init_vram(struct nouveau_drm *drm) ttm_resource_manager_set_used(man, true); return 0; } else { - return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_VRAM, - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, - false, + return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_VRAM, false, drm->gem.vram_available >> PAGE_SHIFT); } } @@ -243,8 +240,7 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) else if (!drm->agp.bridge) func = &nv04_gart_manager; else - return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, - TTM_PL_MASK_CACHING, true, + return ttm_range_man_init(&drm->ttm.bdev, TTM_PL_TT, true, size_pages); man = kzalloc(sizeof(*man), GFP_KERNEL); @@ -252,7 +248,6 @@ nouveau_ttm_init_gtt(struct nouveau_drm *drm) return -ENOMEM; man->func = func; - man->available_caching = TTM_PL_MASK_CACHING; man->use_tt = true; ttm_resource_manager_init(man, size_pages); ttm_set_driver_manager(&drm->ttm.bdev, TTM_PL_TT, man); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index d39d7994ea349..bf3b091d0e2ae 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -202,8 +202,7 @@ static int qxl_ttm_init_mem_type(struct qxl_device *qdev, unsigned int type, uint64_t size) { - return ttm_range_man_init(&qdev->mman.bdev, type, TTM_PL_MASK_CACHING, - false, size); + return ttm_range_man_init(&qdev->mman.bdev, type, false, size); } int qxl_ttm_init(struct qxl_device *qdev) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b8e60b3630d7f..96be5c3c12692 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -69,14 +69,12 @@ struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) static int radeon_ttm_init_vram(struct radeon_device *rdev) { return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_VRAM, - TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC, false, rdev->mc.real_vram_size >> PAGE_SHIFT); } static int radeon_ttm_init_gtt(struct radeon_device *rdev) { return ttm_range_man_init(&rdev->mman.bdev, TTM_PL_TT, - TTM_PL_MASK_CACHING, true, rdev->mc.gtt_size >> PAGE_SHIFT); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 43c0a5f09d671..ee2632128d3c6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -910,11 +910,8 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo, if (!man || !ttm_resource_manager_used(man)) return -EBUSY; - if ((place->flags & man->available_caching) == 0) - return -EBUSY; - - cur_flags = place->flags & man->available_caching; - cur_flags = ttm_bo_select_caching(man, bo->mem.placement, cur_flags); + cur_flags = ttm_bo_select_caching(man, bo->mem.placement, + place->flags); cur_flags |= place->flags & ~TTM_PL_MASK_CACHING; mem->mem_type = place->mem_type; @@ -1432,7 +1429,6 @@ static void ttm_bo_init_sysman(struct ttm_bo_device *bdev) * Other types need to be driver / IOCTL initialized. */ man->use_tt = true; - man->available_caching = TTM_PL_MASK_CACHING; ttm_resource_manager_init(man, 0); ttm_set_driver_manager(bdev, TTM_PL_SYSTEM, man); diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index c80d9fa022f79..1da0e277c5111 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -113,9 +113,7 @@ static void ttm_range_man_free(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func ttm_range_manager_func; int ttm_range_man_init(struct ttm_bo_device *bdev, - unsigned type, - uint32_t available_caching, - bool use_tt, + unsigned type, bool use_tt, unsigned long p_size) { struct ttm_resource_manager *man; @@ -126,7 +124,6 @@ int ttm_range_man_init(struct ttm_bo_device *bdev, return -ENOMEM; man = &rman->manager; - man->available_caching = available_caching; man->use_tt = use_tt; man->func = &ttm_range_manager_func; diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 80e10c28f3e84..b325b9264203c 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -140,7 +140,6 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, drm_printf(p, " use_type: %d\n", man->use_type); drm_printf(p, " use_tt: %d\n", man->use_tt); drm_printf(p, " size: %llu\n", man->size); - drm_printf(p, " available_caching: 0x%08X\n", man->available_caching); if (man->func && man->func->debug) (*man->func->debug)(man, p); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1020c991fd9b9..31e3e5c9f3622 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -626,8 +626,7 @@ static int vmw_vram_manager_init(struct vmw_private *dev_priv) #ifdef CONFIG_TRANSPARENT_HUGEPAGE ret = vmw_thp_init(dev_priv); #else - ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, - TTM_PL_FLAG_CACHED, false, + ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, false, dev_priv->vram_size >> PAGE_SHIFT); #endif ttm_resource_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false); @@ -882,8 +881,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) DRM_ERROR("Failed initializing TTM buffer object driver.\n"); goto out_no_bdev; } - ttm_manager_type(&dev_priv->bdev, TTM_PL_SYSTEM)->available_caching = - TTM_PL_FLAG_CACHED; /* * Enable VRAM, but initially don't use it until SVGA is enabled and diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index 2d81a276b301d..db64c3a902852 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -112,7 +112,6 @@ int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type) man = &gman->manager; man->func = &vmw_gmrid_manager_func; - man->available_caching = TTM_PL_FLAG_CACHED; /* TODO: This is most likely not correct */ man->use_tt = true; ttm_resource_manager_init(man, 0); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index b6cf5763c9373..63fe7da4cbf40 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -123,24 +123,20 @@ static void vmw_thp_put_node(struct ttm_resource_manager *man, int vmw_thp_init(struct vmw_private *dev_priv) { - struct ttm_resource_manager *man; struct vmw_thp_manager *rman; rman = kzalloc(sizeof(*rman), GFP_KERNEL); if (!rman) return -ENOMEM; - man = &rman->manager; - man->available_caching = TTM_PL_FLAG_CACHED; - - ttm_resource_manager_init(man, + ttm_resource_manager_init(&rman->manager, dev_priv->vram_size >> PAGE_SHIFT); - drm_mm_init(&rman->mm, 0, man->size); + drm_mm_init(&rman->mm, 0, rman->manager.size); spin_lock_init(&rman->lock); ttm_set_driver_manager(&dev_priv->bdev, TTM_PL_VRAM, &rman->manager); - ttm_resource_manager_set_used(man, true); + ttm_resource_manager_set_used(&rman->manager, true); return 0; } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index bf000d69e5339..0b7d18650dc53 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -689,7 +689,6 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); * * @bdev: ttm device * @type: memory manager type - * @available_caching: TTM_PL_FLAG_* for allowed caching modes * @use_tt: if the memory manager uses tt * @p_size: size of area to be managed in pages. * @@ -697,9 +696,7 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); * The range manager is installed for this device in the type slot. */ int ttm_range_man_init(struct ttm_bo_device *bdev, - unsigned type, - uint32_t available_caching, - bool use_tt, + unsigned type, bool use_tt, unsigned long p_size); /** diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index a6ae4bf9c3e1d..0e172d94a0c1e 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -108,8 +108,6 @@ struct ttm_resource_manager_func { * @gpu_offset: If used, the GPU offset of the first managed page of * fixed memory or the first managed location in an aperture. * @size: Size of the managed region. - * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, - * as defined in ttm_placement_common.h * @func: structure pointer implementing the range manager. See above * @move_lock: lock for move fence * static information. bdev::driver::io_mem_free is never used. @@ -125,7 +123,6 @@ struct ttm_resource_manager { bool use_type; bool use_tt; uint64_t size; - uint32_t available_caching; const struct ttm_resource_manager_func *func; spinlock_t move_lock; -- GitLab From 5526fa0bfd248051ef92d62df9f1b78c72fd2046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:50 +0300 Subject: [PATCH 1102/1494] drm/i915: Add more AUX CHs to the enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to go up to AUX_CH_I (aka. AUX CH USBC6) these days. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-2-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 003b68dda9445..d10b7c8cde3fd 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -280,6 +280,8 @@ enum aux_ch { AUX_CH_E, /* ICL+ */ AUX_CH_F, AUX_CH_G, + AUX_CH_H, + AUX_CH_I, }; #define aux_ch_name(a) ((a) + 'A') -- GitLab From 07c9b088d780fbef51dc6d194a45c6b0bf3df10f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:51 +0300 Subject: [PATCH 1103/1494] drm/i915: Add PORT_{H,I} to intel_port_to_power_domain() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to go up to PORT_I (aka. TC6) these days. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5611a3d955940..69128f11b1d9b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7332,6 +7332,10 @@ enum intel_display_power_domain intel_port_to_power_domain(enum port port) return POWER_DOMAIN_PORT_DDI_F_LANES; case PORT_G: return POWER_DOMAIN_PORT_DDI_G_LANES; + case PORT_H: + return POWER_DOMAIN_PORT_DDI_H_LANES; + case PORT_I: + return POWER_DOMAIN_PORT_DDI_I_LANES; default: MISSING_CASE(port); return POWER_DOMAIN_PORT_OTHER; -- GitLab From 244f2e9ce3e3f38c0cd46db1fcbe21aa04d9ba94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:52 +0300 Subject: [PATCH 1104/1494] drm/i915: Add AUX_CH_{H,I} power domain handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AUX CH H/I need their power domains too. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 69128f11b1d9b..254fbeec56298 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7361,6 +7361,10 @@ intel_aux_power_domain(struct intel_digital_port *dig_port) return POWER_DOMAIN_AUX_F_TBT; case AUX_CH_G: return POWER_DOMAIN_AUX_G_TBT; + case AUX_CH_H: + return POWER_DOMAIN_AUX_H_TBT; + case AUX_CH_I: + return POWER_DOMAIN_AUX_I_TBT; default: MISSING_CASE(dig_port->aux_ch); return POWER_DOMAIN_AUX_C_TBT; @@ -7392,6 +7396,10 @@ intel_legacy_aux_to_power_domain(enum aux_ch aux_ch) return POWER_DOMAIN_AUX_F; case AUX_CH_G: return POWER_DOMAIN_AUX_G; + case AUX_CH_H: + return POWER_DOMAIN_AUX_H; + case AUX_CH_I: + return POWER_DOMAIN_AUX_I; default: MISSING_CASE(aux_ch); return POWER_DOMAIN_AUX_A; -- GitLab From 176430cc13470e0c7191459af832abc8d41c3c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:53 +0300 Subject: [PATCH 1105/1494] drm/i915: Add VBT DVO ports H and I MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VBT has ports H and I since version 217. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-5-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_bios.c | 2 ++ drivers/gpu/drm/i915/display/intel_vbt_defs.h | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index c110cd9e8a73c..4437de010b4d0 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1656,6 +1656,8 @@ static enum port dvo_port_to_port(struct drm_i915_private *dev_priv, [PORT_E] = { DVO_PORT_HDMIE, DVO_PORT_DPE, DVO_PORT_CRT }, [PORT_F] = { DVO_PORT_HDMIF, DVO_PORT_DPF, -1 }, [PORT_G] = { DVO_PORT_HDMIG, DVO_PORT_DPG, -1 }, + [PORT_H] = { DVO_PORT_HDMIH, DVO_PORT_DPH, -1 }, + [PORT_I] = { DVO_PORT_HDMII, DVO_PORT_DPI, -1 }, }; /* * Bspec lists the ports as A, B, C, D - however internally in our diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index 6faabd4f6d498..a5c0114b042af 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -293,8 +293,12 @@ struct bdb_general_features { #define DVO_PORT_HDMIE 12 /* 193 */ #define DVO_PORT_DPF 13 /* N/A */ #define DVO_PORT_HDMIF 14 /* N/A */ -#define DVO_PORT_DPG 15 -#define DVO_PORT_HDMIG 16 +#define DVO_PORT_DPG 15 /* 217 */ +#define DVO_PORT_HDMIG 16 /* 217 */ +#define DVO_PORT_DPH 17 /* 217 */ +#define DVO_PORT_HDMIH 18 /* 217 */ +#define DVO_PORT_DPI 19 /* 217 */ +#define DVO_PORT_HDMII 20 /* 217 */ #define DVO_PORT_MIPIA 21 /* 171 */ #define DVO_PORT_MIPIB 22 /* 171 */ #define DVO_PORT_MIPIC 23 /* 171 */ -- GitLab From 5bf22ee41003729e28e082a9574cef0ed31a434b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:54 +0300 Subject: [PATCH 1106/1494] drm/i915: Add VBT AUX CH H and I MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As with everything else VBT can now specify AUX CH H or I. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-6-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_bios.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_vbt_defs.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 4437de010b4d0..4716484af62d9 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2652,6 +2652,12 @@ enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, case DP_AUX_G: aux_ch = AUX_CH_G; break; + case DP_AUX_H: + aux_ch = AUX_CH_H; + break; + case DP_AUX_I: + aux_ch = AUX_CH_I; + break; default: MISSING_CASE(info->alternate_aux_channel); aux_ch = AUX_CH_A; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index a5c0114b042af..54bcc6a6947c2 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -334,6 +334,8 @@ enum vbt_gmbus_ddi { #define DP_AUX_E 0x50 #define DP_AUX_F 0x60 #define DP_AUX_G 0x70 +#define DP_AUX_H 0x80 +#define DP_AUX_I 0x90 #define VBT_DP_MAX_LINK_RATE_HBR3 0 #define VBT_DP_MAX_LINK_RATE_HBR2 1 -- GitLab From a52bfcdd806f054156a72e9dc88d2d53d565e475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:55 +0300 Subject: [PATCH 1107/1494] drm/i915: Nuke the redundant TC/TBT HPD bit defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have nice parametrized GEN11_{TC,TBT}_HOTPLUG() so nuke the overlapping defines. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-7-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 20 +++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 36 +++++++++++---------------------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f113fe44572b5..81cfc7280514d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -132,19 +132,19 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { }; static const u32 hpd_gen11[HPD_NUM_PINS] = { - [HPD_PORT_C] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, - [HPD_PORT_D] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, - [HPD_PORT_E] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, - [HPD_PORT_F] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG, + [HPD_PORT_C] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), + [HPD_PORT_D] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), + [HPD_PORT_E] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), + [HPD_PORT_F] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), }; static const u32 hpd_gen12[HPD_NUM_PINS] = { - [HPD_PORT_D] = GEN11_TC1_HOTPLUG | GEN11_TBT1_HOTPLUG, - [HPD_PORT_E] = GEN11_TC2_HOTPLUG | GEN11_TBT2_HOTPLUG, - [HPD_PORT_F] = GEN11_TC3_HOTPLUG | GEN11_TBT3_HOTPLUG, - [HPD_PORT_G] = GEN11_TC4_HOTPLUG | GEN11_TBT4_HOTPLUG, - [HPD_PORT_H] = GEN12_TC5_HOTPLUG | GEN12_TBT5_HOTPLUG, - [HPD_PORT_I] = GEN12_TC6_HOTPLUG | GEN12_TBT6_HOTPLUG, + [HPD_PORT_D] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), + [HPD_PORT_E] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), + [HPD_PORT_F] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), + [HPD_PORT_G] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), + [HPD_PORT_H] = GEN11_TC_HOTPLUG(PORT_TC5) | GEN11_TBT_HOTPLUG(PORT_TC5), + [HPD_PORT_I] = GEN11_TC_HOTPLUG(PORT_TC6) | GEN11_TBT_HOTPLUG(PORT_TC6), }; static const u32 hpd_icp[HPD_NUM_PINS] = { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 90a05e37ba2fe..d805d4da6181b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7759,32 +7759,20 @@ enum { #define GEN11_DE_HPD_IMR _MMIO(0x44474) #define GEN11_DE_HPD_IIR _MMIO(0x44478) #define GEN11_DE_HPD_IER _MMIO(0x4447c) -#define GEN12_TC6_HOTPLUG (1 << 21) -#define GEN12_TC5_HOTPLUG (1 << 20) -#define GEN11_TC4_HOTPLUG (1 << 19) -#define GEN11_TC3_HOTPLUG (1 << 18) -#define GEN11_TC2_HOTPLUG (1 << 17) -#define GEN11_TC1_HOTPLUG (1 << 16) #define GEN11_TC_HOTPLUG(tc_port) (1 << ((tc_port) + 16)) -#define GEN11_DE_TC_HOTPLUG_MASK (GEN12_TC6_HOTPLUG | \ - GEN12_TC5_HOTPLUG | \ - GEN11_TC4_HOTPLUG | \ - GEN11_TC3_HOTPLUG | \ - GEN11_TC2_HOTPLUG | \ - GEN11_TC1_HOTPLUG) -#define GEN12_TBT6_HOTPLUG (1 << 5) -#define GEN12_TBT5_HOTPLUG (1 << 4) -#define GEN11_TBT4_HOTPLUG (1 << 3) -#define GEN11_TBT3_HOTPLUG (1 << 2) -#define GEN11_TBT2_HOTPLUG (1 << 1) -#define GEN11_TBT1_HOTPLUG (1 << 0) +#define GEN11_DE_TC_HOTPLUG_MASK (GEN11_TC_HOTPLUG(PORT_TC6) | \ + GEN11_TC_HOTPLUG(PORT_TC5) | \ + GEN11_TC_HOTPLUG(PORT_TC4) | \ + GEN11_TC_HOTPLUG(PORT_TC3) | \ + GEN11_TC_HOTPLUG(PORT_TC2) | \ + GEN11_TC_HOTPLUG(PORT_TC1)) #define GEN11_TBT_HOTPLUG(tc_port) (1 << (tc_port)) -#define GEN11_DE_TBT_HOTPLUG_MASK (GEN12_TBT6_HOTPLUG | \ - GEN12_TBT5_HOTPLUG | \ - GEN11_TBT4_HOTPLUG | \ - GEN11_TBT3_HOTPLUG | \ - GEN11_TBT2_HOTPLUG | \ - GEN11_TBT1_HOTPLUG) +#define GEN11_DE_TBT_HOTPLUG_MASK (GEN11_TBT_HOTPLUG(PORT_TC6) | \ + GEN11_TBT_HOTPLUG(PORT_TC5) | \ + GEN11_TBT_HOTPLUG(PORT_TC4) | \ + GEN11_TBT_HOTPLUG(PORT_TC3) | \ + GEN11_TBT_HOTPLUG(PORT_TC2) | \ + GEN11_TBT_HOTPLUG(PORT_TC1)) #define GEN11_TBT_HOTPLUG_CTL _MMIO(0x44030) #define GEN11_TC_HOTPLUG_CTL _MMIO(0x44038) -- GitLab From 1db9f992d67b9edefed65b829767bb01fb23c63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:56 +0300 Subject: [PATCH 1108/1494] drm/i915: Configure GEN11_{TBT,TC}_HOTPLUG_CTL for ports TC5/6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gen11_hpd_detection_setup() is missing ports TC5/6. Add them. TODO: Might be nice to only enable the hpd detection logic for ports we actually have. Should be rolled out for all platforms if/when done... Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-8-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 81cfc7280514d..78f8ab9bf229d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3154,14 +3154,18 @@ static void gen11_hpd_detection_setup(struct drm_i915_private *dev_priv) hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC6); I915_WRITE(GEN11_TC_HOTPLUG_CTL, hotplug); hotplug = I915_READ(GEN11_TBT_HOTPLUG_CTL); hotplug |= GEN11_HOTPLUG_CTL_ENABLE(PORT_TC1) | GEN11_HOTPLUG_CTL_ENABLE(PORT_TC2) | GEN11_HOTPLUG_CTL_ENABLE(PORT_TC3) | - GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4); + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC4) | + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC5) | + GEN11_HOTPLUG_CTL_ENABLE(PORT_TC6); I915_WRITE(GEN11_TBT_HOTPLUG_CTL, hotplug); } -- GitLab From 815f4ef21f4ae9fdd182400560ac6025f420a21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:57 +0300 Subject: [PATCH 1109/1494] drm/i915: Split icp_hpd_detection_setup() into ddi vs. tc parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No reason to stuff both DDI and TC port handling into the same function. Split it into two. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-9-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 48 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 78f8ab9bf229d..c71f1cc2e5b61 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3089,21 +3089,24 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) ibx_hpd_detection_setup(dev_priv); } -static void icp_hpd_detection_setup(struct drm_i915_private *dev_priv, - u32 ddi_hotplug_enable_mask, - u32 tc_hotplug_enable_mask) +static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv, + u32 enable_mask) { u32 hotplug; hotplug = I915_READ(SHOTPLUG_CTL_DDI); - hotplug |= ddi_hotplug_enable_mask; + hotplug |= enable_mask; I915_WRITE(SHOTPLUG_CTL_DDI, hotplug); +} - if (tc_hotplug_enable_mask) { - hotplug = I915_READ(SHOTPLUG_CTL_TC); - hotplug |= tc_hotplug_enable_mask; - I915_WRITE(SHOTPLUG_CTL_TC, hotplug); - } +static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv, + u32 enable_mask) +{ + u32 hotplug; + + hotplug = I915_READ(SHOTPLUG_CTL_TC); + hotplug |= enable_mask; + I915_WRITE(SHOTPLUG_CTL_TC, hotplug); } static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, @@ -3120,7 +3123,9 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); - icp_hpd_detection_setup(dev_priv, ddi_enable_mask, tc_enable_mask); + icp_ddi_hpd_detection_setup(dev_priv, ddi_enable_mask); + if (tc_enable_mask) + icp_tc_hpd_detection_setup(dev_priv, tc_enable_mask); } /* @@ -3538,17 +3543,18 @@ static void icp_irq_postinstall(struct drm_i915_private *dev_priv) gen3_assert_iir_is_zero(&dev_priv->uncore, SDEIIR); I915_WRITE(SDEIMR, ~mask); - if (HAS_PCH_TGP(dev_priv)) - icp_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK, - TGP_TC_HPD_ENABLE_MASK); - else if (HAS_PCH_JSP(dev_priv)) - icp_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK, 0); - else if (HAS_PCH_MCC(dev_priv)) - icp_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK, - ICP_TC_HPD_ENABLE(PORT_TC1)); - else - icp_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK, - ICP_TC_HPD_ENABLE_MASK); + if (HAS_PCH_TGP(dev_priv)) { + icp_ddi_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK); + icp_tc_hpd_detection_setup(dev_priv, TGP_TC_HPD_ENABLE_MASK); + } else if (HAS_PCH_JSP(dev_priv)) { + icp_ddi_hpd_detection_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK); + } else if (HAS_PCH_MCC(dev_priv)) { + icp_ddi_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK); + icp_tc_hpd_detection_setup(dev_priv, ICP_TC_HPD_ENABLE(PORT_TC1)); + } else { + icp_ddi_hpd_detection_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK); + icp_tc_hpd_detection_setup(dev_priv, ICP_TC_HPD_ENABLE_MASK); + } } static void gen11_irq_postinstall(struct drm_i915_private *dev_priv) -- GitLab From 03c7e4f1190e1dc338c7a8f104d2ba1dd233f2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:58 +0300 Subject: [PATCH 1110/1494] drm/i915: Move hpd_pin setup to encoder init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently DP/HDMI/DDI encoders init their hpd_pin from the connector init. Let's move it to the encoder init so that we don't need to add platform specific junk to the connector init (which is shared by all g4x+ platforms). Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-10-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6af080542c969..8074886c2965c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -5050,6 +5050,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->port = port; encoder->cloneable = 0; encoder->pipe_mask = ~0; + encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (INTEL_GEN(dev_priv) >= 11) dig_port->saved_port_bits = diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 1a8185f8fb8ea..4bd10456ad188 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7601,7 +7601,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, if (INTEL_GEN(dev_priv) >= 11) connector->ycbcr_420_allowed = true; - intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); intel_connector->polled = DRM_CONNECTOR_POLL_HPD; intel_dp_aux_init(intel_dp); @@ -7746,6 +7745,7 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, } intel_encoder->cloneable = 0; intel_encoder->port = port; + intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); dig_port->hpd_pulse = intel_dp_hpd_pulse; diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 04f59516d5f31..40620c3d7a30c 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -3259,7 +3259,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port, if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) connector->ycbcr_420_allowed = true; - intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); intel_connector->polled = DRM_CONNECTOR_POLL_HPD; if (HAS_DDI(dev_priv)) @@ -3393,6 +3392,7 @@ void intel_hdmi_init(struct drm_i915_private *dev_priv, intel_encoder->pipe_mask = ~0; } intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG; + intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); /* * BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems * to work on real hardware. And since g4x can send infoframes to -- GitLab From da51e4bafdfafc627ba57de8add05a968d2e6f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:55:59 +0300 Subject: [PATCH 1111/1494] drm/i915: Introduce HPD_PORT_TC<n> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make a clean split between hpd pins for DDI vs. TC. This matches how the actual hardware is split. And with this we move the DDI/PHY->HPD pin mapping into the encoder init instead of having to remap yet again in the interrupt code. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-11-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 65 +++++++++- drivers/gpu/drm/i915/display/intel_hotplug.c | 25 +--- drivers/gpu/drm/i915/i915_drv.h | 17 +-- drivers/gpu/drm/i915/i915_irq.c | 121 +++++-------------- 4 files changed, 102 insertions(+), 126 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 8074886c2965c..a73534d0a6423 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4975,6 +4975,57 @@ static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy) i915->hti_state & HDPORT_PHY_USED_HDMI(phy)); } +static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port >= PORT_D) + return HPD_PORT_TC1 + port - PORT_D; + else + return HPD_PORT_A + port - PORT_A; +} + +static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (HAS_PCH_TGP(dev_priv)) + return tgl_hpd_pin(dev_priv, port); + + if (port >= PORT_D) + return HPD_PORT_C + port - PORT_D; + else + return HPD_PORT_A + port - PORT_A; +} + +static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port >= PORT_C) + return HPD_PORT_TC1 + port - PORT_C; + else + return HPD_PORT_A + port - PORT_A; +} + +static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port == PORT_D) + return HPD_PORT_A; + + if (HAS_PCH_MCC(dev_priv)) + return icl_hpd_pin(dev_priv, port); + + return HPD_PORT_A + port - PORT_A; +} + +static enum hpd_pin cnl_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port == PORT_F) + return HPD_PORT_E; + + return HPD_PORT_A + port - PORT_A; +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *dig_port; @@ -5050,7 +5101,19 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->port = port; encoder->cloneable = 0; encoder->pipe_mask = ~0; - encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); + + if (IS_ROCKETLAKE(dev_priv)) + encoder->hpd_pin = rkl_hpd_pin(dev_priv, port); + else if (INTEL_GEN(dev_priv) >= 12) + encoder->hpd_pin = tgl_hpd_pin(dev_priv, port); + else if (IS_ELKHARTLAKE(dev_priv)) + encoder->hpd_pin = ehl_hpd_pin(dev_priv, port); + else if (IS_GEN(dev_priv, 11)) + encoder->hpd_pin = icl_hpd_pin(dev_priv, port); + else if (IS_GEN(dev_priv, 10)) + encoder->hpd_pin = cnl_hpd_pin(dev_priv, port); + else + encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); if (INTEL_GEN(dev_priv) >= 11) dig_port->saved_port_bits = diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 3f1d7b804a668..f3dbf2bd80107 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -81,33 +81,12 @@ * * It is only valid and used by digital port encoder. * - * Return pin that is associatade with @port and HDP_NONE if no pin is - * hard associated with that @port. + * Return pin that is associatade with @port. */ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv, enum port port) { - enum phy phy = intel_port_to_phy(dev_priv, port); - - /* - * RKL + TGP PCH is a special case; we effectively choose the hpd_pin - * based on the DDI rather than the PHY (i.e., the last two outputs - * shold be HPD_PORT_{D,E} rather than {C,D}. Note that this differs - * from the behavior of both TGL+TGP and RKL+CMP. - */ - if (IS_ROCKETLAKE(dev_priv) && HAS_PCH_TGP(dev_priv)) - return HPD_PORT_A + port - PORT_A; - - switch (phy) { - case PHY_F: - return IS_CNL_WITH_PORT_F(dev_priv) ? HPD_PORT_E : HPD_PORT_F; - case PHY_A ... PHY_E: - case PHY_G ... PHY_I: - return HPD_PORT_A + phy - PHY_A; - default: - MISSING_CASE(phy); - return HPD_NONE; - } + return HPD_PORT_A + port - PORT_A; } #define HPD_STORM_DETECT_PERIOD 1000 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 61d7a6114628d..8c62b5c41d058 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -113,13 +113,6 @@ struct drm_i915_gem_object; -/* - * The code assumes that the hpd_pins below have consecutive values and - * starting with HPD_PORT_A, the HPD pin associated with any port can be - * retrieved by adding the corresponding port (or phy) enum value to - * HPD_PORT_A in most cases. For example: - * HPD_PORT_C = HPD_PORT_A + PHY_C - PHY_A - */ enum hpd_pin { HPD_NONE = 0, HPD_TV = HPD_NONE, /* TV is known to be unreliable */ @@ -131,10 +124,12 @@ enum hpd_pin { HPD_PORT_C, HPD_PORT_D, HPD_PORT_E, - HPD_PORT_F, - HPD_PORT_G, - HPD_PORT_H, - HPD_PORT_I, + HPD_PORT_TC1, + HPD_PORT_TC2, + HPD_PORT_TC3, + HPD_PORT_TC4, + HPD_PORT_TC5, + HPD_PORT_TC6, HPD_NUM_PINS }; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c71f1cc2e5b61..f5297bacf793e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -132,40 +132,24 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { }; static const u32 hpd_gen11[HPD_NUM_PINS] = { - [HPD_PORT_C] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), - [HPD_PORT_D] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), - [HPD_PORT_E] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), - [HPD_PORT_F] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), -}; - -static const u32 hpd_gen12[HPD_NUM_PINS] = { - [HPD_PORT_D] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), - [HPD_PORT_E] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), - [HPD_PORT_F] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), - [HPD_PORT_G] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), - [HPD_PORT_H] = GEN11_TC_HOTPLUG(PORT_TC5) | GEN11_TBT_HOTPLUG(PORT_TC5), - [HPD_PORT_I] = GEN11_TC_HOTPLUG(PORT_TC6) | GEN11_TBT_HOTPLUG(PORT_TC6), + [HPD_PORT_TC1] = GEN11_TC_HOTPLUG(PORT_TC1) | GEN11_TBT_HOTPLUG(PORT_TC1), + [HPD_PORT_TC2] = GEN11_TC_HOTPLUG(PORT_TC2) | GEN11_TBT_HOTPLUG(PORT_TC2), + [HPD_PORT_TC3] = GEN11_TC_HOTPLUG(PORT_TC3) | GEN11_TBT_HOTPLUG(PORT_TC3), + [HPD_PORT_TC4] = GEN11_TC_HOTPLUG(PORT_TC4) | GEN11_TBT_HOTPLUG(PORT_TC4), + [HPD_PORT_TC5] = GEN11_TC_HOTPLUG(PORT_TC5) | GEN11_TBT_HOTPLUG(PORT_TC5), + [HPD_PORT_TC6] = GEN11_TC_HOTPLUG(PORT_TC6) | GEN11_TBT_HOTPLUG(PORT_TC6), }; static const u32 hpd_icp[HPD_NUM_PINS] = { - [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(PORT_A), - [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(PORT_B), - [HPD_PORT_C] = SDE_TC_HOTPLUG_ICP(PORT_TC1), - [HPD_PORT_D] = SDE_TC_HOTPLUG_ICP(PORT_TC2), - [HPD_PORT_E] = SDE_TC_HOTPLUG_ICP(PORT_TC3), - [HPD_PORT_F] = SDE_TC_HOTPLUG_ICP(PORT_TC4), -}; - -static const u32 hpd_tgp[HPD_NUM_PINS] = { [HPD_PORT_A] = SDE_DDI_HOTPLUG_ICP(PORT_A), [HPD_PORT_B] = SDE_DDI_HOTPLUG_ICP(PORT_B), [HPD_PORT_C] = SDE_DDI_HOTPLUG_ICP(PORT_C), - [HPD_PORT_D] = SDE_TC_HOTPLUG_ICP(PORT_TC1), - [HPD_PORT_E] = SDE_TC_HOTPLUG_ICP(PORT_TC2), - [HPD_PORT_F] = SDE_TC_HOTPLUG_ICP(PORT_TC3), - [HPD_PORT_G] = SDE_TC_HOTPLUG_ICP(PORT_TC4), - [HPD_PORT_H] = SDE_TC_HOTPLUG_ICP(PORT_TC5), - [HPD_PORT_I] = SDE_TC_HOTPLUG_ICP(PORT_TC6), + [HPD_PORT_TC1] = SDE_TC_HOTPLUG_ICP(PORT_TC1), + [HPD_PORT_TC2] = SDE_TC_HOTPLUG_ICP(PORT_TC2), + [HPD_PORT_TC3] = SDE_TC_HOTPLUG_ICP(PORT_TC3), + [HPD_PORT_TC4] = SDE_TC_HOTPLUG_ICP(PORT_TC4), + [HPD_PORT_TC5] = SDE_TC_HOTPLUG_ICP(PORT_TC5), + [HPD_PORT_TC6] = SDE_TC_HOTPLUG_ICP(PORT_TC6), }; static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) @@ -181,9 +165,7 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) return; } - if (INTEL_GEN(dev_priv) >= 12) - hpd->hpd = hpd_gen12; - else if (INTEL_GEN(dev_priv) >= 11) + if (INTEL_GEN(dev_priv) >= 11) hpd->hpd = hpd_gen11; else if (IS_GEN9_LP(dev_priv)) hpd->hpd = hpd_bxt; @@ -197,9 +179,8 @@ static void intel_hpd_init_pins(struct drm_i915_private *dev_priv) if (!HAS_PCH_SPLIT(dev_priv) || HAS_PCH_NOP(dev_priv)) return; - if (HAS_PCH_TGP(dev_priv) || HAS_PCH_JSP(dev_priv)) - hpd->pch_hpd = hpd_tgp; - else if (HAS_PCH_ICP(dev_priv) || HAS_PCH_MCC(dev_priv)) + if (HAS_PCH_TGP(dev_priv) || HAS_PCH_JSP(dev_priv) || + HAS_PCH_ICP(dev_priv) || HAS_PCH_MCC(dev_priv)) hpd->pch_hpd = hpd_icp; else if (HAS_PCH_CNP(dev_priv) || HAS_PCH_SPT(dev_priv)) hpd->pch_hpd = hpd_spt; @@ -1049,33 +1030,17 @@ static void ivb_parity_work(struct work_struct *work) static bool gen11_port_hotplug_long_detect(enum hpd_pin pin, u32 val) { switch (pin) { - case HPD_PORT_C: + case HPD_PORT_TC1: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); - case HPD_PORT_D: + case HPD_PORT_TC2: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); - case HPD_PORT_E: + case HPD_PORT_TC3: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); - case HPD_PORT_F: + case HPD_PORT_TC4: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); - default: - return false; - } -} - -static bool gen12_port_hotplug_long_detect(enum hpd_pin pin, u32 val) -{ - switch (pin) { - case HPD_PORT_D: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC1); - case HPD_PORT_E: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC2); - case HPD_PORT_F: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC3); - case HPD_PORT_G: - return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC4); - case HPD_PORT_H: + case HPD_PORT_TC5: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC5); - case HPD_PORT_I: + case HPD_PORT_TC6: return val & GEN11_HOTPLUG_CTL_LONG_DETECT(PORT_TC6); default: return false; @@ -1113,33 +1078,17 @@ static bool icp_ddi_port_hotplug_long_detect(enum hpd_pin pin, u32 val) static bool icp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) { switch (pin) { - case HPD_PORT_C: + case HPD_PORT_TC1: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); - case HPD_PORT_D: + case HPD_PORT_TC2: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); - case HPD_PORT_E: + case HPD_PORT_TC3: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); - case HPD_PORT_F: + case HPD_PORT_TC4: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); - default: - return false; - } -} - -static bool tgp_tc_port_hotplug_long_detect(enum hpd_pin pin, u32 val) -{ - switch (pin) { - case HPD_PORT_D: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC1); - case HPD_PORT_E: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC2); - case HPD_PORT_F: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC3); - case HPD_PORT_G: - return val & ICP_TC_HPD_LONG_DETECT(PORT_TC4); - case HPD_PORT_H: + case HPD_PORT_TC5: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC5); - case HPD_PORT_I: + case HPD_PORT_TC6: return val & ICP_TC_HPD_LONG_DETECT(PORT_TC6); default: return false; @@ -1893,19 +1842,16 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) { u32 ddi_hotplug_trigger, tc_hotplug_trigger; u32 pin_mask = 0, long_mask = 0; - bool (*tc_port_hotplug_long_detect)(enum hpd_pin pin, u32 val); if (HAS_PCH_TGP(dev_priv)) { ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; tc_hotplug_trigger = pch_iir & SDE_TC_MASK_TGP; - tc_port_hotplug_long_detect = tgp_tc_port_hotplug_long_detect; } else if (HAS_PCH_JSP(dev_priv)) { ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_TGP; tc_hotplug_trigger = 0; } else if (HAS_PCH_MCC(dev_priv)) { ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; tc_hotplug_trigger = pch_iir & SDE_TC_HOTPLUG_ICP(PORT_TC1); - tc_port_hotplug_long_detect = icp_tc_port_hotplug_long_detect; } else { drm_WARN(&dev_priv->drm, !HAS_PCH_ICP(dev_priv), "Unrecognized PCH type 0x%x\n", @@ -1913,7 +1859,6 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) ddi_hotplug_trigger = pch_iir & SDE_DDI_MASK_ICP; tc_hotplug_trigger = pch_iir & SDE_TC_MASK_ICP; - tc_port_hotplug_long_detect = icp_tc_port_hotplug_long_detect; } if (ddi_hotplug_trigger) { @@ -1937,7 +1882,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, tc_hotplug_trigger, dig_hotplug_reg, dev_priv->hotplug.pch_hpd, - tc_port_hotplug_long_detect); + icp_tc_port_hotplug_long_detect); } if (pin_mask) @@ -2185,12 +2130,6 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) u32 pin_mask = 0, long_mask = 0; u32 trigger_tc = iir & GEN11_DE_TC_HOTPLUG_MASK; u32 trigger_tbt = iir & GEN11_DE_TBT_HOTPLUG_MASK; - long_pulse_detect_func long_pulse_detect; - - if (INTEL_GEN(dev_priv) >= 12) - long_pulse_detect = gen12_port_hotplug_long_detect; - else - long_pulse_detect = gen11_port_hotplug_long_detect; if (trigger_tc) { u32 dig_hotplug_reg; @@ -2201,7 +2140,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tc, dig_hotplug_reg, dev_priv->hotplug.hpd, - long_pulse_detect); + gen11_port_hotplug_long_detect); } if (trigger_tbt) { @@ -2213,7 +2152,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir) intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, trigger_tbt, dig_hotplug_reg, dev_priv->hotplug.hpd, - long_pulse_detect); + gen11_port_hotplug_long_detect); } if (pin_mask) -- GitLab From 6d3144eb367063df630248e0564b75701f63423b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:56:00 +0300 Subject: [PATCH 1112/1494] drm/i915: Introduce intel_hpd_hotplug_irqs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce intel_hpd_hotplug_irqs() as a partner to intel_hpd_enabled_irqs(). There's no need to care about the encoders which we're not exposing, so we can avoid hardcoding the masks in various places. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-12-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/i915_irq.c | 50 +++++++++++++++------------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f5297bacf793e..759f523c6a6bf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2987,6 +2987,18 @@ static u32 intel_hpd_enabled_irqs(struct drm_i915_private *dev_priv, return enabled_irqs; } +static u32 intel_hpd_hotplug_irqs(struct drm_i915_private *dev_priv, + const u32 hpd[HPD_NUM_PINS]) +{ + struct intel_encoder *encoder; + u32 hotplug_irqs = 0; + + for_each_intel_encoder(&dev_priv->drm, encoder) + hotplug_irqs |= hpd[encoder->hpd_pin]; + + return hotplug_irqs; +} + static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv) { u32 hotplug; @@ -3016,12 +3028,8 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - if (HAS_PCH_IBX(dev_priv)) - hotplug_irqs = SDE_HOTPLUG_MASK; - else - hotplug_irqs = SDE_HOTPLUG_MASK_CPT; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -3049,13 +3057,12 @@ static void icp_tc_hpd_detection_setup(struct drm_i915_private *dev_priv, } static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, - u32 sde_ddi_mask, u32 sde_tc_mask, u32 ddi_enable_mask, u32 tc_enable_mask) { u32 hotplug_irqs, enabled_irqs; - hotplug_irqs = sde_ddi_mask | sde_tc_mask; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); if (INTEL_PCH_TYPE(dev_priv) <= PCH_TGP) I915_WRITE(SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); @@ -3074,7 +3081,6 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv, static void mcc_hpd_irq_setup(struct drm_i915_private *dev_priv) { icp_hpd_irq_setup(dev_priv, - SDE_DDI_MASK_ICP, SDE_TC_HOTPLUG_ICP(PORT_TC1), ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE(PORT_TC1)); } @@ -3086,7 +3092,6 @@ static void mcc_hpd_irq_setup(struct drm_i915_private *dev_priv) static void jsp_hpd_irq_setup(struct drm_i915_private *dev_priv) { icp_hpd_irq_setup(dev_priv, - SDE_DDI_MASK_TGP, 0, TGP_DDI_HPD_ENABLE_MASK, 0); } @@ -3119,7 +3124,7 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) u32 val; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - hotplug_irqs = GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK; + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); val = I915_READ(GEN11_DE_HPD_IMR); val &= ~hotplug_irqs; @@ -3130,10 +3135,10 @@ static void gen11_hpd_irq_setup(struct drm_i915_private *dev_priv) gen11_hpd_detection_setup(dev_priv); if (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP) - icp_hpd_irq_setup(dev_priv, SDE_DDI_MASK_TGP, SDE_TC_MASK_TGP, + icp_hpd_irq_setup(dev_priv, TGP_DDI_HPD_ENABLE_MASK, TGP_TC_HPD_ENABLE_MASK); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - icp_hpd_irq_setup(dev_priv, SDE_DDI_MASK_ICP, SDE_TC_MASK_ICP, + icp_hpd_irq_setup(dev_priv, ICP_DDI_HPD_ENABLE_MASK, ICP_TC_HPD_ENABLE_MASK); } @@ -3169,8 +3174,8 @@ static void spt_hpd_irq_setup(struct drm_i915_private *dev_priv) if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) I915_WRITE(SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); - hotplug_irqs = SDE_HOTPLUG_MASK_SPT; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.pch_hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.pch_hpd); ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs); @@ -3197,22 +3202,13 @@ static void ilk_hpd_irq_setup(struct drm_i915_private *dev_priv) { u32 hotplug_irqs, enabled_irqs; - if (INTEL_GEN(dev_priv) >= 8) { - hotplug_irqs = GEN8_PORT_DP_A_HOTPLUG; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); + enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); + if (INTEL_GEN(dev_priv) >= 8) bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); - } else if (INTEL_GEN(dev_priv) >= 7) { - hotplug_irqs = DE_DP_A_HOTPLUG_IVB; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - - ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); - } else { - hotplug_irqs = DE_DP_A_HOTPLUG; - enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - + else ilk_update_display_irq(dev_priv, hotplug_irqs, enabled_irqs); - } ilk_hpd_detection_setup(dev_priv); @@ -3261,7 +3257,7 @@ static void bxt_hpd_irq_setup(struct drm_i915_private *dev_priv) u32 hotplug_irqs, enabled_irqs; enabled_irqs = intel_hpd_enabled_irqs(dev_priv, dev_priv->hotplug.hpd); - hotplug_irqs = BXT_DE_PORT_HOTPLUG_MASK; + hotplug_irqs = intel_hpd_hotplug_irqs(dev_priv, dev_priv->hotplug.hpd); bdw_update_port_irq(dev_priv, hotplug_irqs, enabled_irqs); -- GitLab From e198eea948a0f12630cf7a8d12fe30d257c9339d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 1 Jul 2020 00:56:01 +0300 Subject: [PATCH 1113/1494] drm/i915: Nuke pointless variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in assigning the function return value to a local variable if we're just going to use it the one time. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200630215601.28557-13-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza <jose.souza@intel.com> --- drivers/gpu/drm/i915/display/intel_hotplug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index f3dbf2bd80107..5c58c1ed6493c 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -482,7 +482,6 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, * only the one of them (DP) will have ->hpd_pulse(). */ for_each_intel_encoder(&dev_priv->drm, encoder) { - bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder); enum port port = encoder->port; bool long_hpd; @@ -490,7 +489,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv, if (!(BIT(pin) & pin_mask)) continue; - if (!has_hpd_pulse) + if (!intel_encoder_has_hpd_pulse(encoder)) continue; long_hpd = long_mask & BIT(pin); -- GitLab From 8907afb476ac6754a4d1ba8d2dd16dbb0fd4d428 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 14 Sep 2020 16:40:21 -0600 Subject: [PATCH 1114/1494] drm/msm: Allow a5xx to mark the RPTR shadow as privileged Newer microcode versions have support for the CP_WHERE_AM_I opcode which allows the RPTR shadow memory to be marked as privileged to protect it from corruption. Move the RPTR shadow into its own buffer and protect it it if the current microcode version supports the new feature. We can also re-enable preemption for those targets that support CP_WHERE_AM_I. Start out by preemptively assuming that we can enable preemption and disable it in a5xx_hw_init if the microcode version comes back as too old. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 96 ++++++++++++++++++--- drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 12 +++ drivers/gpu/drm/msm/adreno/a5xx_power.c | 2 +- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 5 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 5 ++ drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h | 1 + drivers/gpu/drm/msm/msm_gpu.h | 1 + 7 files changed, 109 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 616d9e7980588..835aaef72b00d 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -18,13 +18,24 @@ static void a5xx_dump(struct msm_gpu *gpu); #define GPU_PAS_ID 13 -static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, + bool sync) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); uint32_t wptr; unsigned long flags; + /* + * Most flush operations need to issue a WHERE_AM_I opcode to sync up + * the rptr shadow + */ + if (a5xx_gpu->has_whereami && sync) { + OUT_PKT7(ring, CP_WHERE_AM_I, 2); + OUT_RING(ring, lower_32_bits(shadowptr(a5xx_gpu, ring))); + OUT_RING(ring, upper_32_bits(shadowptr(a5xx_gpu, ring))); + } + spin_lock_irqsave(&ring->lock, flags); /* Copy the shadow to the actual register */ @@ -90,7 +101,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit } } - a5xx_flush(gpu, ring); + a5xx_flush(gpu, ring, true); a5xx_preempt_trigger(gpu); /* we might not necessarily have a cmd from userspace to @@ -204,7 +215,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) /* Set bit 0 to trigger an interrupt on preempt complete */ OUT_RING(ring, 0x01); - a5xx_flush(gpu, ring); + /* A WHERE_AM_I packet is not needed after a YIELD */ + a5xx_flush(gpu, ring, false); /* Check to see if we need to start preemption */ a5xx_preempt_trigger(gpu); @@ -363,7 +375,7 @@ static int a5xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu, ring); + a5xx_flush(gpu, ring, true); return a5xx_idle(gpu, ring) ? 0 : -EINVAL; } @@ -405,11 +417,31 @@ static int a5xx_preempt_start(struct msm_gpu *gpu) OUT_RING(ring, 0x01); OUT_RING(ring, 0x01); - gpu->funcs->flush(gpu, ring); + /* The WHERE_AMI_I packet is not needed after a YIELD is issued */ + a5xx_flush(gpu, ring, false); return a5xx_idle(gpu, ring) ? 0 : -EINVAL; } +static void a5xx_ucode_check_version(struct a5xx_gpu *a5xx_gpu, + struct drm_gem_object *obj) +{ + u32 *buf = msm_gem_get_vaddr_active(obj); + + if (IS_ERR(buf)) + return; + + /* + * If the lowest nibble is 0xa that is an indication that this microcode + * has been patched. The actual version is in dword [3] but we only care + * about the patchlevel which is the lowest nibble of dword [3] + */ + if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) + a5xx_gpu->has_whereami = true; + + msm_gem_put_vaddr(obj); +} + static int a5xx_ucode_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -445,6 +477,7 @@ static int a5xx_ucode_init(struct msm_gpu *gpu) } msm_gem_object_set_name(a5xx_gpu->pfp_bo, "pfpfw"); + a5xx_ucode_check_version(a5xx_gpu, a5xx_gpu->pfp_bo); } gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO, @@ -504,6 +537,7 @@ static int a5xx_zap_shader_init(struct msm_gpu *gpu) static int a5xx_hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); int ret; gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003); @@ -712,9 +746,36 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI, gpu->rb[0]->iova); + /* + * If the microcode supports the WHERE_AM_I opcode then we can use that + * in lieu of the RPTR shadow and enable preemption. Otherwise, we + * can't safely use the RPTR shadow or preemption. In either case, the + * RPTR shadow should be disabled in hardware. + */ gpu_write(gpu, REG_A5XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + /* Disable preemption if WHERE_AM_I isn't available */ + if (!a5xx_gpu->has_whereami && gpu->nr_rings > 1) { + a5xx_preempt_fini(gpu); + gpu->nr_rings = 1; + } else { + /* Create a privileged buffer for the RPTR shadow */ + if (!a5xx_gpu->shadow_bo) { + a5xx_gpu->shadow = msm_gem_kernel_new(gpu->dev, + sizeof(u32) * gpu->nr_rings, + MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, + gpu->aspace, &a5xx_gpu->shadow_bo, + &a5xx_gpu->shadow_iova); + + if (IS_ERR(a5xx_gpu->shadow)) + return PTR_ERR(a5xx_gpu->shadow); + } + + gpu_write64(gpu, REG_A5XX_CP_RB_RPTR_ADDR, + REG_A5XX_CP_RB_RPTR_ADDR_HI, shadowptr(a5xx_gpu, gpu->rb[0])); + } + a5xx_preempt_hw_init(gpu); /* Disable the interrupts through the initial bringup stage */ @@ -738,7 +799,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) OUT_PKT7(gpu->rb[0], CP_EVENT_WRITE, 1); OUT_RING(gpu->rb[0], CP_EVENT_WRITE_0_EVENT(STAT_EVENT)); - gpu->funcs->flush(gpu, gpu->rb[0]); + a5xx_flush(gpu, gpu->rb[0], true); if (!a5xx_idle(gpu, gpu->rb[0])) return -EINVAL; } @@ -756,7 +817,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1); OUT_RING(gpu->rb[0], 0x00000000); - gpu->funcs->flush(gpu, gpu->rb[0]); + a5xx_flush(gpu, gpu->rb[0], true); if (!a5xx_idle(gpu, gpu->rb[0])) return -EINVAL; } else if (ret == -ENODEV) { @@ -823,6 +884,11 @@ static void a5xx_destroy(struct msm_gpu *gpu) drm_gem_object_put(a5xx_gpu->gpmu_bo); } + if (a5xx_gpu->shadow_bo) { + msm_gem_unpin_iova(a5xx_gpu->shadow_bo, gpu->aspace); + drm_gem_object_put(a5xx_gpu->shadow_bo); + } + adreno_gpu_cleanup(adreno_gpu); kfree(a5xx_gpu); } @@ -1430,6 +1496,17 @@ static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu) return (unsigned long)busy_time; } +static uint32_t a5xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + + if (a5xx_gpu->has_whereami) + return a5xx_gpu->shadow[ring->id]; + + 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, @@ -1438,7 +1515,6 @@ static const struct adreno_gpu_funcs funcs = { .pm_resume = a5xx_pm_resume, .recover = a5xx_recover, .submit = a5xx_submit, - .flush = a5xx_flush, .active_ring = a5xx_active_ring, .irq = a5xx_irq, .destroy = a5xx_destroy, @@ -1452,6 +1528,7 @@ static const struct adreno_gpu_funcs funcs = { .gpu_state_get = a5xx_gpu_state_get, .gpu_state_put = a5xx_gpu_state_put, .create_address_space = adreno_iommu_create_address_space, + .get_rptr = a5xx_get_rptr, }, .get_timestamp = a5xx_get_timestamp, }; @@ -1516,8 +1593,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) check_speed_bin(&pdev->dev); - /* Restricting nr_rings to 1 to temporarily disable preemption */ - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); if (ret) { a5xx_destroy(&(a5xx_gpu->base.base)); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index 1e5b1a15a70f0..c7187bcc5e908 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -37,6 +37,13 @@ struct a5xx_gpu { atomic_t preempt_state; struct timer_list preempt_timer; + + struct drm_gem_object *shadow_bo; + uint64_t shadow_iova; + uint32_t *shadow; + + /* True if the microcode supports the WHERE_AM_I opcode */ + bool has_whereami; }; #define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base) @@ -141,6 +148,9 @@ static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs, return -ETIMEDOUT; } +#define shadowptr(a5xx_gpu, ring) ((a5xx_gpu)->shadow_iova + \ + ((ring)->id * sizeof(uint32_t))) + bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring); void a5xx_set_hwcg(struct msm_gpu *gpu, bool state); @@ -150,6 +160,8 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu); void a5xx_preempt_irq(struct msm_gpu *gpu); void a5xx_preempt_fini(struct msm_gpu *gpu); +void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, bool sync); + /* Return true if we are in a preempt state */ static inline bool a5xx_in_preempt(struct a5xx_gpu *a5xx_gpu) { diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 321a8061fd325..f176a6f3eff66 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -240,7 +240,7 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu) OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); OUT_RING(ring, 1); - gpu->funcs->flush(gpu, ring); + a5xx_flush(gpu, ring, true); if (!a5xx_idle(gpu, ring)) { DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n", diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 9f3fe177b00e9..7e04509c4e1f0 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -259,8 +259,9 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr->magic = A5XX_PREEMPT_RECORD_MAGIC; ptr->info = 0; ptr->data = 0; - ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; - ptr->rptr_addr = rbmemptr(ring, rptr); + ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE; + + ptr->rptr_addr = shadowptr(a5xx_gpu, ring); ptr->counter = counters_iova; return 0; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index a833dd0ab7516..11635e39ca196 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -422,6 +422,11 @@ int adreno_hw_init(struct msm_gpu *gpu) static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, struct msm_ringbuffer *ring) { + struct msm_gpu *gpu = &adreno_gpu->base; + + if (gpu->funcs->get_rptr) + return gpu->funcs->get_rptr(gpu, ring); + return ring->memptrs->rptr = adreno_gpu_read( adreno_gpu, REG_ADRENO_CP_RB_RPTR); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h index 3931eecadaff8..59bb8c1ffce66 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h +++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h @@ -298,6 +298,7 @@ enum adreno_pm4_type3_packets { CP_SET_BIN_DATA5_OFFSET = 46, CP_SET_CTXSWITCH_IB = 85, CP_REG_WRITE = 109, + CP_WHERE_AM_I = 98, }; enum adreno_state_block { diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 5ee358b480e6e..6c9e1fdc1a762 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -68,6 +68,7 @@ struct msm_gpu_funcs { (struct msm_gpu *gpu, struct platform_device *pdev); struct msm_gem_address_space *(*create_private_address_space) (struct msm_gpu *gpu); + uint32_t (*get_rptr)(struct msm_gpu *gpu, struct msm_ringbuffer *ring); }; struct msm_gpu { -- GitLab From d3a569fccfa087ac685b17fc378547846891e7b4 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 14 Sep 2020 16:40:22 -0600 Subject: [PATCH 1115/1494] drm/msm: a6xx: Use WHERE_AM_I for eligible targets Support the WHERE_AM_I opcode for the A618, A630 and A640 GPUs if the microcode supports it. The WHERE_AM_I opcode allows the RPTR shadow to be updated in priviliged memory which protects the shadow from being read or written from user submissions. A650 already supports extended APRIV have built in hardware support for to access privilged memory from the CP and can go back to using the hardware RPTR shadow feature. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 87 ++++++++++++++++++++++++++- drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 9 +++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index a3a8d6fd06bbf..9cce2b01b1a7c 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -51,9 +51,20 @@ bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) static 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); uint32_t wptr; unsigned long flags; + /* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */ + if (a6xx_gpu->has_whereami && !adreno_gpu->base.hw_apriv) { + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + OUT_PKT7(ring, CP_WHERE_AM_I, 2); + OUT_RING(ring, lower_32_bits(shadowptr(a6xx_gpu, ring))); + OUT_RING(ring, upper_32_bits(shadowptr(a6xx_gpu, ring))); + } + spin_lock_irqsave(&ring->lock, flags); /* Copy the shadow to the actual register */ @@ -508,6 +519,30 @@ static int a6xx_cp_init(struct msm_gpu *gpu) return a6xx_idle(gpu, ring) ? 0 : -EINVAL; } +static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, + struct drm_gem_object *obj) +{ + u32 *buf = msm_gem_get_vaddr_active(obj); + + if (IS_ERR(buf)) + return; + + /* + * If the lowest nibble is 0xa that is an indication that this microcode + * has been patched. The actual version is in dword [3] but we only care + * about the patchlevel which is the lowest nibble of dword [3] + * + * Otherwise check that the firmware is greater than or equal to 1.90 + * which was the first version that had this fix built in + */ + if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) + a6xx_gpu->has_whereami = true; + else if ((buf[0] & 0xfff) > 0x190) + a6xx_gpu->has_whereami = true; + + msm_gem_put_vaddr(obj); +} + static int a6xx_ucode_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -528,6 +563,7 @@ static int a6xx_ucode_init(struct msm_gpu *gpu) } msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw"); + a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo); } gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO, @@ -743,8 +779,37 @@ static int a6xx_hw_init(struct msm_gpu *gpu) gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI, gpu->rb[0]->iova); - gpu_write(gpu, REG_A6XX_CP_RB_CNTL, - MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + /* Targets that support extended APRIV can use the RPTR shadow from + * hardware but all the other ones need to disable the feature. Targets + * that support the WHERE_AM_I opcode can use that instead + */ + if (adreno_gpu->base.hw_apriv) + gpu_write(gpu, REG_A6XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT); + else + gpu_write(gpu, REG_A6XX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + + /* + * Expanded APRIV and targets that support WHERE_AM_I both need a + * privileged buffer to store the RPTR shadow + */ + + if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) { + if (!a6xx_gpu->shadow_bo) { + a6xx_gpu->shadow = msm_gem_kernel_new_locked(gpu->dev, + sizeof(u32) * gpu->nr_rings, + MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, + gpu->aspace, &a6xx_gpu->shadow_bo, + &a6xx_gpu->shadow_iova); + + if (IS_ERR(a6xx_gpu->shadow)) + return PTR_ERR(a6xx_gpu->shadow); + } + + gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR_LO, + REG_A6XX_CP_RB_RPTR_ADDR_HI, + shadowptr(a6xx_gpu, gpu->rb[0])); + } /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; @@ -1033,6 +1098,11 @@ static void a6xx_destroy(struct msm_gpu *gpu) drm_gem_object_put(a6xx_gpu->sqe_bo); } + if (a6xx_gpu->shadow_bo) { + msm_gem_unpin_iova(a6xx_gpu->shadow_bo, gpu->aspace); + drm_gem_object_put(a6xx_gpu->shadow_bo); + } + a6xx_gmu_remove(a6xx_gpu); adreno_gpu_cleanup(adreno_gpu); @@ -1081,6 +1151,17 @@ a6xx_create_private_address_space(struct msm_gpu *gpu) "gpu", 0x100000000ULL, 0x1ffffffffULL); } +static uint32_t a6xx_get_rptr(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); + + if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) + return a6xx_gpu->shadow[ring->id]; + + return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR); +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -1089,7 +1170,6 @@ static const struct adreno_gpu_funcs funcs = { .pm_resume = a6xx_pm_resume, .recover = a6xx_recover, .submit = a6xx_submit, - .flush = a6xx_flush, .active_ring = a6xx_active_ring, .irq = a6xx_irq, .destroy = a6xx_destroy, @@ -1105,6 +1185,7 @@ static const struct adreno_gpu_funcs funcs = { #endif .create_address_space = adreno_iommu_create_address_space, .create_private_address_space = a6xx_create_private_address_space, + .get_rptr = a6xx_get_rptr, }, .get_timestamp = a6xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index da22d7549d9b4..3eeebf6a754b9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -22,6 +22,12 @@ struct a6xx_gpu { struct msm_file_private *cur_ctx; struct a6xx_gmu gmu; + + struct drm_gem_object *shadow_bo; + uint64_t shadow_iova; + uint32_t *shadow; + + bool has_whereami; }; #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base) @@ -51,6 +57,9 @@ static inline bool a6xx_has_gbif(struct adreno_gpu *gpu) return true; } +#define shadowptr(_a6xx_gpu, _ring) ((_a6xx_gpu)->shadow_iova + \ + ((_ring)->id * sizeof(uint32_t))) + int a6xx_gmu_resume(struct a6xx_gpu *gpu); int a6xx_gmu_stop(struct a6xx_gpu *gpu); -- GitLab From 2fb7487aaf71071e02986ccd9c981ba1a790880e Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Mon, 14 Sep 2020 16:40:23 -0600 Subject: [PATCH 1116/1494] drm/msm: Get rid of the REG_ADRENO offsets As newer GPU families are added it makes less sense to maintain a "generic" version functions for older families. Move adreno_submit() and get_rptr() into the target specific code for a2xx, a3xx and a4xx. Add a parameter to adreno_flush to pass the target specific WPTR register instead of relying on the generic register. All of this gets rid of the last of the REG_ADRENO offsets so remove all all the register definitions and infrastructure. Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 65 +++++++++++++++----- drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 77 ++++++++++++++++++----- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 82 ++++++++++++++++++------- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 12 ---- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 13 ---- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 82 +------------------------ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 81 +----------------------- 7 files changed, 178 insertions(+), 234 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 48fa49f69d6d0..7e82c41a85f1a 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -10,6 +10,48 @@ extern bool hang_debug; static void a2xx_dump(struct msm_gpu *gpu); static bool a2xx_idle(struct msm_gpu *gpu); +static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) +{ + struct msm_drm_private *priv = gpu->dev->dev_private; + struct msm_ringbuffer *ring = submit->ring; + unsigned int i; + + for (i = 0; i < submit->nr_cmds; i++) { + switch (submit->cmd[i].type) { + case MSM_SUBMIT_CMD_IB_TARGET_BUF: + /* ignore IB-targets */ + break; + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: + /* ignore if there has not been a ctx switch: */ + if (priv->lastctx == submit->queue->ctx) + break; + fallthrough; + case MSM_SUBMIT_CMD_BUF: + OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2); + OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); + OUT_RING(ring, submit->cmd[i].size); + OUT_PKT2(ring); + break; + } + } + + OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); + OUT_RING(ring, submit->seqno); + + /* wait for idle before cache flush/interrupt */ + OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); + OUT_RING(ring, 0x00000000); + + OUT_PKT3(ring, CP_EVENT_WRITE, 3); + OUT_RING(ring, CACHE_FLUSH_TS); + OUT_RING(ring, rbmemptr(ring, fence)); + OUT_RING(ring, submit->seqno); + OUT_PKT3(ring, CP_INTERRUPT, 1); + OUT_RING(ring, 0x80000000); + + adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); +} + static bool a2xx_me_init(struct msm_gpu *gpu) { struct msm_ringbuffer *ring = gpu->rb[0]; @@ -53,7 +95,7 @@ static bool a2xx_me_init(struct msm_gpu *gpu) OUT_PKT3(ring, CP_SET_PROTECTED_MODE, 1); OUT_RING(ring, 1); - gpu->funcs->flush(gpu, ring); + adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); return a2xx_idle(gpu); } @@ -421,16 +463,11 @@ a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev) return aspace; } -/* Register offset defines for A2XX - copy of A3XX */ -static const unsigned int a2xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL), -}; +static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR); + return ring->memptrs->rptr; +} static const struct adreno_gpu_funcs funcs = { .base = { @@ -439,8 +476,7 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = msm_gpu_pm_suspend, .pm_resume = msm_gpu_pm_resume, .recover = a2xx_recover, - .submit = adreno_submit, - .flush = adreno_flush, + .submit = a2xx_submit, .active_ring = adreno_active_ring, .irq = a2xx_irq, .destroy = a2xx_destroy, @@ -450,6 +486,7 @@ static const struct adreno_gpu_funcs funcs = { .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, }, }; @@ -491,8 +528,6 @@ struct msm_gpu *a2xx_gpu_init(struct drm_device *dev) else adreno_gpu->registers = a220_registers; - adreno_gpu->reg_offsets = a2xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index f6471145a7a60..f29c77d9cd42d 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -28,6 +28,61 @@ extern bool hang_debug; static void a3xx_dump(struct msm_gpu *gpu); static bool a3xx_idle(struct msm_gpu *gpu); +static void a3xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) +{ + struct msm_drm_private *priv = gpu->dev->dev_private; + struct msm_ringbuffer *ring = submit->ring; + unsigned int i; + + for (i = 0; i < submit->nr_cmds; i++) { + switch (submit->cmd[i].type) { + case MSM_SUBMIT_CMD_IB_TARGET_BUF: + /* ignore IB-targets */ + break; + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: + /* ignore if there has not been a ctx switch: */ + if (priv->lastctx == submit->queue->ctx) + break; + fallthrough; + case MSM_SUBMIT_CMD_BUF: + OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFD, 2); + OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); + OUT_RING(ring, submit->cmd[i].size); + OUT_PKT2(ring); + break; + } + } + + OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); + OUT_RING(ring, submit->seqno); + + /* Flush HLSQ lazy updates to make sure there is nothing + * pending for indirect loads after the timestamp has + * passed: + */ + OUT_PKT3(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, HLSQ_FLUSH); + + /* wait for idle before cache flush/interrupt */ + OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); + OUT_RING(ring, 0x00000000); + + /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ + OUT_PKT3(ring, CP_EVENT_WRITE, 3); + OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); + OUT_RING(ring, rbmemptr(ring, fence)); + OUT_RING(ring, submit->seqno); + +#if 0 + /* Dummy set-constant to trigger context rollover */ + OUT_PKT3(ring, CP_SET_CONSTANT, 2); + OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG)); + OUT_RING(ring, 0x00000000); +#endif + + adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); +} + static bool a3xx_me_init(struct msm_gpu *gpu) { struct msm_ringbuffer *ring = gpu->rb[0]; @@ -51,7 +106,7 @@ static bool a3xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu, ring); + adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR); return a3xx_idle(gpu); } @@ -423,16 +478,11 @@ static struct msm_gpu_state *a3xx_gpu_state_get(struct msm_gpu *gpu) return state; } -/* Register offset defines for A3XX */ -static const unsigned int a3xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL), -}; +static u32 a3xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR); + return ring->memptrs->rptr; +} static const struct adreno_gpu_funcs funcs = { .base = { @@ -441,8 +491,7 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = msm_gpu_pm_suspend, .pm_resume = msm_gpu_pm_resume, .recover = a3xx_recover, - .submit = adreno_submit, - .flush = adreno_flush, + .submit = a3xx_submit, .active_ring = adreno_active_ring, .irq = a3xx_irq, .destroy = a3xx_destroy, @@ -452,6 +501,7 @@ static const struct adreno_gpu_funcs funcs = { .gpu_state_get = a3xx_gpu_state_get, .gpu_state_put = adreno_gpu_state_put, .create_address_space = adreno_iommu_create_address_space, + .get_rptr = a3xx_get_rptr, }, }; @@ -490,7 +540,6 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); adreno_gpu->registers = a3xx_registers; - adreno_gpu->reg_offsets = a3xx_register_offsets; ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 9547536006254..2b93b33b05e45 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -22,6 +22,54 @@ extern bool hang_debug; static void a4xx_dump(struct msm_gpu *gpu); static bool a4xx_idle(struct msm_gpu *gpu); +static void a4xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) +{ + struct msm_drm_private *priv = gpu->dev->dev_private; + struct msm_ringbuffer *ring = submit->ring; + unsigned int i; + + for (i = 0; i < submit->nr_cmds; i++) { + switch (submit->cmd[i].type) { + case MSM_SUBMIT_CMD_IB_TARGET_BUF: + /* ignore IB-targets */ + break; + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: + /* ignore if there has not been a ctx switch: */ + if (priv->lastctx == submit->queue->ctx) + break; + fallthrough; + case MSM_SUBMIT_CMD_BUF: + OUT_PKT3(ring, CP_INDIRECT_BUFFER_PFE, 2); + OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); + OUT_RING(ring, submit->cmd[i].size); + OUT_PKT2(ring); + break; + } + } + + OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); + OUT_RING(ring, submit->seqno); + + /* Flush HLSQ lazy updates to make sure there is nothing + * pending for indirect loads after the timestamp has + * passed: + */ + OUT_PKT3(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, HLSQ_FLUSH); + + /* wait for idle before cache flush/interrupt */ + OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); + OUT_RING(ring, 0x00000000); + + /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ + OUT_PKT3(ring, CP_EVENT_WRITE, 3); + OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); + OUT_RING(ring, rbmemptr(ring, fence)); + OUT_RING(ring, submit->seqno); + + adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); +} + /* * a4xx_enable_hwcg() - Program the clock control registers * @device: The adreno device pointer @@ -129,7 +177,7 @@ static bool a4xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu, ring); + adreno_flush(gpu, ring, REG_A4XX_CP_RB_WPTR); return a4xx_idle(gpu); } @@ -515,17 +563,6 @@ static struct msm_gpu_state *a4xx_gpu_state_get(struct msm_gpu *gpu) return state; } -/* Register offset defines for A4XX, in order of enum adreno_regs */ -static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR), - REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL), -}; - static void a4xx_dump(struct msm_gpu *gpu) { printk("status: %08x\n", @@ -576,6 +613,12 @@ static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) return 0; } +static u32 a4xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + ring->memptrs->rptr = gpu_read(gpu, REG_A4XX_CP_RB_RPTR); + return ring->memptrs->rptr; +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -583,8 +626,7 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = a4xx_pm_suspend, .pm_resume = a4xx_pm_resume, .recover = a4xx_recover, - .submit = adreno_submit, - .flush = adreno_flush, + .submit = a4xx_submit, .active_ring = adreno_active_ring, .irq = a4xx_irq, .destroy = a4xx_destroy, @@ -594,6 +636,7 @@ static const struct adreno_gpu_funcs funcs = { .gpu_state_get = a4xx_gpu_state_get, .gpu_state_put = adreno_gpu_state_put, .create_address_space = adreno_iommu_create_address_space, + .get_rptr = a4xx_get_rptr, }, .get_timestamp = a4xx_get_timestamp, }; @@ -631,15 +674,12 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = adreno_is_a405(adreno_gpu) ? a405_registers : a4xx_registers; - adreno_gpu->reg_offsets = a4xx_register_offsets; /* if needed, allocate gmem: */ - if (adreno_is_a4xx(adreno_gpu)) { - ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu, - &a4xx_gpu->ocmem); - if (ret) - goto fail; - } + ret = adreno_gpu_ocmem_init(dev->dev, adreno_gpu, + &a4xx_gpu->ocmem); + if (ret) + goto fail; if (!gpu->aspace) { /* TODO we think it is possible to configure the GPU to diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 835aaef72b00d..c941c8138f257 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1121,17 +1121,6 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) return IRQ_HANDLED; } -static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI, - REG_A5XX_CP_RB_RPTR_ADDR_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL), -}; - static const u32 a5xx_registers[] = { 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B, 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095, @@ -1587,7 +1576,6 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) gpu = &adreno_gpu->base; adreno_gpu->registers = a5xx_registers; - adreno_gpu->reg_offsets = a5xx_register_offsets; a5xx_gpu->lm_leakage = 0x4E001A; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 9cce2b01b1a7c..3248c89aa0010 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1022,18 +1022,6 @@ static irqreturn_t a6xx_irq(struct msm_gpu *gpu) return IRQ_HANDLED; } -static const u32 a6xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A6XX_CP_RB_BASE), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A6XX_CP_RB_BASE_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, - REG_A6XX_CP_RB_RPTR_ADDR_LO), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI, - REG_A6XX_CP_RB_RPTR_ADDR_HI), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A6XX_CP_RB_RPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A6XX_CP_RB_WPTR), - REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A6XX_CP_RB_CNTL), -}; - static int a6xx_pm_resume(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -1208,7 +1196,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) gpu = &adreno_gpu->base; adreno_gpu->registers = NULL; - adreno_gpu->reg_offsets = a6xx_register_offsets; if (adreno_is_a650(adreno_gpu)) adreno_gpu->base.hw_apriv = true; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 11635e39ca196..fd8f491f2e48e 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -424,11 +424,7 @@ static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, { struct msm_gpu *gpu = &adreno_gpu->base; - if (gpu->funcs->get_rptr) - return gpu->funcs->get_rptr(gpu, ring); - - return ring->memptrs->rptr = adreno_gpu_read( - adreno_gpu, REG_ADRENO_CP_RB_RPTR); + return gpu->funcs->get_rptr(gpu, ring); } struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu) @@ -454,80 +450,8 @@ void adreno_recover(struct msm_gpu *gpu) } } -void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) +void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, u32 reg) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - struct msm_drm_private *priv = gpu->dev->dev_private; - struct msm_ringbuffer *ring = submit->ring; - unsigned i; - - for (i = 0; i < submit->nr_cmds; i++) { - switch (submit->cmd[i].type) { - case MSM_SUBMIT_CMD_IB_TARGET_BUF: - /* ignore IB-targets */ - break; - case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: - /* ignore if there has not been a ctx switch: */ - if (priv->lastctx == submit->queue->ctx) - break; - /* fall-thru */ - case MSM_SUBMIT_CMD_BUF: - OUT_PKT3(ring, adreno_is_a4xx(adreno_gpu) ? - CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2); - OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); - OUT_RING(ring, submit->cmd[i].size); - OUT_PKT2(ring); - break; - } - } - - OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); - OUT_RING(ring, submit->seqno); - - if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { - /* Flush HLSQ lazy updates to make sure there is nothing - * pending for indirect loads after the timestamp has - * passed: - */ - OUT_PKT3(ring, CP_EVENT_WRITE, 1); - OUT_RING(ring, HLSQ_FLUSH); - } - - /* wait for idle before cache flush/interrupt */ - OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1); - OUT_RING(ring, 0x00000000); - - if (!adreno_is_a2xx(adreno_gpu)) { - /* BIT(31) of CACHE_FLUSH_TS triggers CACHE_FLUSH_TS IRQ from GPU */ - OUT_PKT3(ring, CP_EVENT_WRITE, 3); - OUT_RING(ring, CACHE_FLUSH_TS | BIT(31)); - OUT_RING(ring, rbmemptr(ring, fence)); - OUT_RING(ring, submit->seqno); - } else { - /* BIT(31) means something else on a2xx */ - OUT_PKT3(ring, CP_EVENT_WRITE, 3); - OUT_RING(ring, CACHE_FLUSH_TS); - OUT_RING(ring, rbmemptr(ring, fence)); - OUT_RING(ring, submit->seqno); - OUT_PKT3(ring, CP_INTERRUPT, 1); - OUT_RING(ring, 0x80000000); - } - -#if 0 - if (adreno_is_a3xx(adreno_gpu)) { - /* Dummy set-constant to trigger context rollover */ - OUT_PKT3(ring, CP_SET_CONSTANT, 2); - OUT_RING(ring, CP_REG(REG_A3XX_HLSQ_CL_KERNEL_GROUP_X_REG)); - OUT_RING(ring, 0x00000000); - } -#endif - - gpu->funcs->flush(gpu, ring); -} - -void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) -{ - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); uint32_t wptr; /* Copy the shadow to the actual register */ @@ -543,7 +467,7 @@ void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) /* ensure writes to ringbuffer have hit system memory: */ mb(); - adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr); + gpu_write(gpu, reg, wptr); } bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 848632758450c..c3775f79525a7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -17,29 +17,8 @@ #include "adreno_common.xml.h" #include "adreno_pm4.xml.h" -#define REG_ADRENO_DEFINE(_offset, _reg) [_offset] = (_reg) + 1 -#define REG_SKIP ~0 -#define REG_ADRENO_SKIP(_offset) [_offset] = REG_SKIP - extern bool snapshot_debugbus; -/** - * adreno_regs: List of registers that are used in across all - * 3D devices. Each device type has different offset value for the same - * register, so an array of register offsets are declared for every device - * and are indexed by the enumeration values defined in this enum - */ -enum adreno_regs { - REG_ADRENO_CP_RB_BASE, - REG_ADRENO_CP_RB_BASE_HI, - REG_ADRENO_CP_RB_RPTR_ADDR, - REG_ADRENO_CP_RB_RPTR_ADDR_HI, - REG_ADRENO_CP_RB_RPTR, - REG_ADRENO_CP_RB_WPTR, - REG_ADRENO_CP_RB_CNTL, - REG_ADRENO_REGISTER_MAX, -}; - enum { ADRENO_FW_PM4 = 0, ADRENO_FW_SQE = 0, /* a6xx */ @@ -176,11 +155,6 @@ static inline bool adreno_is_a225(struct adreno_gpu *gpu) return gpu->revn == 225; } -static inline bool adreno_is_a3xx(struct adreno_gpu *gpu) -{ - return (gpu->revn >= 300) && (gpu->revn < 400); -} - static inline bool adreno_is_a305(struct adreno_gpu *gpu) { return gpu->revn == 305; @@ -207,11 +181,6 @@ static inline bool adreno_is_a330v2(struct adreno_gpu *gpu) return adreno_is_a330(gpu) && (gpu->rev.patchid > 0); } -static inline bool adreno_is_a4xx(struct adreno_gpu *gpu) -{ - return (gpu->revn >= 400) && (gpu->revn < 500); -} - static inline int adreno_is_a405(struct adreno_gpu *gpu) { return gpu->revn == 405; @@ -269,8 +238,7 @@ struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova); int adreno_hw_init(struct msm_gpu *gpu); void adreno_recover(struct msm_gpu *gpu); -void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit); -void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring); +void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, u32 reg); bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring); #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, @@ -364,59 +332,12 @@ OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23)); } -/* - * adreno_reg_check() - Checks the validity of a register enum - * @gpu: Pointer to struct adreno_gpu - * @offset_name: The register enum that is checked - */ -static inline bool adreno_reg_check(struct adreno_gpu *gpu, - enum adreno_regs offset_name) -{ - BUG_ON(offset_name >= REG_ADRENO_REGISTER_MAX || !gpu->reg_offsets[offset_name]); - - /* - * REG_SKIP is a special value that tell us that the register in - * question isn't implemented on target but don't trigger a BUG(). This - * is used to cleanly implement adreno_gpu_write64() and - * adreno_gpu_read64() in a generic fashion - */ - if (gpu->reg_offsets[offset_name] == REG_SKIP) - return false; - - return true; -} - -static inline u32 adreno_gpu_read(struct adreno_gpu *gpu, - enum adreno_regs offset_name) -{ - u32 reg = gpu->reg_offsets[offset_name]; - u32 val = 0; - if(adreno_reg_check(gpu,offset_name)) - val = gpu_read(&gpu->base, reg - 1); - return val; -} - -static inline void adreno_gpu_write(struct adreno_gpu *gpu, - enum adreno_regs offset_name, u32 data) -{ - u32 reg = gpu->reg_offsets[offset_name]; - if(adreno_reg_check(gpu, offset_name)) - gpu_write(&gpu->base, reg - 1, data); -} - 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 void adreno_gpu_write64(struct adreno_gpu *gpu, - enum adreno_regs lo, enum adreno_regs hi, u64 data) -{ - adreno_gpu_write(gpu, lo, lower_32_bits(data)); - adreno_gpu_write(gpu, hi, upper_32_bits(data)); -} - static inline uint32_t get_wptr(struct msm_ringbuffer *ring) { return (ring->cur - ring->start) % (MSM_GPU_RINGBUFFER_SZ >> 2); -- GitLab From b22960b8f274382ff165db50faebbde5f8a16c32 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju <chandanu@codeaurora.org> Date: Thu, 27 Aug 2020 14:16:54 -0700 Subject: [PATCH 1117/1494] drm: add constant N value in helper file The constant N value (0x8000) is used by i915 DP driver. Define this value in dp helper header file to use in multiple Display Port drivers. Change i915 driver accordingly. Change in v6: Change commit message Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> Signed-off-by: Vara Reddy <varar@codeaurora.org> Signed-off-by: Tanmay Shah <tanmay@codeaurora.org> Reviewed-by: Stephen Boyd <swboyd@chromium.org> Acked-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- include/drm/drm_dp_helper.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 729ec6e0d43a0..10b8310f290b2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8114,7 +8114,7 @@ static void compute_m_n(unsigned int m, unsigned int n, * which the devices expect also in synchronous clock mode. */ if (constant_n) - *ret_n = 0x8000; + *ret_n = DP_LINK_CONSTANT_N_VALUE; else *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index e47dc22ebf503..a31d7aebb8b85 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1134,6 +1134,7 @@ #define DP_MST_PHYSICAL_PORT_0 0 #define DP_MST_LOGICAL_PORT_0 8 +#define DP_LINK_CONSTANT_N_VALUE 0x8000 #define DP_LINK_STATUS_SIZE 6 bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], int lane_count); -- GitLab From c943b4948b5848fc0e07f875edbd35a973879e22 Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju <chandanu@codeaurora.org> Date: Thu, 27 Aug 2020 14:16:55 -0700 Subject: [PATCH 1118/1494] drm/msm/dp: add displayPort driver support Add the needed displayPort files to enable DP driver on msm target. "dp_display" module is the main module that calls into other sub-modules. "dp_drm" file represents the interface between DRM framework and DP driver. Changes in v12: -- Add support of pm ops in display port driver -- Clear bpp depth bits before writing to MISC register -- Fix edid read Previous Change log: https://lkml.kernel.org/lkml/20200818051137.21478-3-tanmay@codeaurora.org/ Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> Signed-off-by: Vara Reddy <varar@codeaurora.org> Signed-off-by: Tanmay Shah <tanmay@codeaurora.org> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Co-developed-by: Kuogee Hsieh <khsieh@codeaurora.org> Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> Co-developed-by: Guenter Roeck <groeck@chromium.org> Signed-off-by: Guenter Roeck <groeck@chromium.org> Co-developed-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Kconfig | 8 + drivers/gpu/drm/msm/Makefile | 12 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 19 + .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 + drivers/gpu/drm/msm/dp/dp_aux.c | 535 ++++++ drivers/gpu/drm/msm/dp/dp_aux.h | 30 + drivers/gpu/drm/msm/dp/dp_catalog.c | 1019 ++++++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 102 + drivers/gpu/drm/msm/dp/dp_ctrl.c | 1694 +++++++++++++++++ drivers/gpu/drm/msm/dp/dp_ctrl.h | 35 + drivers/gpu/drm/msm/dp/dp_display.c | 936 +++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 28 + drivers/gpu/drm/msm/dp/dp_drm.c | 168 ++ drivers/gpu/drm/msm/dp/dp_drm.h | 18 + drivers/gpu/drm/msm/dp/dp_hpd.c | 69 + drivers/gpu/drm/msm/dp/dp_hpd.h | 79 + drivers/gpu/drm/msm/dp/dp_link.c | 1214 ++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 132 ++ drivers/gpu/drm/msm/dp/dp_panel.c | 486 +++++ drivers/gpu/drm/msm/dp/dp_panel.h | 95 + drivers/gpu/drm/msm/dp/dp_parser.c | 265 +++ drivers/gpu/drm/msm/dp/dp_parser.h | 139 ++ drivers/gpu/drm/msm/dp/dp_power.c | 363 ++++ drivers/gpu/drm/msm/dp/dp_power.h | 65 + drivers/gpu/drm/msm/dp/dp_reg.h | 490 +++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 53 +- 27 files changed, 8061 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.c create mode 100644 drivers/gpu/drm/msm/dp/dp_aux.h create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.c create mode 100644 drivers/gpu/drm/msm/dp/dp_catalog.h create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.c create mode 100644 drivers/gpu/drm/msm/dp/dp_ctrl.h create mode 100644 drivers/gpu/drm/msm/dp/dp_display.c create mode 100644 drivers/gpu/drm/msm/dp/dp_display.h create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_drm.h create mode 100644 drivers/gpu/drm/msm/dp/dp_hpd.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hpd.h create mode 100644 drivers/gpu/drm/msm/dp/dp_link.c create mode 100644 drivers/gpu/drm/msm/dp/dp_link.h create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.c create mode 100644 drivers/gpu/drm/msm/dp/dp_panel.h create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.c create mode 100644 drivers/gpu/drm/msm/dp/dp_parser.h create mode 100644 drivers/gpu/drm/msm/dp/dp_power.c create mode 100644 drivers/gpu/drm/msm/dp/dp_power.h create mode 100644 drivers/gpu/drm/msm/dp/dp_reg.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5ad8c3486ef32..a5fa0f87d1280 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -58,6 +58,14 @@ config DRM_MSM_HDMI_HDCP help Choose this option to enable HDCP state machine +config DRM_MSM_DP + bool "Enable DisplayPort support in MSM DRM driver" + depends on DRM_MSM + help + Compile in support for DP driver in MSM DRM driver. DP external + display support is enabled through this config option. It can + be primary or secondary display on device. + config DRM_MSM_DSI bool "Enable DSI support in MSM DRM driver" depends on DRM_MSM diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index c65cdd6397a35..fd5a3d580f274 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -2,6 +2,7 @@ ccflags-y := -I $(srctree)/$(src) ccflags-y += -I $(srctree)/$(src)/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -I $(srctree)/$(src)/dsi +ccflags-$(CONFIG_DRM_MSM_DP) += -I $(srctree)/$(src)/dp msm-y := \ adreno/adreno_device.o \ @@ -99,6 +100,17 @@ msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o +msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ + dp/dp_catalog.o \ + dp/dp_ctrl.o \ + dp/dp_display.o \ + dp/dp_drm.o \ + dp/dp_hpd.o \ + dp/dp_link.o \ + dp/dp_panel.o \ + dp/dp_parser.o \ + dp/dp_power.o + msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index bd6def436c657..eb2ba7e070837 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1001,6 +1001,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) + msm_dp_display_mode_set(priv->dp, drm_enc, mode, adj_mode); + list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) conn = conn_iter; @@ -1146,6 +1149,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = NULL; int ret = 0; + struct msm_drm_private *priv; struct drm_display_mode *cur_mode = NULL; if (!drm_enc) { @@ -1156,6 +1160,7 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) mutex_lock(&dpu_enc->enc_lock); cur_mode = &dpu_enc->base.crtc->state->adjusted_mode; + priv = drm_enc->dev->dev_private; trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay, cur_mode->vdisplay); @@ -1176,6 +1181,15 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) _dpu_encoder_virt_enable_helper(drm_enc); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + ret = msm_dp_display_enable(priv->dp, + drm_enc); + if (ret) { + DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n", + ret); + goto out; + } + } dpu_enc->enabled = true; out: @@ -1234,6 +1248,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + if (msm_dp_display_disable(priv->dp, drm_enc)) + DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n"); + } + mutex_unlock(&dpu_enc->enc_lock); } 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 b5a49050d1316..be11a0c5e60c6 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 @@ -100,6 +100,14 @@ static void drm_mode_to_intf_timing_params( * display_v_end -= mode->hsync_start - mode->hdisplay; * } */ + /* for DP/EDP, Shift timings to align it to bottom right */ + if ((phys_enc->hw_intf->cap->type == INTF_DP) || + (phys_enc->hw_intf->cap->type == INTF_EDP)) { + 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; + } } static u32 get_horizontal_total(const struct intf_timing_params *timing) diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c new file mode 100644 index 0000000000000..6bf3a5712968c --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/delay.h> + +#include "dp_reg.h" +#include "dp_aux.h" + +#define DP_AUX_ENUM_STR(x) #x + +struct dp_aux_private { + struct device *dev; + struct dp_catalog *catalog; + + struct mutex mutex; + struct completion comp; + + u32 aux_error_num; + u32 retry_cnt; + bool cmd_busy; + bool native; + bool read; + bool no_send_addr; + bool no_send_stop; + u32 offset; + u32 segment; + u32 isr; + + struct drm_dp_aux dp_aux; +}; + +static const char *dp_aux_get_error(u32 aux_error) +{ + switch (aux_error) { + case DP_AUX_ERR_NONE: + return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE); + case DP_AUX_ERR_ADDR: + return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR); + case DP_AUX_ERR_TOUT: + return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT); + case DP_AUX_ERR_NACK: + return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK); + case DP_AUX_ERR_DEFER: + return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER); + case DP_AUX_ERR_NACK_DEFER: + return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER); + default: + return "unknown"; + } +} + +static u32 dp_aux_write(struct dp_aux_private *aux, + struct drm_dp_aux_msg *msg) +{ + u32 data[4], reg, len; + u8 *msgdata = msg->buffer; + int const AUX_CMD_FIFO_LEN = 128; + int i = 0; + + if (aux->read) + len = 4; + else + len = msg->size + 4; + + /* + * cmd fifo only has depth of 144 bytes + * limit buf length to 128 bytes here + */ + if (len > AUX_CMD_FIFO_LEN) { + DRM_ERROR("buf size greater than allowed size of 128 bytes\n"); + return 0; + } + + /* Pack cmd and write to HW */ + data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */ + if (aux->read) + data[0] |= BIT(4); /* R/W */ + + data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */ + data[2] = msg->address & 0xff; /* addr[7:0] */ + data[3] = (msg->size - 1) & 0xff; /* len[7:0] */ + + for (i = 0; i < len; i++) { + reg = (i < 4) ? data[i] : msgdata[i - 4]; + /* index = 0, write */ + reg = (((reg) << DP_AUX_DATA_OFFSET) + & DP_AUX_DATA_MASK) | DP_AUX_DATA_WRITE; + if (i == 0) + reg |= DP_AUX_DATA_INDEX_WRITE; + aux->catalog->aux_data = reg; + dp_catalog_aux_write_data(aux->catalog); + } + + dp_catalog_aux_clear_trans(aux->catalog, false); + dp_catalog_aux_clear_hw_interrupts(aux->catalog); + + reg = 0; /* Transaction number == 1 */ + if (!aux->native) { /* i2c */ + reg |= DP_AUX_TRANS_CTRL_I2C; + + if (aux->no_send_addr) + reg |= DP_AUX_TRANS_CTRL_NO_SEND_ADDR; + + if (aux->no_send_stop) + reg |= DP_AUX_TRANS_CTRL_NO_SEND_STOP; + } + + reg |= DP_AUX_TRANS_CTRL_GO; + aux->catalog->aux_data = reg; + dp_catalog_aux_write_trans(aux->catalog); + + return len; +} + +static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, + struct drm_dp_aux_msg *msg) +{ + u32 ret, len, timeout; + int aux_timeout_ms = HZ/4; + + reinit_completion(&aux->comp); + + len = dp_aux_write(aux, msg); + if (len == 0) { + DRM_ERROR("DP AUX write failed\n"); + return -EINVAL; + } + + timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms); + if (!timeout) { + DRM_ERROR("aux %s timeout\n", (aux->read ? "read" : "write")); + return -ETIMEDOUT; + } + + if (aux->aux_error_num == DP_AUX_ERR_NONE) { + ret = len; + } else { + DRM_ERROR_RATELIMITED("aux err: %s\n", + dp_aux_get_error(aux->aux_error_num)); + + ret = -EINVAL; + } + + return ret; +} + +static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux, + struct drm_dp_aux_msg *msg) +{ + u32 data; + u8 *dp; + u32 i, actual_i; + u32 len = msg->size; + + dp_catalog_aux_clear_trans(aux->catalog, true); + + data = DP_AUX_DATA_INDEX_WRITE; /* INDEX_WRITE */ + data |= DP_AUX_DATA_READ; /* read */ + + aux->catalog->aux_data = data; + dp_catalog_aux_write_data(aux->catalog); + + dp = msg->buffer; + + /* discard first byte */ + data = dp_catalog_aux_read_data(aux->catalog); + + for (i = 0; i < len; i++) { + data = dp_catalog_aux_read_data(aux->catalog); + *dp++ = (u8)((data >> DP_AUX_DATA_OFFSET) & 0xff); + + actual_i = (data >> DP_AUX_DATA_INDEX_OFFSET) & 0xFF; + if (i != actual_i) + DRM_ERROR("Index mismatch: expected %d, found %d\n", + i, actual_i); + } +} + +static void dp_aux_native_handler(struct dp_aux_private *aux) +{ + u32 isr = aux->isr; + + if (isr & DP_INTR_AUX_I2C_DONE) + aux->aux_error_num = DP_AUX_ERR_NONE; + else if (isr & DP_INTR_WRONG_ADDR) + aux->aux_error_num = DP_AUX_ERR_ADDR; + else if (isr & DP_INTR_TIMEOUT) + aux->aux_error_num = DP_AUX_ERR_TOUT; + if (isr & DP_INTR_NACK_DEFER) + aux->aux_error_num = DP_AUX_ERR_NACK; + if (isr & DP_INTR_AUX_ERROR) { + aux->aux_error_num = DP_AUX_ERR_PHY; + dp_catalog_aux_clear_hw_interrupts(aux->catalog); + } + + complete(&aux->comp); +} + +static void dp_aux_i2c_handler(struct dp_aux_private *aux) +{ + u32 isr = aux->isr; + + if (isr & DP_INTR_AUX_I2C_DONE) { + if (isr & (DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER)) + aux->aux_error_num = DP_AUX_ERR_NACK; + else + aux->aux_error_num = DP_AUX_ERR_NONE; + } else { + if (isr & DP_INTR_WRONG_ADDR) + aux->aux_error_num = DP_AUX_ERR_ADDR; + else if (isr & DP_INTR_TIMEOUT) + aux->aux_error_num = DP_AUX_ERR_TOUT; + if (isr & DP_INTR_NACK_DEFER) + aux->aux_error_num = DP_AUX_ERR_NACK_DEFER; + if (isr & DP_INTR_I2C_NACK) + aux->aux_error_num = DP_AUX_ERR_NACK; + if (isr & DP_INTR_I2C_DEFER) + aux->aux_error_num = DP_AUX_ERR_DEFER; + if (isr & DP_INTR_AUX_ERROR) { + aux->aux_error_num = DP_AUX_ERR_PHY; + dp_catalog_aux_clear_hw_interrupts(aux->catalog); + } + } + + complete(&aux->comp); +} + +static void dp_aux_update_offset_and_segment(struct dp_aux_private *aux, + struct drm_dp_aux_msg *input_msg) +{ + u32 edid_address = 0x50; + u32 segment_address = 0x30; + bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); + u8 *data; + + if (aux->native || i2c_read || ((input_msg->address != edid_address) && + (input_msg->address != segment_address))) + return; + + + data = input_msg->buffer; + if (input_msg->address == segment_address) + aux->segment = *data; + else + aux->offset = *data; +} + +/** + * dp_aux_transfer_helper() - helper function for EDID read transactions + * + * @aux: DP AUX private structure + * @input_msg: input message from DRM upstream APIs + * @send_seg: send the segment to sink + * + * return: void + * + * This helper function is used to fix EDID reads for non-compliant + * sinks that do not handle the i2c middle-of-transaction flag correctly. + */ +static void dp_aux_transfer_helper(struct dp_aux_private *aux, + struct drm_dp_aux_msg *input_msg, + bool send_seg) +{ + struct drm_dp_aux_msg helper_msg; + u32 message_size = 0x10; + u32 segment_address = 0x30; + u32 const edid_block_length = 0x80; + bool i2c_mot = input_msg->request & DP_AUX_I2C_MOT; + bool i2c_read = input_msg->request & + (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); + + if (!i2c_mot || !i2c_read || (input_msg->size == 0)) + return; + + /* + * Sending the segment value and EDID offset will be performed + * from the DRM upstream EDID driver for each block. Avoid + * duplicate AUX transactions related to this while reading the + * first 16 bytes of each block. + */ + if (!(aux->offset % edid_block_length) || !send_seg) + goto end; + + aux->read = false; + aux->cmd_busy = true; + aux->no_send_addr = true; + aux->no_send_stop = true; + + /* + * Send the segment address for every i2c read in which the + * middle-of-tranaction flag is set. This is required to support EDID + * reads of more than 2 blocks as the segment address is reset to 0 + * since we are overriding the middle-of-transaction flag for read + * transactions. + */ + + if (aux->segment) { + memset(&helper_msg, 0, sizeof(helper_msg)); + helper_msg.address = segment_address; + helper_msg.buffer = &aux->segment; + helper_msg.size = 1; + dp_aux_cmd_fifo_tx(aux, &helper_msg); + } + + /* + * Send the offset address for every i2c read in which the + * middle-of-transaction flag is set. This will ensure that the sink + * will update its read pointer and return the correct portion of the + * EDID buffer in the subsequent i2c read trasntion triggered in the + * native AUX transfer function. + */ + memset(&helper_msg, 0, sizeof(helper_msg)); + helper_msg.address = input_msg->address; + helper_msg.buffer = &aux->offset; + helper_msg.size = 1; + dp_aux_cmd_fifo_tx(aux, &helper_msg); + +end: + aux->offset += message_size; + if (aux->offset == 0x80 || aux->offset == 0x100) + aux->segment = 0x0; /* reset segment at end of block */ +} + +/* + * This function does the real job to process an AUX transaction. + * It will call aux_reset() function to reset the AUX channel, + * if the waiting is timeout. + */ +static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, + struct drm_dp_aux_msg *msg) +{ + ssize_t ret; + int const aux_cmd_native_max = 16; + int const aux_cmd_i2c_max = 128; + int const retry_count = 5; + struct dp_aux_private *aux = container_of(dp_aux, + struct dp_aux_private, dp_aux); + + mutex_lock(&aux->mutex); + + aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ); + + /* Ignore address only message */ + if ((msg->size == 0) || (msg->buffer == NULL)) { + msg->reply = aux->native ? + DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; + ret = msg->size; + goto unlock_exit; + } + + /* msg sanity check */ + if ((aux->native && (msg->size > aux_cmd_native_max)) || + (msg->size > aux_cmd_i2c_max)) { + DRM_ERROR("%s: invalid msg: size(%zu), request(%x)\n", + __func__, msg->size, msg->request); + ret = -EINVAL; + goto unlock_exit; + } + + dp_aux_update_offset_and_segment(aux, msg); + dp_aux_transfer_helper(aux, msg, true); + + aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ); + aux->cmd_busy = true; + + if (aux->read) { + aux->no_send_addr = true; + aux->no_send_stop = false; + } else { + aux->no_send_addr = true; + aux->no_send_stop = true; + } + + ret = dp_aux_cmd_fifo_tx(aux, msg); + + if (ret < 0) { + if (aux->native) { + aux->retry_cnt++; + if (!(aux->retry_cnt % retry_count)) + dp_catalog_aux_update_cfg(aux->catalog, + PHY_AUX_CFG1); + dp_catalog_aux_reset(aux->catalog); + } + goto unlock_exit; + } + + if (aux->aux_error_num == DP_AUX_ERR_NONE) { + if (aux->read) + dp_aux_cmd_fifo_rx(aux, msg); + + msg->reply = aux->native ? + DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; + } else { + /* Reply defer to retry */ + msg->reply = aux->native ? + DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER; + } + + /* Return requested size for success or retry */ + ret = msg->size; + aux->retry_cnt = 0; + +unlock_exit: + aux->cmd_busy = false; + mutex_unlock(&aux->mutex); + return ret; +} + +void dp_aux_isr(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + + if (!dp_aux) { + DRM_ERROR("invalid input\n"); + return; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->isr = dp_catalog_aux_get_irq(aux->catalog); + + if (!aux->cmd_busy) + return; + + if (aux->native) + dp_aux_native_handler(aux); + else + dp_aux_i2c_handler(aux); +} + +void dp_aux_reconfig(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + dp_catalog_aux_update_cfg(aux->catalog, PHY_AUX_CFG1); + dp_catalog_aux_reset(aux->catalog); +} + +void dp_aux_init(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + + if (!dp_aux) { + DRM_ERROR("invalid input\n"); + return; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + dp_catalog_aux_setup(aux->catalog); + dp_catalog_aux_enable(aux->catalog, true); + aux->retry_cnt = 0; +} + +void dp_aux_deinit(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + dp_catalog_aux_enable(aux->catalog, false); +} + +int dp_aux_register(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + int ret; + + if (!dp_aux) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + aux->dp_aux.name = "dpu_dp_aux"; + aux->dp_aux.dev = aux->dev; + aux->dp_aux.transfer = dp_aux_transfer; + ret = drm_dp_aux_register(&aux->dp_aux); + if (ret) { + DRM_ERROR("%s: failed to register drm aux: %d\n", __func__, + ret); + return ret; + } + + return 0; +} + +void dp_aux_unregister(struct drm_dp_aux *dp_aux) +{ + drm_dp_aux_unregister(dp_aux); +} + +struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog) +{ + struct 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); + + init_completion(&aux->comp); + aux->cmd_busy = false; + mutex_init(&aux->mutex); + + aux->dev = dev; + aux->catalog = catalog; + aux->retry_cnt = 0; + + return &aux->dp_aux; +} + +void dp_aux_put(struct drm_dp_aux *dp_aux) +{ + struct dp_aux_private *aux; + + if (!dp_aux) + return; + + aux = container_of(dp_aux, struct dp_aux_private, dp_aux); + + mutex_destroy(&aux->mutex); + + devm_kfree(aux->dev, aux); +} diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h new file mode 100644 index 0000000000000..f8b8ba9194659 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_aux.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_AUX_H_ +#define _DP_AUX_H_ + +#include "dp_catalog.h" +#include <drm/drm_dp_helper.h> + +#define DP_AUX_ERR_NONE 0 +#define DP_AUX_ERR_ADDR -1 +#define DP_AUX_ERR_TOUT -2 +#define DP_AUX_ERR_NACK -3 +#define DP_AUX_ERR_DEFER -4 +#define DP_AUX_ERR_NACK_DEFER -5 +#define DP_AUX_ERR_PHY -6 + +int dp_aux_register(struct drm_dp_aux *dp_aux); +void dp_aux_unregister(struct drm_dp_aux *dp_aux); +void dp_aux_isr(struct drm_dp_aux *dp_aux); +void dp_aux_init(struct drm_dp_aux *dp_aux); +void dp_aux_deinit(struct drm_dp_aux *dp_aux); +void dp_aux_reconfig(struct drm_dp_aux *dp_aux); + +struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog); +void 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 new file mode 100644 index 0000000000000..0ffde1a748529 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -0,0 +1,1019 @@ +// 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/rational.h> +#include <drm/drm_dp_helper.h> + +#include "dp_catalog.h" +#include "dp_reg.h" + +#define POLLING_SLEEP_US 1000 +#define POLLING_TIMEOUT_US 10000 + +#define REFTIMER_DEFAULT_VALUE 0x20000 +#define SCRAMBLER_RESET_COUNT_VALUE 0xFC + +#define DP_INTERRUPT_STATUS_ACK_SHIFT 1 +#define DP_INTERRUPT_STATUS_MASK_SHIFT 2 + +#define MSM_DP_CONTROLLER_AHB_OFFSET 0x0000 +#define MSM_DP_CONTROLLER_AHB_SIZE 0x0200 +#define MSM_DP_CONTROLLER_AUX_OFFSET 0x0200 +#define MSM_DP_CONTROLLER_AUX_SIZE 0x0200 +#define MSM_DP_CONTROLLER_LINK_OFFSET 0x0400 +#define MSM_DP_CONTROLLER_LINK_SIZE 0x0C00 +#define MSM_DP_CONTROLLER_P0_OFFSET 0x1000 +#define MSM_DP_CONTROLLER_P0_SIZE 0x0400 + +#define DP_INTERRUPT_STATUS1 \ + (DP_INTR_AUX_I2C_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) + +static u8 const vm_pre_emphasis_hbr_rbr[4][4] = { + {0x00, 0x0C, 0x14, 0x19}, + {0x00, 0x0B, 0x12, 0xFF}, + {0x00, 0x0B, 0xFF, 0xFF}, + {0x04, 0xFF, 0xFF, 0xFF} +}; + +static u8 const vm_voltage_swing_hbr_rbr[4][4] = { + {0x08, 0x0F, 0x16, 0x1F}, + {0x11, 0x1E, 0x1F, 0xFF}, + {0x19, 0x1F, 0xFF, 0xFF}, + {0x1F, 0xFF, 0xFF, 0xFF} +}; + +/* AUX look-up-table configurations + * Pair of offset and config values for each LUT + */ +static u8 const aux_lut_offset[] = { + 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, 0x40, 0x44 +}; + +static u8 const +aux_lut_value[PHY_AUX_CFG_MAX][DP_AUX_CFG_MAX_VALUE_CNT] = { + { 0x00, 0x00, 0x00, }, + { 0x13, 0x23, 0x1d, }, + { 0x24, 0x00, 0x00, }, + { 0x00, 0x00, 0x00, }, + { 0x0A, 0x00, 0x00, }, + { 0x26, 0x00, 0x00, }, + { 0x0A, 0x00, 0x00, }, + { 0x03, 0x00, 0x00, }, + { 0xBB, 0x00, 0x00, }, + { 0x03, 0x00, 0x00, } +}; + +struct dp_catalog_private { + struct device *dev; + struct dp_io *io; + struct dp_catalog dp_catalog; + u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; +}; + +static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) +{ + offset += MSM_DP_CONTROLLER_AUX_OFFSET; + return readl_relaxed(catalog->io->dp_controller.base + offset); +} + +static inline void dp_write_aux(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + offset += MSM_DP_CONTROLLER_AUX_OFFSET; + /* + * To make sure aux reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, catalog->io->dp_controller.base + offset); +} + +static inline u32 dp_read_ahb(struct dp_catalog_private *catalog, u32 offset) +{ + offset += MSM_DP_CONTROLLER_AHB_OFFSET; + return readl_relaxed(catalog->io->dp_controller.base + offset); +} + +static inline void dp_write_ahb(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + offset += MSM_DP_CONTROLLER_AHB_OFFSET; + /* + * To make sure phy reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, catalog->io->dp_controller.base + offset); +} + +static inline void dp_write_phy(struct 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->phy_io.base + offset); +} + +static inline u32 dp_read_phy(struct dp_catalog_private *catalog, + u32 offset) +{ + /* + * To make sure phy reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + return readl_relaxed(catalog->io->phy_io.base + offset); +} + +static inline void dp_write_pll(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + writel_relaxed(data, catalog->io->dp_pll_io.base + offset); +} + +static inline void dp_write_ln_tx0(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + writel_relaxed(data, catalog->io->ln_tx0_io.base + offset); +} + +static inline void dp_write_ln_tx1(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + writel_relaxed(data, catalog->io->ln_tx1_io.base + offset); +} + +static inline u32 dp_read_ln_tx0(struct dp_catalog_private *catalog, + u32 offset) +{ + return readl_relaxed(catalog->io->ln_tx0_io.base + offset); +} + +static inline u32 dp_read_ln_tx1(struct dp_catalog_private *catalog, + u32 offset) +{ + return readl_relaxed(catalog->io->ln_tx1_io.base + offset); +} + +static inline void dp_write_usb_cm(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + /* + * To make sure usb reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, catalog->io->usb3_dp_com.base + offset); +} + +static inline u32 dp_read_usb_cm(struct dp_catalog_private *catalog, + u32 offset) +{ + /* + * To make sure usb reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + return readl_relaxed(catalog->io->usb3_dp_com.base + offset); +} + +static inline void dp_write_p0(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + offset += MSM_DP_CONTROLLER_P0_OFFSET; + /* + * To make sure interface reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, catalog->io->dp_controller.base + offset); +} + +static inline u32 dp_read_p0(struct dp_catalog_private *catalog, + u32 offset) +{ + offset += MSM_DP_CONTROLLER_P0_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->dp_controller.base + offset); +} + +static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) +{ + offset += MSM_DP_CONTROLLER_LINK_OFFSET; + return readl_relaxed(catalog->io->dp_controller.base + offset); +} + +static inline void dp_write_link(struct dp_catalog_private *catalog, + u32 offset, u32 data) +{ + offset += MSM_DP_CONTROLLER_LINK_OFFSET; + /* + * To make sure link reg writes happens before any other operation, + * this function uses writel() instread of writel_relaxed() + */ + writel(data, catalog->io->dp_controller.base + offset); +} + +/* aux related catalog functions */ +u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + return dp_read_aux(catalog, REG_DP_AUX_DATA); +} + +int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_aux(catalog, REG_DP_AUX_DATA, dp_catalog->aux_data); + return 0; +} + +int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, dp_catalog->aux_data); + return 0; +} + +int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read) +{ + u32 data; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + if (read) { + data = dp_read_aux(catalog, REG_DP_AUX_TRANS_CTRL); + data &= ~DP_AUX_TRANS_CTRL_GO; + dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, data); + } else { + dp_write_aux(catalog, REG_DP_AUX_TRANS_CTRL, 0); + } + return 0; +} + +int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_read_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_STATUS); + dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x1f); + dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0x9f); + dp_write_aux(catalog, REG_DP_PHY_AUX_INTERRUPT_CLEAR, 0); + return 0; +} + +void dp_catalog_aux_reset(struct dp_catalog *dp_catalog) +{ + u32 aux_ctrl; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); + + aux_ctrl |= DP_AUX_CTRL_RESET; + dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); + usleep_range(1000, 1100); /* h/w recommended delay */ + + aux_ctrl &= ~DP_AUX_CTRL_RESET; + dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); +} + +void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) +{ + u32 aux_ctrl; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + aux_ctrl = dp_read_aux(catalog, REG_DP_AUX_CTRL); + + if (enable) { + dp_write_aux(catalog, REG_DP_TIMEOUT_COUNT, 0xffff); + dp_write_aux(catalog, REG_DP_AUX_LIMITS, 0xffff); + aux_ctrl |= DP_AUX_CTRL_ENABLE; + } else { + aux_ctrl &= ~DP_AUX_CTRL_ENABLE; + } + + dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); +} + +void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog, + enum dp_phy_aux_config_type type) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u32 new_index = 0, current_index = 0; + + if (type >= PHY_AUX_CFG_MAX) { + DRM_ERROR("invalid input\n"); + return; + } + + current_index = catalog->aux_lut_cfg_index[type]; + new_index = (current_index + 1) % DP_AUX_CFG_MAX_VALUE_CNT; + DRM_DEBUG_DP("Updating PHY_AUX_CFG%d from 0x%08x to 0x%08x\n", + type, aux_lut_value[type][current_index], + aux_lut_value[type][new_index]); + + dp_write_phy(catalog, aux_lut_offset[type], + aux_lut_value[type][new_index]); + catalog->aux_lut_cfg_index[type] = new_index; +} + +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 dp_catalog_dump_regs(struct dp_catalog *dp_catalog) +{ + u32 offset, len; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + pr_info("AHB regs\n"); + offset = MSM_DP_CONTROLLER_AHB_OFFSET; + len = MSM_DP_CONTROLLER_AHB_SIZE; + dump_regs(catalog->io->dp_controller.base + offset, len); + + pr_info("AUXCLK regs\n"); + offset = MSM_DP_CONTROLLER_AUX_OFFSET; + len = MSM_DP_CONTROLLER_AUX_SIZE; + dump_regs(catalog->io->dp_controller.base + offset, len); + + pr_info("LCLK regs\n"); + offset = MSM_DP_CONTROLLER_LINK_OFFSET; + len = MSM_DP_CONTROLLER_LINK_SIZE; + dump_regs(catalog->io->dp_controller.base + offset, len); + + pr_info("P0CLK regs\n"); + offset = MSM_DP_CONTROLLER_P0_OFFSET; + len = MSM_DP_CONTROLLER_P0_SIZE; + dump_regs(catalog->io->dp_controller.base + offset, len); + + pr_info("USB3 DP COM regs\n"); + dump_regs(catalog->io->usb3_dp_com.base, catalog->io->usb3_dp_com.len); + + pr_info("LN TX0 regs\n"); + dump_regs(catalog->io->ln_tx0_io.base, catalog->io->ln_tx0_io.len); + + pr_info("LN TX1 regs\n"); + dump_regs(catalog->io->ln_tx1_io.base, catalog->io->ln_tx1_io.len); + + pr_info("DP PHY regs\n"); + dump_regs(catalog->io->phy_io.base, catalog->io->phy_io.len); +} + +void dp_catalog_aux_setup(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + int i = 0; + + dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PWRDN | + DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | + DP_PHY_PD_CTL_DP_CLAMP_EN); + + /* Turn on BIAS current for PHY/PLL */ + dp_write_pll(catalog, + QSERDES_COM_BIAS_EN_CLKBUFLR_EN, QSERDES_COM_BIAS_EN | + QSERDES_COM_BIAS_EN_MUX | QSERDES_COM_CLKBUF_L_EN | + QSERDES_COM_EN_SYSCLK_TX_SEL); + + dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PSR_PWRDN); + + dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PWRDN | + DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_LANE_0_1_PWRDN + | DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN + | DP_PHY_PD_CTL_DP_CLAMP_EN); + + dp_write_pll(catalog, + QSERDES_COM_BIAS_EN_CLKBUFLR_EN, QSERDES_COM_BIAS_EN | + QSERDES_COM_BIAS_EN_MUX | QSERDES_COM_CLKBUF_R_EN | + QSERDES_COM_CLKBUF_L_EN | QSERDES_COM_EN_SYSCLK_TX_SEL | + QSERDES_COM_CLKBUF_RX_DRIVE_L); + + /* DP AUX CFG register programming */ + for (i = 0; i < PHY_AUX_CFG_MAX; i++) { + DRM_DEBUG_DP("PHY_AUX_CFG%ds: offset=0x%08x, value=0x%08x\n", + i, aux_lut_offset[i], aux_lut_value[i][0]); + dp_write_phy(catalog, aux_lut_offset[i], + aux_lut_value[i][0]); + } + + dp_write_phy(catalog, REG_DP_PHY_AUX_INTERRUPT_MASK, + PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | + PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | + PHY_AUX_REQ_ERR_MASK); +} + +int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u32 intr, intr_ack; + + intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS); + intr &= ~DP_INTERRUPT_STATUS1_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS1) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + dp_write_ahb(catalog, REG_DP_INTR_STATUS, intr_ack | + DP_INTERRUPT_STATUS1_MASK); + + return intr; + +} + +/* controller related catalog functions */ +void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog, + u32 dp_tu, u32 valid_boundary, + u32 valid_boundary2) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_link(catalog, REG_DP_VALID_BOUNDARY, valid_boundary); + dp_write_link(catalog, REG_DP_TU, dp_tu); + dp_write_link(catalog, REG_DP_VALID_BOUNDARY_2, valid_boundary2); +} + +void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_link(catalog, REG_DP_STATE_CTRL, state); +} + +void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 cfg) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + DRM_DEBUG_DP("DP_CONFIGURATION_CTRL=0x%x\n", cfg); + + dp_write_link(catalog, REG_DP_CONFIGURATION_CTRL, cfg); +} + +void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, 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; + + dp_write_link(catalog, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING, + ln_mapping); +} + +void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, + bool enable) +{ + u32 mainlink_ctrl; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + if (enable) { + /* + * To make sure link reg writes happens before other operation, + * dp_write_link() function uses writel() + */ + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_FB_BOUNDARY_SEL); + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_FB_BOUNDARY_SEL | + DP_MAINLINK_CTRL_RESET); + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_FB_BOUNDARY_SEL); + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_FB_BOUNDARY_SEL | + DP_MAINLINK_CTRL_ENABLE); + } else { + mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); + mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + } +} + +void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, + u32 colorimetry_cfg, + u32 test_bits_depth) +{ + u32 misc_val; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + misc_val = 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_DEBUG_DP("misc settings = 0x%x\n", misc_val); + dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val); +} + +void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, + u32 rate, u32 stream_rate_khz, + bool fixed_nvid) +{ + u32 pixel_m, pixel_n; + u32 mvid, nvid, div, 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 dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + div = dp_read_phy(catalog, REG_DP_PHY_VCO_DIV); + div &= 0x03; + + if (div == 0) + pixel_div = 6; + else if (div == 1) + pixel_div = 2; + else if (div == 2) + 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 (link_rate_hbr2 == rate) + nvid *= 2; + + if (link_rate_hbr3 == rate) + nvid *= 3; + + DRM_DEBUG_DP("mvid=0x%x, nvid=0x%x\n", mvid, nvid); + dp_write_link(catalog, REG_DP_SOFTWARE_MVID, mvid); + dp_write_link(catalog, REG_DP_SOFTWARE_NVID, nvid); + dp_write_p0(catalog, MMSS_DP_DSC_DTO, 0x0); +} + +int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, + u32 pattern) +{ + int bit, ret; + u32 data; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + bit = BIT(pattern - 1); + DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern); + dp_write_link(catalog, REG_DP_STATE_CTRL, bit); + + bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; + + /* Poll for mainlink ready status */ + ret = readx_poll_timeout(readl, catalog->io->dp_controller.base + + MSM_DP_CONTROLLER_LINK_OFFSET + + REG_DP_MAINLINK_READY, + data, data & bit, + POLLING_SLEEP_US, POLLING_TIMEOUT_US); + if (ret < 0) { + DRM_ERROR("set pattern for link_train=%d failed\n", pattern); + return ret; + } + return 0; +} + +void dp_catalog_ctrl_usb_reset(struct dp_catalog *dp_catalog, bool flip) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u32 typec_ctrl; + + dp_write_usb_cm(catalog, REG_USB3_DP_COM_RESET_OVRD_CTRL, + USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX | + USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX); + dp_write_usb_cm(catalog, REG_USB3_DP_COM_PHY_MODE_CTRL, + USB3_DP_COM_PHY_MODE_DP); + dp_write_usb_cm(catalog, REG_USB3_DP_COM_SW_RESET, + USB3_DP_COM_SW_RESET_SET); + + /* Default configuration i.e CC1 */ + typec_ctrl = USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX; + if (flip) + typec_ctrl |= USB3_DP_COM_TYPEC_CTRL_PORTSEL; + + dp_write_usb_cm(catalog, REG_USB3_DP_COM_TYPEC_CTRL, typec_ctrl); + + dp_write_usb_cm(catalog, REG_USB3_DP_COM_SWI_CTRL, 0x00); + dp_write_usb_cm(catalog, REG_USB3_DP_COM_SW_RESET, 0x00); + + dp_write_usb_cm(catalog, REG_USB3_DP_COM_POWER_DOWN_CTRL, + USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN); + dp_write_usb_cm(catalog, REG_USB3_DP_COM_RESET_OVRD_CTRL, 0x00); + +} + +void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog) +{ + u32 sw_reset; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + sw_reset = dp_read_ahb(catalog, REG_DP_SW_RESET); + + sw_reset |= DP_SW_RESET; + dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); + usleep_range(1000, 1100); /* h/w recommended delay */ + + sw_reset &= ~DP_SW_RESET; + dp_write_ahb(catalog, REG_DP_SW_RESET, sw_reset); +} + +bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog) +{ + u32 data; + int ret; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + /* Poll for mainlink ready status */ + ret = readl_poll_timeout(catalog->io->dp_controller.base + + MSM_DP_CONTROLLER_LINK_OFFSET + + 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 dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, + bool enable) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + if (enable) { + dp_write_ahb(catalog, REG_DP_INTR_STATUS, + DP_INTERRUPT_STATUS1_MASK); + dp_write_ahb(catalog, REG_DP_INTR_STATUS2, + DP_INTERRUPT_STATUS2_MASK); + } else { + dp_write_ahb(catalog, REG_DP_INTR_STATUS, 0x00); + dp_write_ahb(catalog, REG_DP_INTR_STATUS2, 0x00); + } +} + +void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog, bool en) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + if (en) { + u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); + + dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, + DP_DP_HPD_PLUG_INT_ACK | + DP_DP_IRQ_HPD_INT_ACK | + DP_DP_HPD_REPLUG_INT_ACK | + DP_DP_HPD_UNPLUG_INT_ACK); + dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, + DP_DP_HPD_PLUG_INT_MASK | + DP_DP_IRQ_HPD_INT_MASK | + DP_DP_HPD_REPLUG_INT_MASK | + DP_DP_HPD_UNPLUG_INT_MASK); + + /* Configure REFTIMER */ + reftimer |= REFTIMER_DEFAULT_VALUE; + dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); + /* Enable HPD */ + dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, + DP_DP_HPD_CTRL_HPD_EN); + } else { + /* Disable HPD */ + dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, 0x0); + } +} + +int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u32 intr, intr_ack; + + intr = dp_read_ahb(catalog, REG_DP_INTR_STATUS2); + intr &= ~DP_INTERRUPT_STATUS2_MASK; + intr_ack = (intr & DP_INTERRUPT_STATUS2) + << DP_INTERRUPT_STATUS_ACK_SHIFT; + dp_write_ahb(catalog, REG_DP_INTR_STATUS2, + intr_ack | DP_INTERRUPT_STATUS2_MASK); + + return intr; +} + +void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_ahb(catalog, REG_DP_PHY_CTRL, + DP_PHY_CTRL_SW_RESET_PLL | DP_PHY_CTRL_SW_RESET); + usleep_range(1000, 1100); /* h/w recommended delay */ + dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); +} + +void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog *dp_catalog, + bool flipped, u8 ln_cnt) +{ + u32 info; + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u8 orientation = BIT(!!flipped); + + info = ln_cnt & DP_PHY_SPARE0_MASK; + info |= (orientation & DP_PHY_SPARE0_MASK) + << DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT; + DRM_DEBUG_DP("Shared Info = 0x%x\n", info); + + dp_write_phy(catalog, REG_DP_PHY_SPARE0, info); +} + +int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, + u8 v_level, u8 p_level) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u8 voltage_swing_cfg, pre_emphasis_cfg; + + DRM_DEBUG_DP("hw: v=%d p=%d\n", v_level, p_level); + + voltage_swing_cfg = vm_voltage_swing_hbr_rbr[v_level][p_level]; + pre_emphasis_cfg = vm_pre_emphasis_hbr_rbr[v_level][p_level]; + + if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) { + DRM_ERROR("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", + v_level, voltage_swing_cfg, p_level, pre_emphasis_cfg); + return -EINVAL; + } + + /* Enable MUX to use Cursor values from these registers */ + voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; + pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; + + /* Configure host and panel only if both values are allowed */ + dp_write_ln_tx0(catalog, REG_DP_PHY_TXn_TX_DRV_LVL, voltage_swing_cfg); + dp_write_ln_tx1(catalog, REG_DP_PHY_TXn_TX_DRV_LVL, voltage_swing_cfg); + dp_write_ln_tx0(catalog, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, + pre_emphasis_cfg); + dp_write_ln_tx1(catalog, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, + pre_emphasis_cfg); + DRM_DEBUG_DP("hw: vx_value=0x%x px_value=0x%x\n", + voltage_swing_cfg, pre_emphasis_cfg); + + return 0; +} + +void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, + u32 pattern) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + u32 value = 0x0; + + /* Make sure to clear the current pattern before starting a new one */ + dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); + + switch (pattern) { + case DP_LINK_QUAL_PATTERN_D10_2: + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TRAINING_PATTERN1); + return; + case DP_LINK_QUAL_PATTERN_PRBS7: + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_PRBS7); + return; + case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM: + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); + /* 00111110000011111000001111100000 */ + dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0, + 0x3E0F83E0); + /* 00001111100000111110000011111000 */ + dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1, + 0x0F83E0F8); + /* 1111100000111110 */ + dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, + 0x0000F83E); + return; + case DP_LINK_QUAL_PATTERN_HBR2_EYE: + case DP_LINK_QUAL_PATTERN_ERROR_RATE: + value &= ~DP_HBR2_ERM_PATTERN; + if (pattern == DP_LINK_QUAL_PATTERN_HBR2_EYE) + value = DP_HBR2_ERM_PATTERN; + dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + value |= SCRAMBLER_RESET_COUNT_VALUE; + dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, + DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); + return; + default: + DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern); + return; + } +} + +u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + return dp_read_link(catalog, REG_DP_MAINLINK_READY); +} + +/* panel related catalog functions */ +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_link(catalog, REG_DP_TOTAL_HOR_VER, + dp_catalog->total); + dp_write_link(catalog, REG_DP_START_HOR_VER_FROM_SYNC, + dp_catalog->sync_start); + dp_write_link(catalog, REG_DP_HSYNC_VSYNC_WIDTH_POLARITY, + dp_catalog->width_blanking); + dp_write_link(catalog, REG_DP_ACTIVE_HOR_VER, dp_catalog->dp_active); + return 0; +} + +void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, + struct drm_display_mode *drm_mode) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, 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; + + + dp_write_p0(catalog, MMSS_DP_INTF_CONFIG, 0x0); + dp_write_p0(catalog, MMSS_DP_INTF_HSYNC_CTL, hsync_ctl); + dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F0, vsync_period * + hsync_period); + dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0, v_sync_width * + hsync_period); + dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PERIOD_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_HCTL, display_hctl); + dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_HCTL, 0); + dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F0, display_v_start); + dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F0, display_v_end); + dp_write_p0(catalog, MMSS_INTF_DISPLAY_V_START_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_DISPLAY_V_END_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F0, 0); + dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F0, 0); + dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_START_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_ACTIVE_V_END_F1, 0); + dp_write_p0(catalog, MMSS_DP_INTF_POLARITY_CTL, 0); + + dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, + DP_TPG_CHECKERED_RECT_PATTERN); + dp_write_p0(catalog, MMSS_DP_TPG_VIDEO_CONFIG, + DP_TPG_VIDEO_CONFIG_BPP_8BIT | + DP_TPG_VIDEO_CONFIG_RGB); + dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, + DP_BIST_ENABLE_DPBIST_EN); + dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, + DP_TIMING_ENGINE_EN_EN); + DRM_DEBUG_DP("%s: enabled tpg\n", __func__); +} + +void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + dp_write_p0(catalog, MMSS_DP_TPG_MAIN_CONTROL, 0x0); + dp_write_p0(catalog, MMSS_DP_BIST_ENABLE, 0x0); + dp_write_p0(catalog, MMSS_DP_TIMING_ENGINE_EN, 0x0); +} + +struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) +{ + struct dp_catalog_private *catalog; + + if (!io) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-EINVAL); + } + + catalog = devm_kzalloc(dev, sizeof(*catalog), GFP_KERNEL); + if (!catalog) + return ERR_PTR(-ENOMEM); + + catalog->dev = dev; + catalog->io = io; + + return &catalog->dp_catalog; +} diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h new file mode 100644 index 0000000000000..012570be16353 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -0,0 +1,102 @@ +/* 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 "dp_parser.h" + +/* interrupts */ +#define DP_INTR_HPD BIT(0) +#define DP_INTR_AUX_I2C_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_AUX_CFG_MAX_VALUE_CNT 3 + +/* PHY AUX config registers */ +enum dp_phy_aux_config_type { + PHY_AUX_CFG0, + PHY_AUX_CFG1, + PHY_AUX_CFG2, + PHY_AUX_CFG3, + PHY_AUX_CFG4, + PHY_AUX_CFG5, + PHY_AUX_CFG6, + PHY_AUX_CFG7, + PHY_AUX_CFG8, + PHY_AUX_CFG9, + PHY_AUX_CFG_MAX, +}; + +struct dp_catalog { + u32 aux_data; + u32 total; + u32 sync_start; + u32 width_blanking; + u32 dp_active; +}; + +/* AUX APIs */ +u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog); +int dp_catalog_aux_write_data(struct dp_catalog *dp_catalog); +int dp_catalog_aux_write_trans(struct dp_catalog *dp_catalog); +int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read); +int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog); +void dp_catalog_aux_reset(struct dp_catalog *dp_catalog); +void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable); +void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog, + enum dp_phy_aux_config_type type); +void dp_catalog_aux_setup(struct dp_catalog *dp_catalog); +int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog); + +/* DP Controller APIs */ +void dp_catalog_ctrl_state_ctrl(struct dp_catalog *dp_catalog, u32 state); +void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 config); +void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog); +void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable); +void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb); +void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate, + u32 stream_rate_khz, bool fixed_nvid); +int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern); +void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); +void dp_catalog_ctrl_usb_reset(struct dp_catalog *dp_catalog, bool flip); +bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); +void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); +void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog, bool enable); +void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog); +void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog *dp_catalog, bool flipped, + u8 lane_cnt); +int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, u8 v_level, + u8 p_level); +int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog); +void dp_catalog_ctrl_update_transfer_unit(struct dp_catalog *dp_catalog, + u32 dp_tu, u32 valid_boundary, + u32 valid_boundary2); +void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, + u32 pattern); +u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog); + +/* DP Panel APIs */ +int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog); +void dp_catalog_dump_regs(struct dp_catalog *dp_catalog); +void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog, + struct drm_display_mode *drm_mode); +void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog); + +struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io); + +#endif /* _DP_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c new file mode 100644 index 0000000000000..9a06cbf40af1b --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -0,0 +1,1694 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/types.h> +#include <linux/completion.h> +#include <linux/delay.h> +#include <drm/drm_fixed.h> +#include <drm/drm_dp_helper.h> + +#include "dp_reg.h" +#include "dp_ctrl.h" +#include "dp_link.h" + +#define DP_KHZ_TO_HZ 1000 +#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES (30 * HZ / 1000) /* 30 ms */ +#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2) + +#define DP_CTRL_INTR_READY_FOR_VIDEO BIT(0) +#define DP_CTRL_INTR_IDLE_PATTERN_SENT BIT(3) + +#define MR_LINK_TRAINING1 0x8 +#define MR_LINK_SYMBOL_ERM 0x80 +#define MR_LINK_PRBS7 0x100 +#define MR_LINK_CUSTOM80 0x200 + +struct dp_tu_calc_input { + u64 lclk; /* 162, 270, 540 and 810 */ + u64 pclk_khz; /* in KHz */ + u64 hactive; /* active h-width */ + u64 hporch; /* bp + fp + pulse */ + int nlanes; /* no.of.lanes */ + int bpp; /* bits */ + int pixel_enc; /* 444, 420, 422 */ + int dsc_en; /* dsc on/off */ + int async_en; /* async mode */ + int fec_en; /* fec */ + int compress_ratio; /* 2:1 = 200, 3:1 = 300, 3.75:1 = 375 */ + int num_of_dsc_slices; /* number of slices per line */ +}; + +struct dp_vc_tu_mapping_table { + u32 vic; + u8 lanes; + u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */ + u8 bpp; + u8 valid_boundary_link; + u16 delay_start_link; + bool boundary_moderation_en; + u8 valid_lower_boundary_link; + u8 upper_boundary_count; + u8 lower_boundary_count; + u8 tu_size_minus1; +}; + +struct dp_ctrl_private { + struct dp_ctrl dp_ctrl; + + struct device *dev; + struct drm_dp_aux *aux; + struct dp_panel *panel; + struct dp_link *link; + struct dp_power *power; + struct dp_parser *parser; + struct dp_catalog *catalog; + + struct completion idle_comp; + struct mutex push_idle_mutex; + struct completion video_comp; +}; + +static int dp_aux_link_configure(struct drm_dp_aux *aux, + struct dp_link_info *link) +{ + u8 values[2]; + int err; + + values[0] = drm_dp_link_rate_to_bw_code(link->rate); + values[1] = link->num_lanes; + + if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) + values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); + if (err < 0) + return err; + + return 0; +} + +void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + mutex_lock(&ctrl->push_idle_mutex); + + reinit_completion(&ctrl->idle_comp); + dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE); + + if (!wait_for_completion_timeout(&ctrl->idle_comp, + IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) + pr_warn("PUSH_IDLE pattern timedout\n"); + + mutex_unlock(&ctrl->push_idle_mutex); + pr_debug("mainlink off done\n"); +} + +static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) +{ + u32 config = 0, tbd; + u8 *dpcd = ctrl->panel->dpcd; + + /* Default-> LSCLK DIV: 1/4 LCLK */ + config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT); + + /* Scrambler reset enable */ + if (dpcd[DP_EDP_CONFIGURATION_CAP] & DP_ALTERNATE_SCRAMBLER_RESET_CAP) + config |= DP_CONFIGURATION_CTRL_ASSR; + + tbd = dp_link_get_test_bits_depth(ctrl->link, + ctrl->panel->dp_mode.bpp); + + if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) { + pr_debug("BIT_DEPTH not set. Configure default\n"); + tbd = DP_TEST_BIT_DEPTH_8; + } + + config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; + + /* Num of Lanes */ + config |= ((ctrl->link->link_params.num_lanes - 1) + << DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT); + + if (drm_dp_enhanced_frame_cap(dpcd)) + config |= DP_CONFIGURATION_CTRL_ENHANCED_FRAMING; + + config |= DP_CONFIGURATION_CTRL_P_INTERLACED; /* progressive video */ + + /* sync clock & static Mvid */ + config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN; + config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK; + + dp_catalog_ctrl_config_ctrl(ctrl->catalog, config); +} + +static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl) +{ + u32 cc, tb; + + dp_catalog_ctrl_lane_mapping(ctrl->catalog); + dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); + + dp_ctrl_config_ctrl(ctrl); + + tb = dp_link_get_test_bits_depth(ctrl->link, + ctrl->panel->dp_mode.bpp); + cc = dp_link_get_colorimetry_config(ctrl->link); + dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb); + dp_panel_timing_cfg(ctrl->panel); +} + +/* + * The structure and few functions present below are IP/Hardware + * specific implementation. Most of the implementation will not + * have coding comments + */ +struct tu_algo_data { + s64 lclk_fp; + s64 pclk_fp; + s64 lwidth; + s64 lwidth_fp; + s64 hbp_relative_to_pclk; + s64 hbp_relative_to_pclk_fp; + int nlanes; + int bpp; + int pixelEnc; + int dsc_en; + int async_en; + int bpc; + + uint delay_start_link_extra_pixclk; + int extra_buffer_margin; + s64 ratio_fp; + s64 original_ratio_fp; + + s64 err_fp; + s64 n_err_fp; + s64 n_n_err_fp; + int tu_size; + int tu_size_desired; + int tu_size_minus1; + + int valid_boundary_link; + s64 resulting_valid_fp; + s64 total_valid_fp; + s64 effective_valid_fp; + s64 effective_valid_recorded_fp; + int n_tus; + int n_tus_per_lane; + int paired_tus; + int remainder_tus; + int remainder_tus_upper; + int remainder_tus_lower; + int extra_bytes; + int filler_size; + int delay_start_link; + + int extra_pclk_cycles; + int extra_pclk_cycles_in_link_clk; + s64 ratio_by_tu_fp; + s64 average_valid2_fp; + int new_valid_boundary_link; + int remainder_symbols_exist; + int n_symbols; + s64 n_remainder_symbols_per_lane_fp; + s64 last_partial_tu_fp; + s64 TU_ratio_err_fp; + + int n_tus_incl_last_incomplete_tu; + int extra_pclk_cycles_tmp; + int extra_pclk_cycles_in_link_clk_tmp; + int extra_required_bytes_new_tmp; + int filler_size_tmp; + int lower_filler_size_tmp; + int delay_start_link_tmp; + + bool boundary_moderation_en; + int boundary_mod_lower_err; + int upper_boundary_count; + int lower_boundary_count; + int i_upper_boundary_count; + int i_lower_boundary_count; + int valid_lower_boundary_link; + int even_distribution_BF; + int even_distribution_legacy; + int even_distribution; + int min_hblank_violated; + s64 delay_start_time_fp; + s64 hbp_time_fp; + s64 hactive_time_fp; + s64 diff_abs_fp; + + s64 ratio; +}; + +static int _tu_param_compare(s64 a, s64 b) +{ + u32 a_sign; + u32 b_sign; + s64 a_temp, b_temp, minus_1; + + if (a == b) + return 0; + + minus_1 = drm_fixp_from_fraction(-1, 1); + + a_sign = (a >> 32) & 0x80000000 ? 1 : 0; + + b_sign = (b >> 32) & 0x80000000 ? 1 : 0; + + if (a_sign > b_sign) + return 2; + else if (b_sign > a_sign) + return 1; + + if (!a_sign && !b_sign) { /* positive */ + if (a > b) + return 1; + else + return 2; + } else { /* negative */ + a_temp = drm_fixp_mul(a, minus_1); + b_temp = drm_fixp_mul(b, minus_1); + + if (a_temp > b_temp) + return 2; + else + return 1; + } +} + +static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in, + struct tu_algo_data *tu) +{ + int nlanes = in->nlanes; + int dsc_num_slices = in->num_of_dsc_slices; + int dsc_num_bytes = 0; + int numerator; + s64 pclk_dsc_fp; + s64 dwidth_dsc_fp; + s64 hbp_dsc_fp; + + int tot_num_eoc_symbols = 0; + int tot_num_hor_bytes = 0; + int tot_num_dummy_bytes = 0; + int dwidth_dsc_bytes = 0; + int eoc_bytes = 0; + + s64 temp1_fp, temp2_fp, temp3_fp; + + tu->lclk_fp = drm_fixp_from_fraction(in->lclk, 1); + tu->pclk_fp = drm_fixp_from_fraction(in->pclk_khz, 1000); + tu->lwidth = in->hactive; + tu->hbp_relative_to_pclk = in->hporch; + tu->nlanes = in->nlanes; + tu->bpp = in->bpp; + tu->pixelEnc = in->pixel_enc; + tu->dsc_en = in->dsc_en; + tu->async_en = in->async_en; + tu->lwidth_fp = drm_fixp_from_fraction(in->hactive, 1); + tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1); + + if (tu->pixelEnc == 420) { + temp1_fp = drm_fixp_from_fraction(2, 1); + tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp); + tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp); + tu->hbp_relative_to_pclk_fp = + drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2); + } + + if (tu->pixelEnc == 422) { + switch (tu->bpp) { + case 24: + tu->bpp = 16; + tu->bpc = 8; + break; + case 30: + tu->bpp = 20; + tu->bpc = 10; + break; + default: + tu->bpp = 16; + tu->bpc = 8; + break; + } + } else { + tu->bpc = tu->bpp/3; + } + + if (!in->dsc_en) + goto fec_check; + + temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100); + temp2_fp = drm_fixp_from_fraction(in->bpp, 1); + temp3_fp = drm_fixp_div(temp2_fp, temp1_fp); + temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp); + + temp1_fp = drm_fixp_from_fraction(8, 1); + temp3_fp = drm_fixp_div(temp2_fp, temp1_fp); + + numerator = drm_fixp2int(temp3_fp); + + dsc_num_bytes = numerator / dsc_num_slices; + eoc_bytes = dsc_num_bytes % nlanes; + tot_num_eoc_symbols = nlanes * dsc_num_slices; + tot_num_hor_bytes = dsc_num_bytes * dsc_num_slices; + tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices; + + if (dsc_num_bytes == 0) + pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes); + + dwidth_dsc_bytes = (tot_num_hor_bytes + + tot_num_eoc_symbols + + (eoc_bytes == 0 ? 0 : tot_num_dummy_bytes)); + + dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3); + + temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp); + temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp); + pclk_dsc_fp = temp1_fp; + + temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp); + temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp); + hbp_dsc_fp = temp2_fp; + + /* output */ + tu->pclk_fp = pclk_dsc_fp; + tu->lwidth_fp = dwidth_dsc_fp; + tu->hbp_relative_to_pclk_fp = hbp_dsc_fp; + +fec_check: + if (in->fec_en) { + temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */ + tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp); + } +} + +static void _tu_valid_boundary_calc(struct tu_algo_data *tu) +{ + s64 temp1_fp, temp2_fp, temp, temp1, temp2; + int compare_result_1, compare_result_2, compare_result_3; + + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); + + tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp); + + temp = (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link-1)); + tu->average_valid2_fp = drm_fixp_from_fraction(temp, + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + temp1_fp = drm_fixp_from_fraction(tu->bpp, 8); + temp2_fp = tu->lwidth_fp; + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp); + tu->n_tus = drm_fixp2int(temp2_fp); + if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000) + tu->n_tus += 1; + + temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1); + temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp); + temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1); + temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); + tu->n_remainder_symbols_per_lane_fp = temp2_fp; + + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + tu->last_partial_tu_fp = + drm_fixp_div(tu->n_remainder_symbols_per_lane_fp, + temp1_fp); + + if (tu->n_remainder_symbols_per_lane_fp != 0) + tu->remainder_symbols_exist = 1; + else + tu->remainder_symbols_exist = 0; + + temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes); + tu->n_tus_per_lane = drm_fixp2int(temp1_fp); + + tu->paired_tus = (int)((tu->n_tus_per_lane) / + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count)); + + tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus * + (tu->i_upper_boundary_count + + tu->i_lower_boundary_count); + + if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) { + tu->remainder_tus_upper = tu->i_upper_boundary_count; + tu->remainder_tus_lower = tu->remainder_tus - + tu->i_upper_boundary_count; + } else { + tu->remainder_tus_upper = tu->remainder_tus; + tu->remainder_tus_lower = 0; + } + + temp = tu->paired_tus * (tu->i_upper_boundary_count * + tu->new_valid_boundary_link + + tu->i_lower_boundary_count * + (tu->new_valid_boundary_link - 1)) + + (tu->remainder_tus_upper * + tu->new_valid_boundary_link) + + (tu->remainder_tus_lower * + (tu->new_valid_boundary_link - 1)); + tu->total_valid_fp = drm_fixp_from_fraction(temp, 1); + + if (tu->remainder_symbols_exist) { + temp1_fp = tu->total_valid_fp + + tu->n_remainder_symbols_per_lane_fp; + temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1); + temp2_fp = temp2_fp + tu->last_partial_tu_fp; + temp1_fp = drm_fixp_div(temp1_fp, temp2_fp); + } else { + temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1); + temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp); + } + tu->effective_valid_fp = temp1_fp; + + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); + tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp; + + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp); + tu->n_err_fp = tu->average_valid2_fp - temp2_fp; + + tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0; + + temp1_fp = drm_fixp_from_fraction(tu->bpp, 8); + temp2_fp = tu->lwidth_fp; + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp); + + if (temp2_fp) + tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp); + else + tu->n_tus_incl_last_incomplete_tu = 0; + + temp1 = 0; + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp); + temp1_fp = tu->average_valid2_fp - temp2_fp; + temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1); + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + + if (temp1_fp) + temp1 = drm_fixp2int_ceil(temp1_fp); + + temp = tu->i_upper_boundary_count * tu->nlanes; + temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1); + temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp); + temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp = drm_fixp_from_fraction(temp, 1); + temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); + + if (temp2_fp) + temp2 = drm_fixp2int_ceil(temp2_fp); + else + temp2 = 0; + tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2); + + temp1_fp = drm_fixp_from_fraction(8, tu->bpp); + temp2_fp = drm_fixp_from_fraction( + tu->extra_required_bytes_new_tmp, 1); + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + + if (temp1_fp) + tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp); + else + tu->extra_pclk_cycles_tmp = 0; + + temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1); + temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp); + temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp); + + if (temp1_fp) + tu->extra_pclk_cycles_in_link_clk_tmp = + drm_fixp2int_ceil(temp1_fp); + else + tu->extra_pclk_cycles_in_link_clk_tmp = 0; + + tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link; + + tu->lower_filler_size_tmp = tu->filler_size_tmp + 1; + + tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp + + tu->lower_filler_size_tmp + + tu->extra_buffer_margin; + + temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1); + tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp); + + compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp); + if (compare_result_1 == 2) + compare_result_1 = 1; + else + compare_result_1 = 0; + + compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp); + if (compare_result_2 == 2) + compare_result_2 = 1; + else + compare_result_2 = 0; + + compare_result_3 = _tu_param_compare(tu->hbp_time_fp, + tu->delay_start_time_fp); + if (compare_result_3 == 2) + compare_result_3 = 0; + else + compare_result_3 = 1; + + if (((tu->even_distribution == 1) || + ((tu->even_distribution_BF == 0) && + (tu->even_distribution_legacy == 0))) && + tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 && + compare_result_2 && + (compare_result_1 || (tu->min_hblank_violated == 1)) && + (tu->new_valid_boundary_link - 1) > 0 && + compare_result_3 && + (tu->delay_start_link_tmp <= 1023)) { + tu->upper_boundary_count = tu->i_upper_boundary_count; + tu->lower_boundary_count = tu->i_lower_boundary_count; + tu->err_fp = tu->n_n_err_fp; + tu->boundary_moderation_en = true; + tu->tu_size_desired = tu->tu_size; + tu->valid_boundary_link = tu->new_valid_boundary_link; + tu->effective_valid_recorded_fp = tu->effective_valid_fp; + tu->even_distribution_BF = 1; + tu->delay_start_link = tu->delay_start_link_tmp; + } else if (tu->boundary_mod_lower_err == 0) { + compare_result_1 = _tu_param_compare(tu->n_n_err_fp, + tu->diff_abs_fp); + if (compare_result_1 == 2) + tu->boundary_mod_lower_err = 1; + } +} + +static void _dp_ctrl_calc_tu(struct dp_tu_calc_input *in, + struct dp_vc_tu_mapping_table *tu_table) +{ + struct tu_algo_data tu; + int compare_result_1, compare_result_2; + u64 temp = 0; + s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0; + + s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */ + s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */ + s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */ + s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000); + + u8 DP_BRUTE_FORCE = 1; + s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */ + uint EXTRA_PIXCLK_CYCLE_DELAY = 4; + uint HBLANK_MARGIN = 4; + + memset(&tu, 0, sizeof(tu)); + + dp_panel_update_tu_timings(in, &tu); + + tu.err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */ + + temp1_fp = drm_fixp_from_fraction(4, 1); + temp2_fp = drm_fixp_mul(temp1_fp, tu.lclk_fp); + temp_fp = drm_fixp_div(temp2_fp, tu.pclk_fp); + tu.extra_buffer_margin = drm_fixp2int_ceil(temp_fp); + + temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); + temp2_fp = drm_fixp_mul(tu.pclk_fp, temp1_fp); + temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); + temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); + tu.ratio_fp = drm_fixp_div(temp2_fp, tu.lclk_fp); + + tu.original_ratio_fp = tu.ratio_fp; + tu.boundary_moderation_en = false; + tu.upper_boundary_count = 0; + tu.lower_boundary_count = 0; + tu.i_upper_boundary_count = 0; + tu.i_lower_boundary_count = 0; + tu.valid_lower_boundary_link = 0; + tu.even_distribution_BF = 0; + tu.even_distribution_legacy = 0; + tu.even_distribution = 0; + tu.delay_start_time_fp = 0; + + tu.err_fp = drm_fixp_from_fraction(1000, 1); + tu.n_err_fp = 0; + tu.n_n_err_fp = 0; + + tu.ratio = drm_fixp2int(tu.ratio_fp); + temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); + div64_u64_rem(tu.lwidth_fp, temp1_fp, &temp2_fp); + if (temp2_fp != 0 && + !tu.ratio && tu.dsc_en == 0) { + tu.ratio_fp = drm_fixp_mul(tu.ratio_fp, RATIO_SCALE_fp); + tu.ratio = drm_fixp2int(tu.ratio_fp); + if (tu.ratio) + tu.ratio_fp = drm_fixp_from_fraction(1, 1); + } + + if (tu.ratio > 1) + tu.ratio = 1; + + if (tu.ratio == 1) + goto tu_size_calc; + + compare_result_1 = _tu_param_compare(tu.ratio_fp, const_p49_fp); + if (!compare_result_1 || compare_result_1 == 1) + compare_result_1 = 1; + else + compare_result_1 = 0; + + compare_result_2 = _tu_param_compare(tu.ratio_fp, const_p56_fp); + if (!compare_result_2 || compare_result_2 == 2) + compare_result_2 = 1; + else + compare_result_2 = 0; + + if (tu.dsc_en && compare_result_1 && compare_result_2) { + HBLANK_MARGIN += 4; + DRM_DEBUG_DP("Info: increase HBLANK_MARGIN to %d\n", + HBLANK_MARGIN); + } + +tu_size_calc: + for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) { + temp1_fp = drm_fixp_from_fraction(tu.tu_size, 1); + temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); + temp = drm_fixp2int_ceil(temp2_fp); + temp1_fp = drm_fixp_from_fraction(temp, 1); + tu.n_err_fp = temp1_fp - temp2_fp; + + if (tu.n_err_fp < tu.err_fp) { + tu.err_fp = tu.n_err_fp; + tu.tu_size_desired = tu.tu_size; + } + } + + tu.tu_size_minus1 = tu.tu_size_desired - 1; + + temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); + temp2_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); + tu.valid_boundary_link = drm_fixp2int_ceil(temp2_fp); + + temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); + temp2_fp = tu.lwidth_fp; + temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp); + + temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1); + temp2_fp = drm_fixp_div(temp2_fp, temp1_fp); + tu.n_tus = drm_fixp2int(temp2_fp); + if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000) + tu.n_tus += 1; + + tu.even_distribution_legacy = tu.n_tus % tu.nlanes == 0 ? 1 : 0; + DRM_DEBUG_DP("Info: n_sym = %d, num_of_tus = %d\n", + tu.valid_boundary_link, tu.n_tus); + + temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); + temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp); + temp1_fp = drm_fixp_from_fraction(tu.valid_boundary_link, 1); + temp2_fp = temp1_fp - temp2_fp; + temp1_fp = drm_fixp_from_fraction(tu.n_tus + 1, 1); + temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); + + temp = drm_fixp2int(temp2_fp); + if (temp && temp2_fp) + tu.extra_bytes = drm_fixp2int_ceil(temp2_fp); + else + tu.extra_bytes = 0; + + temp1_fp = drm_fixp_from_fraction(tu.extra_bytes, 1); + temp2_fp = drm_fixp_from_fraction(8, tu.bpp); + temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp); + + if (temp && temp1_fp) + tu.extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp); + else + tu.extra_pclk_cycles = drm_fixp2int(temp1_fp); + + temp1_fp = drm_fixp_div(tu.lclk_fp, tu.pclk_fp); + temp2_fp = drm_fixp_from_fraction(tu.extra_pclk_cycles, 1); + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + + if (temp1_fp) + tu.extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp); + else + tu.extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp); + + tu.filler_size = tu.tu_size_desired - tu.valid_boundary_link; + + temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); + tu.ratio_by_tu_fp = drm_fixp_mul(tu.ratio_fp, temp1_fp); + + tu.delay_start_link = tu.extra_pclk_cycles_in_link_clk + + tu.filler_size + tu.extra_buffer_margin; + + tu.resulting_valid_fp = + drm_fixp_from_fraction(tu.valid_boundary_link, 1); + + temp1_fp = drm_fixp_from_fraction(tu.tu_size_desired, 1); + temp2_fp = drm_fixp_div(tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + + temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1); + temp1_fp = tu.hbp_relative_to_pclk_fp - temp1_fp; + tu.hbp_time_fp = drm_fixp_div(temp1_fp, tu.pclk_fp); + + temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1); + tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp); + + compare_result_1 = _tu_param_compare(tu.hbp_time_fp, + tu.delay_start_time_fp); + if (compare_result_1 == 2) /* if (hbp_time_fp < delay_start_time_fp) */ + tu.min_hblank_violated = 1; + + tu.hactive_time_fp = drm_fixp_div(tu.lwidth_fp, tu.pclk_fp); + + compare_result_2 = _tu_param_compare(tu.hactive_time_fp, + tu.delay_start_time_fp); + if (compare_result_2 == 2) + tu.min_hblank_violated = 1; + + tu.delay_start_time_fp = 0; + + /* brute force */ + + tu.delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY; + tu.diff_abs_fp = tu.resulting_valid_fp - tu.ratio_by_tu_fp; + + temp = drm_fixp2int(tu.diff_abs_fp); + if (!temp && tu.diff_abs_fp <= 0xffff) + tu.diff_abs_fp = 0; + + /* if(diff_abs < 0) diff_abs *= -1 */ + if (tu.diff_abs_fp < 0) + tu.diff_abs_fp = drm_fixp_mul(tu.diff_abs_fp, -1); + + tu.boundary_mod_lower_err = 0; + if ((tu.diff_abs_fp != 0 && + ((tu.diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) || + (tu.even_distribution_legacy == 0) || + (DP_BRUTE_FORCE == 1))) || + (tu.min_hblank_violated == 1)) { + do { + tu.err_fp = drm_fixp_from_fraction(1000, 1); + + temp1_fp = drm_fixp_div(tu.lclk_fp, tu.pclk_fp); + temp2_fp = drm_fixp_from_fraction( + tu.delay_start_link_extra_pixclk, 1); + temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp); + + if (temp1_fp) + tu.extra_buffer_margin = + drm_fixp2int_ceil(temp1_fp); + else + tu.extra_buffer_margin = 0; + + temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); + temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp); + + if (temp1_fp) + tu.n_symbols = drm_fixp2int_ceil(temp1_fp); + else + tu.n_symbols = 0; + + for (tu.tu_size = 32; tu.tu_size <= 64; tu.tu_size++) { + for (tu.i_upper_boundary_count = 1; + tu.i_upper_boundary_count <= 15; + tu.i_upper_boundary_count++) { + for (tu.i_lower_boundary_count = 1; + tu.i_lower_boundary_count <= 15; + tu.i_lower_boundary_count++) { + _tu_valid_boundary_calc(&tu); + } + } + } + tu.delay_start_link_extra_pixclk--; + } while (tu.boundary_moderation_en != true && + tu.boundary_mod_lower_err == 1 && + tu.delay_start_link_extra_pixclk != 0); + + if (tu.boundary_moderation_en == true) { + temp1_fp = drm_fixp_from_fraction( + (tu.upper_boundary_count * + tu.valid_boundary_link + + tu.lower_boundary_count * + (tu.valid_boundary_link - 1)), 1); + temp2_fp = drm_fixp_from_fraction( + (tu.upper_boundary_count + + tu.lower_boundary_count), 1); + tu.resulting_valid_fp = + drm_fixp_div(temp1_fp, temp2_fp); + + temp1_fp = drm_fixp_from_fraction( + tu.tu_size_desired, 1); + tu.ratio_by_tu_fp = + drm_fixp_mul(tu.original_ratio_fp, temp1_fp); + + tu.valid_lower_boundary_link = + tu.valid_boundary_link - 1; + + temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); + temp1_fp = drm_fixp_mul(tu.lwidth_fp, temp1_fp); + temp2_fp = drm_fixp_div(temp1_fp, + tu.resulting_valid_fp); + tu.n_tus = drm_fixp2int(temp2_fp); + + tu.tu_size_minus1 = tu.tu_size_desired - 1; + tu.even_distribution_BF = 1; + + temp1_fp = + drm_fixp_from_fraction(tu.tu_size_desired, 1); + temp2_fp = + drm_fixp_div(tu.resulting_valid_fp, temp1_fp); + tu.TU_ratio_err_fp = temp2_fp - tu.original_ratio_fp; + } + } + + temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu.lwidth_fp); + + if (temp2_fp) + temp = drm_fixp2int_ceil(temp2_fp); + else + temp = 0; + + temp1_fp = drm_fixp_from_fraction(tu.nlanes, 1); + temp2_fp = drm_fixp_mul(tu.original_ratio_fp, temp1_fp); + temp1_fp = drm_fixp_from_fraction(tu.bpp, 8); + temp2_fp = drm_fixp_div(temp1_fp, temp2_fp); + temp1_fp = drm_fixp_from_fraction(temp, 1); + temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp); + temp = drm_fixp2int(temp2_fp); + + if (tu.async_en) + tu.delay_start_link += (int)temp; + + temp1_fp = drm_fixp_from_fraction(tu.delay_start_link, 1); + tu.delay_start_time_fp = drm_fixp_div(temp1_fp, tu.lclk_fp); + + /* OUTPUTS */ + tu_table->valid_boundary_link = tu.valid_boundary_link; + tu_table->delay_start_link = tu.delay_start_link; + tu_table->boundary_moderation_en = tu.boundary_moderation_en; + tu_table->valid_lower_boundary_link = tu.valid_lower_boundary_link; + tu_table->upper_boundary_count = tu.upper_boundary_count; + tu_table->lower_boundary_count = tu.lower_boundary_count; + tu_table->tu_size_minus1 = tu.tu_size_minus1; + + DRM_DEBUG_DP("TU: valid_boundary_link: %d\n", + tu_table->valid_boundary_link); + DRM_DEBUG_DP("TU: delay_start_link: %d\n", + tu_table->delay_start_link); + DRM_DEBUG_DP("TU: boundary_moderation_en: %d\n", + tu_table->boundary_moderation_en); + DRM_DEBUG_DP("TU: valid_lower_boundary_link: %d\n", + tu_table->valid_lower_boundary_link); + DRM_DEBUG_DP("TU: upper_boundary_count: %d\n", + tu_table->upper_boundary_count); + DRM_DEBUG_DP("TU: lower_boundary_count: %d\n", + tu_table->lower_boundary_count); + DRM_DEBUG_DP("TU: tu_size_minus1: %d\n", tu_table->tu_size_minus1); +} + +static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl, + struct dp_vc_tu_mapping_table *tu_table) +{ + struct dp_tu_calc_input in; + struct drm_display_mode *drm_mode; + + drm_mode = &ctrl->panel->dp_mode.drm_mode; + + in.lclk = ctrl->link->link_params.rate / 1000; + in.pclk_khz = drm_mode->clock; + in.hactive = drm_mode->hdisplay; + in.hporch = drm_mode->htotal - drm_mode->hdisplay; + in.nlanes = ctrl->link->link_params.num_lanes; + in.bpp = ctrl->panel->dp_mode.bpp; + in.pixel_enc = 444; + in.dsc_en = 0; + in.async_en = 0; + in.fec_en = 0; + in.num_of_dsc_slices = 0; + in.compress_ratio = 100; + + _dp_ctrl_calc_tu(&in, tu_table); +} + +static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl) +{ + u32 dp_tu = 0x0; + u32 valid_boundary = 0x0; + u32 valid_boundary2 = 0x0; + struct dp_vc_tu_mapping_table tu_calc_table; + + dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table); + + dp_tu |= tu_calc_table.tu_size_minus1; + valid_boundary |= tu_calc_table.valid_boundary_link; + valid_boundary |= (tu_calc_table.delay_start_link << 16); + + valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1); + valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16); + valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20); + + if (tu_calc_table.boundary_moderation_en) + valid_boundary2 |= BIT(0); + + pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n", + dp_tu, valid_boundary, valid_boundary2); + + dp_catalog_ctrl_update_transfer_unit(ctrl->catalog, + dp_tu, valid_boundary, valid_boundary2); +} + +static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + if (!wait_for_completion_timeout(&ctrl->video_comp, + WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES)) { + DRM_ERROR("Link Train timedout\n"); + ret = -ETIMEDOUT; + } + return ret; +} + +static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) +{ + struct dp_link *link = ctrl->link; + int ret = 0, lane, lane_cnt; + u8 buf[4]; + u32 max_level_reached = 0; + u32 voltage_swing_level = link->phy_params.v_level; + u32 pre_emphasis_level = link->phy_params.p_level; + + ret = dp_catalog_ctrl_update_vx_px(ctrl->catalog, + voltage_swing_level, pre_emphasis_level); + + if (ret) + return ret; + + if (voltage_swing_level > DP_TRAIN_VOLTAGE_SWING_MAX) { + DRM_DEBUG_DP("max. voltage swing level reached %d\n", + voltage_swing_level); + max_level_reached |= DP_TRAIN_MAX_SWING_REACHED; + } + + if (pre_emphasis_level == DP_TRAIN_PRE_EMPHASIS_MAX) { + DRM_DEBUG_DP("max. pre-emphasis level reached %d\n", + pre_emphasis_level); + max_level_reached |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + } + + pre_emphasis_level <<= DP_TRAIN_PRE_EMPHASIS_SHIFT; + + lane_cnt = ctrl->link->link_params.num_lanes; + for (lane = 0; lane < lane_cnt; lane++) + buf[lane] = voltage_swing_level | pre_emphasis_level + | max_level_reached; + + DRM_DEBUG_DP("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 (ret == lane_cnt) + ret = 0; + + return ret; +} + +static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl, + u8 pattern) +{ + u8 buf; + int ret = 0; + + DRM_DEBUG_DP("sink: pattern=%x\n", pattern); + + buf = pattern; + ret = drm_dp_dpcd_writeb(ctrl->aux, + DP_TRAINING_PATTERN_SET, buf); + return ret == 1; +} + +static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl, + u8 *link_status) +{ + int len = 0; + u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS; + u32 link_status_read_max_retries = 100; + + while (--link_status_read_max_retries) { + 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); + return len; + } + + if (!(link_status[offset] & DP_LINK_STATUS_UPDATED)) + return 0; + } + + return -ETIMEDOUT; +} + +static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) +{ + int tries, old_v_level, ret = 0; + u8 link_status[DP_LINK_STATUS_SIZE]; + int const maximum_retries = 5; + + dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + + ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, DP_TRAINING_PATTERN_1); + if (ret) + return ret; + dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | + DP_LINK_SCRAMBLING_DISABLE); + ret = dp_ctrl_update_vx_px(ctrl); + 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->panel->dpcd); + + ret = dp_ctrl_read_link_status(ctrl, link_status); + if (ret) + return ret; + + if (drm_dp_clock_recovery_ok(link_status, + ctrl->link->link_params.num_lanes)) { + return ret; + } + + if (ctrl->link->phy_params.v_level > + DP_TRAIN_VOLTAGE_SWING_MAX) { + DRM_ERROR_RATELIMITED("max v_level reached\n"); + return -EAGAIN; + } + + if (old_v_level != ctrl->link->phy_params.v_level) { + tries = 0; + old_v_level = ctrl->link->phy_params.v_level; + } + + DRM_DEBUG_DP("clock recovery not done, adjusting vx px\n"); + + dp_link_adjust_levels(ctrl->link, link_status); + ret = dp_ctrl_update_vx_px(ctrl); + if (ret) + return ret; + } + + DRM_ERROR("max tries reached\n"); + return -ETIMEDOUT; +} + +static void dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) +{ + switch (ctrl->link->link_params.rate) { + case 810000: + ctrl->link->link_params.rate = 540000; + break; + case 540000: + ctrl->link->link_params.rate = 270000; + break; + case 270000: + case 162000: + default: + ctrl->link->link_params.rate = 162000; + break; + }; + + DRM_DEBUG_DP("new rate=0x%x\n", ctrl->link->link_params.rate); +} + +static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) +{ + dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE); + drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); +} + +static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) +{ + int tries = 0, ret = 0; + char pattern; + int const maximum_retries = 5; + u8 link_status[DP_LINK_STATUS_SIZE]; + + dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + + if (drm_dp_tps3_supported(ctrl->panel->dpcd)) + pattern = DP_TRAINING_PATTERN_3; + else + pattern = DP_TRAINING_PATTERN_2; + + ret = dp_ctrl_update_vx_px(ctrl); + if (ret) + return ret; + + ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, pattern); + if (ret) + return ret; + + dp_ctrl_train_pattern_set(ctrl, pattern | DP_RECOVERED_CLOCK_OUT_EN); + + for (tries = 0; tries <= maximum_retries; tries++) { + drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); + + ret = dp_ctrl_read_link_status(ctrl, link_status); + if (ret) + return ret; + + if (drm_dp_channel_eq_ok(link_status, + ctrl->link->link_params.num_lanes)) + return ret; + + dp_link_adjust_levels(ctrl->link, link_status); + ret = dp_ctrl_update_vx_px(ctrl); + if (ret) + return ret; + + } + + return -ETIMEDOUT; +} + +static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + u8 encoding = DP_SET_ANSI_8B10B; + struct dp_link_info link_info = {0}; + + ctrl->link->phy_params.p_level = 0; + ctrl->link->phy_params.v_level = 0; + + dp_ctrl_config_ctrl(ctrl); + + link_info.num_lanes = ctrl->link->link_params.num_lanes; + link_info.rate = ctrl->link->link_params.rate; + link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING; + + dp_aux_link_configure(ctrl->aux, &link_info); + drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, + &encoding, 1); + + ret = dp_ctrl_link_train_1(ctrl); + if (ret) { + DRM_ERROR("link training #1 failed. ret=%d\n", ret); + goto end; + } + + /* print success info as this is a result of user initiated action */ + DRM_DEBUG_DP("link training #1 successful\n"); + + ret = dp_ctrl_link_training_2(ctrl); + if (ret) { + DRM_ERROR("link training #2 failed. ret=%d\n", ret); + goto end; + } + + /* print success info as this is a result of user initiated action */ + DRM_DEBUG_DP("link training #2 successful\n"); + +end: + dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + + dp_ctrl_clear_training_pattern(ctrl); + return ret; +} + +static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train) +{ + bool mainlink_ready = false; + int ret = 0; + + dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); + + ret = dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, false); + if (ret) + return ret; + + if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) + return ret; + + if (train) { + /* + * As part of previous calls, DP controller state might have + * transitioned to PUSH_IDLE. In order to start transmitting + * a link training pattern, we have to first do soft reset. + */ + dp_catalog_ctrl_reset(ctrl->catalog); + + ret = dp_ctrl_link_train(ctrl); + if (ret) + return ret; + } + + /* + * Set up transfer unit values and set controller state to send + * video. + */ + dp_ctrl_setup_tr_unit(ctrl); + dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + + ret = dp_ctrl_wait4video_ready(ctrl); + if (ret) + return ret; + + mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog); + DRM_DEBUG_DP("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); + return ret; +} + +static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, + char *name, u32 rate) +{ + u32 num = ctrl->parser->mp[DP_CTRL_PM].num_clk; + struct dss_clk *cfg = ctrl->parser->mp[DP_CTRL_PM].clk_config; + + while (num && strcmp(cfg->clk_name, name)) { + num--; + cfg++; + } + + DRM_DEBUG_DP("setting rate=%d on clk=%s\n", rate, name); + + if (num) + cfg->rate = rate; + else + DRM_ERROR("%s clock doesn't exit to set rate %d\n", + name, rate); +} + +static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + dp_power_set_link_clk_parent(ctrl->power); + + dp_ctrl_set_clock_rate(ctrl, "ctrl_link", + ctrl->link->link_params.rate); + + dp_ctrl_set_clock_rate(ctrl, "stream_pixel", + ctrl->dp_ctrl.pixel_rate); + + ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true); + if (ret) + DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); + + return ret; +} + +int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip) +{ + struct dp_ctrl_private *ctrl; + + if (!dp_ctrl) { + DRM_ERROR("Invalid input data\n"); + return -EINVAL; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + ctrl->dp_ctrl.orientation = flip; + + dp_catalog_ctrl_usb_reset(ctrl->catalog, flip); + dp_catalog_ctrl_phy_reset(ctrl->catalog); + dp_catalog_ctrl_enable_irq(ctrl->catalog, true); + + return 0; +} + +/** + * dp_ctrl_host_deinit() - Uninitialize DP controller + * @dp_ctrl: Display Port Driver data + * + * Perform required steps to uninitialize DP controller + * and its resources. + */ +void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + + if (!dp_ctrl) { + DRM_ERROR("Invalid input data\n"); + return; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + dp_catalog_ctrl_enable_irq(ctrl->catalog, false); + + DRM_DEBUG_DP("Host deinitialized successfully\n"); +} + +static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) +{ + u8 *dpcd = ctrl->panel->dpcd; + u32 edid_quirks = 0; + + edid_quirks = drm_dp_get_edid_quirks(ctrl->panel->edid); + /* + * For better interop experience, used a fixed NVID=0x8000 + * whenever connected to a VGA dongle downstream. + */ + if (drm_dp_is_branch(dpcd)) + return (drm_dp_has_quirk(&ctrl->panel->desc, edid_quirks, + DP_DPCD_QUIRK_CONSTANT_N)); + + return false; +} + +static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + dp_catalog_ctrl_phy_lane_cfg(ctrl->catalog, + ctrl->dp_ctrl.orientation, ctrl->link->link_params.num_lanes); + /* + * Disable and re-enable the mainlink clock since the + * link clock might have been adjusted as part of the + * link maintenance. + */ + ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + if (ret) { + DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); + return ret; + } + /* hw recommended delay before re-enabling clocks */ + msleep(20); + + ret = dp_ctrl_enable_mainlink_clocks(ctrl); + if (ret) { + DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret); + return ret; + } + + dp_ctrl_configure_source_params(ctrl); + dp_catalog_ctrl_config_msa(ctrl->catalog, + ctrl->link->link_params.rate, + ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl)); + reinit_completion(&ctrl->idle_comp); + + return ret; +} + +static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + int tries; + + dp_ctrl_push_idle(&ctrl->dp_ctrl); + dp_catalog_ctrl_reset(ctrl->catalog); + + ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + + for (tries = 0; tries < 10; tries++) { + ret = dp_ctrl_reinitialize_mainlink(ctrl); + if (ret) { + DRM_ERROR("Failed to reinitialize mainlink. ret=%d\n", + ret); + break; + } + + ret = dp_ctrl_setup_main_link(ctrl, true); + if (ret == -EAGAIN) /* try with lower link rate */ + dp_ctrl_link_rate_down_shift(ctrl); + } + return ret; +} + +static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + if (!ctrl->link->phy_params.phy_test_pattern_sel) { + DRM_DEBUG_DP("no test pattern selected by sink\n"); + return ret; + } + + dp_ctrl_push_idle(&ctrl->dp_ctrl); + /* + * The global reset will need DP link related clocks to be + * running. Add the global reset just before disabling the + * link clocks and core clocks. + */ + dp_catalog_ctrl_reset(ctrl->catalog); + ret = dp_ctrl_off(&ctrl->dp_ctrl); + if (ret) { + DRM_ERROR("failed to disable DP controller\n"); + return ret; + } + + ret = dp_ctrl_on(&ctrl->dp_ctrl); + if (ret) + DRM_ERROR("failed to enable DP controller\n"); + + return ret; +} + +static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) +{ + bool success = false; + u32 pattern_sent = 0x0; + u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel; + + DRM_DEBUG_DP("request: 0x%x\n", pattern_requested); + + if (dp_catalog_ctrl_update_vx_px(ctrl->catalog, + ctrl->link->phy_params.v_level, + ctrl->link->phy_params.p_level)) { + DRM_ERROR("Failed to set v/p levels\n"); + return false; + } + dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); + dp_link_send_test_response(ctrl->link); + + pattern_sent = dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); + + switch (pattern_sent) { + case MR_LINK_TRAINING1: + success = pattern_requested == + DP_LINK_QUAL_PATTERN_D10_2; + break; + case MR_LINK_SYMBOL_ERM: + success = (pattern_requested == + DP_LINK_QUAL_PATTERN_ERROR_RATE) + || (pattern_requested == + DP_LINK_QUAL_PATTERN_HBR2_EYE); + break; + case MR_LINK_PRBS7: + success = pattern_requested == DP_LINK_QUAL_PATTERN_PRBS7; + break; + case MR_LINK_CUSTOM80: + success = pattern_requested == + DP_LINK_QUAL_PATTERN_80BIT_CUSTOM; + break; + default: + success = false; + } + + DRM_DEBUG_DP("%s: test->0x%x\n", success ? "success" : "failed", + pattern_requested); + return success; +} + +void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + u32 sink_request = 0x0; + + if (!dp_ctrl) { + DRM_ERROR("invalid input\n"); + return; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + sink_request = ctrl->link->sink_request; + + if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { + DRM_DEBUG_DP("PHY_TEST_PATTERN request\n"); + if (dp_ctrl_process_phy_test_request(ctrl)) { + DRM_ERROR("process phy_test_req failed\n"); + return; + } + } + + if (sink_request & DP_LINK_STATUS_UPDATED) + if (dp_ctrl_link_maintenance(ctrl)) { + DRM_ERROR("LM failed: STATUS_UPDATED\n"); + return; + } + + + if (sink_request & DP_TEST_LINK_TRAINING) { + dp_link_send_test_response(ctrl->link); + if (dp_ctrl_link_maintenance(ctrl)) { + DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); + return; + } + } +} + +int dp_ctrl_on(struct dp_ctrl *dp_ctrl) +{ + int rc = 0; + struct dp_ctrl_private *ctrl; + u32 rate = 0; + u32 link_train_max_retries = 10; + u32 const phy_cts_pixel_clk_khz = 148500; + + if (!dp_ctrl) + return -EINVAL; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + rate = ctrl->panel->link_info.rate; + + dp_power_clk_enable(ctrl->power, DP_CORE_PM, true); + dp_catalog_ctrl_hpd_config(ctrl->catalog, true); + + if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { + DRM_DEBUG_DP("using phy test link parameters\n"); + if (!ctrl->panel->dp_mode.drm_mode.clock) + ctrl->dp_ctrl.pixel_rate = phy_cts_pixel_clk_khz; + } else { + ctrl->link->link_params.rate = rate; + ctrl->link->link_params.num_lanes = + ctrl->panel->link_info.num_lanes; + ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + } + + DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n", + ctrl->link->link_params.rate, + ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate); + + dp_catalog_ctrl_phy_lane_cfg(ctrl->catalog, + ctrl->dp_ctrl.orientation, + ctrl->link->link_params.num_lanes); + + rc = dp_ctrl_enable_mainlink_clocks(ctrl); + if (rc) + return rc; + + while (--link_train_max_retries && + !atomic_read(&ctrl->dp_ctrl.aborted)) { + rc = dp_ctrl_reinitialize_mainlink(ctrl); + if (rc) { + DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", + rc); + break; + } + rc = dp_ctrl_setup_main_link(ctrl, true); + if (!rc) + break; + /* try with lower link rate */ + dp_ctrl_link_rate_down_shift(ctrl); + } + + if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) + dp_ctrl_send_phy_test_pattern(ctrl); + + return rc; +} + +int dp_ctrl_off(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + int ret = 0; + + if (!dp_ctrl) + return -EINVAL; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + dp_catalog_ctrl_reset(ctrl->catalog); + ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); + if (ret) { + DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); + return ret; + } + + DRM_DEBUG_DP("DP off done\n"); + return ret; +} + +void dp_ctrl_isr(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + u32 isr; + + if (!dp_ctrl) + return; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + isr = dp_catalog_ctrl_get_interrupt(ctrl->catalog); + + if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) { + DRM_DEBUG_DP("dp_video_ready\n"); + complete(&ctrl->video_comp); + } + + if (isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) { + DRM_DEBUG_DP("idle_patterns_sent\n"); + complete(&ctrl->idle_comp); + } +} + +struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, + struct dp_panel *panel, struct drm_dp_aux *aux, + struct dp_power *power, struct dp_catalog *catalog, + struct dp_parser *parser) +{ + struct dp_ctrl_private *ctrl; + + if (!dev || !panel || !aux || + !link || !catalog) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-EINVAL); + } + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) { + DRM_ERROR("Mem allocation failure\n"); + return ERR_PTR(-ENOMEM); + } + + init_completion(&ctrl->idle_comp); + init_completion(&ctrl->video_comp); + mutex_init(&ctrl->push_idle_mutex); + + /* in parameters */ + ctrl->parser = parser; + ctrl->panel = panel; + ctrl->power = power; + ctrl->aux = aux; + ctrl->link = link; + ctrl->catalog = catalog; + ctrl->dev = dev; + + return &ctrl->dp_ctrl; +} + +void dp_ctrl_put(struct dp_ctrl *dp_ctrl) +{ +} diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h new file mode 100644 index 0000000000000..94713a0daff00 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_CTRL_H_ +#define _DP_CTRL_H_ + +#include "dp_aux.h" +#include "dp_panel.h" +#include "dp_link.h" +#include "dp_parser.h" +#include "dp_power.h" +#include "dp_catalog.h" + +struct dp_ctrl { + bool orientation; + atomic_t aborted; + u32 pixel_rate; +}; + +int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip); +void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl); +int dp_ctrl_on(struct dp_ctrl *dp_ctrl); +int dp_ctrl_off(struct dp_ctrl *dp_ctrl); +void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); +void dp_ctrl_isr(struct dp_ctrl *dp_ctrl); +void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl); +struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, + struct dp_panel *panel, struct drm_dp_aux *aux, + struct dp_power *power, struct dp_catalog *catalog, + struct dp_parser *parser); +void dp_ctrl_put(struct dp_ctrl *dp_ctrl); + +#endif /* _DP_CTRL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c new file mode 100644 index 0000000000000..ff381807e350a --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -0,0 +1,936 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/debugfs.h> +#include <linux/component.h> +#include <linux/of_irq.h> + +#include "msm_drv.h" +#include "msm_kms.h" +#include "dp_hpd.h" +#include "dp_parser.h" +#include "dp_power.h" +#include "dp_catalog.h" +#include "dp_aux.h" +#include "dp_link.h" +#include "dp_panel.h" +#include "dp_ctrl.h" +#include "dp_display.h" +#include "dp_drm.h" + +static struct msm_dp *g_dp_display; +#define HPD_STRING_SIZE 30 + +struct dp_display_private { + char *name; + int irq; + + /* state variables */ + bool core_initialized; + bool power_on; + bool hpd_irq_on; + bool audio_supported; + + struct platform_device *pdev; + struct dentry *root; + struct completion notification_comp; + + struct dp_usbpd *usbpd; + struct dp_parser *parser; + struct dp_power *power; + struct dp_catalog *catalog; + struct drm_dp_aux *aux; + struct dp_link *link; + struct dp_panel *panel; + struct dp_ctrl *ctrl; + + struct dp_usbpd_cb usbpd_cb; + struct dp_display_mode dp_mode; + struct msm_dp dp_display; +}; + +static const struct of_device_id dp_dt_match[] = { + {.compatible = "qcom,sc7180-dp"}, + {} +}; + +static irqreturn_t dp_display_irq(int irq, void *dev_id) +{ + struct dp_display_private *dp = dev_id; + + /* DP controller isr */ + dp_ctrl_isr(dp->ctrl); + + /* DP aux isr */ + dp_aux_isr(dp->aux); + + return IRQ_HANDLED; +} + +static int dp_display_bind(struct device *dev, struct device *master, + void *data) +{ + int rc = 0; + struct dp_display_private *dp; + struct drm_device *drm; + struct msm_drm_private *priv; + struct platform_device *pdev = to_platform_device(dev); + + drm = dev_get_drvdata(master); + + dp = platform_get_drvdata(pdev); + if (!dp) { + DRM_ERROR("DP driver bind failed. Invalid driver data\n"); + return -EINVAL; + } + + dp->dp_display.drm_dev = drm; + priv = drm->dev_private; + priv->dp = &(dp->dp_display); + + rc = dp->parser->parse(dp->parser); + if (rc) { + DRM_ERROR("device tree parsing failed\n"); + goto end; + } + + rc = dp_aux_register(dp->aux); + if (rc) { + DRM_ERROR("DRM DP AUX register failed\n"); + goto end; + } + + rc = dp_power_client_init(dp->power); + if (rc) { + DRM_ERROR("Power client create failed\n"); + goto end; + } + +end: + return rc; +} + +static void dp_display_unbind(struct device *dev, struct device *master, + void *data) +{ + struct dp_display_private *dp; + struct platform_device *pdev = to_platform_device(dev); + struct drm_device *drm = dev_get_drvdata(master); + struct msm_drm_private *priv = drm->dev_private; + + dp = platform_get_drvdata(pdev); + if (!dp) { + DRM_ERROR("Invalid DP driver data\n"); + return; + } + + dp_power_client_deinit(dp->power); + dp_aux_unregister(dp->aux); + priv->dp = NULL; +} + +static const struct component_ops dp_display_comp_ops = { + .bind = dp_display_bind, + .unbind = dp_display_unbind, +}; + +static bool dp_display_is_ds_bridge(struct dp_panel *panel) +{ + return (panel->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT); +} + +static bool dp_display_is_sink_count_zero(struct dp_display_private *dp) +{ + return dp_display_is_ds_bridge(dp->panel) && + (dp->link->sink_count == 0); +} + +static void dp_display_send_hpd_event(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + struct drm_connector *connector; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + connector = dp->dp_display.connector; + drm_helper_hpd_irq_event(connector->dev); +} + +static int dp_display_send_hpd_notification(struct dp_display_private *dp, + bool hpd) +{ + static bool encoder_mode_set; + struct msm_drm_private *priv = dp->dp_display.drm_dev->dev_private; + struct msm_kms *kms = priv->kms; + + mutex_lock(&dp->dp_display.connect_mutex); + if ((hpd && dp->dp_display.is_connected) || + (!hpd && !dp->dp_display.is_connected)) { + DRM_DEBUG_DP("HPD already %s\n", (hpd ? "on" : "off")); + mutex_unlock(&dp->dp_display.connect_mutex); + return 0; + } + + /* reset video pattern flag on disconnect */ + if (!hpd) + dp->panel->video_test = false; + + dp->dp_display.is_connected = hpd; + reinit_completion(&dp->notification_comp); + + if (dp->dp_display.is_connected && dp->dp_display.encoder + && !encoder_mode_set + && kms->funcs->set_encoder_mode) { + kms->funcs->set_encoder_mode(kms, + dp->dp_display.encoder, false); + DRM_DEBUG_DP("set_encoder_mode() Completed\n"); + encoder_mode_set = true; + } + + dp_display_send_hpd_event(&dp->dp_display); + + if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) { + pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); + mutex_unlock(&dp->dp_display.connect_mutex); + return -EINVAL; + } + + mutex_unlock(&dp->dp_display.connect_mutex); + return 0; +} + +static int dp_display_process_hpd_high(struct dp_display_private *dp) +{ + int rc = 0; + struct edid *edid; + + dp_aux_init(dp->aux); + + if (dp->link->psm_enabled) + goto notify; + + dp->panel->max_dp_lanes = dp->parser->max_dp_lanes; + + rc = dp_panel_read_sink_caps(dp->panel, dp->dp_display.connector); + if (rc) + goto notify; + + dp_link_process_request(dp->link); + + if (dp_display_is_sink_count_zero(dp)) { + DRM_DEBUG_DP("no downstream devices connected\n"); + rc = -EINVAL; + goto end; + } + + edid = dp->panel->edid; + + dp->audio_supported = drm_detect_monitor_audio(edid); + + dp_panel_handle_sink_request(dp->panel); + + dp->dp_display.max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; + dp->dp_display.max_dp_lanes = dp->parser->max_dp_lanes; +notify: + dp_display_send_hpd_notification(dp, true); + +end: + return rc; +} + +static void dp_display_host_init(struct dp_display_private *dp) +{ + bool flip = false; + + if (dp->core_initialized) { + DRM_DEBUG_DP("DP core already initialized\n"); + return; + } + + if (dp->usbpd->orientation == ORIENTATION_CC2) + flip = true; + + dp_power_init(dp->power, flip); + dp_ctrl_host_init(dp->ctrl, flip); + dp_aux_init(dp->aux); + dp->core_initialized = true; +} + +static void dp_display_host_deinit(struct dp_display_private *dp) +{ + if (!dp->core_initialized) { + DRM_DEBUG_DP("DP core already off\n"); + return; + } + + dp_ctrl_host_deinit(dp->ctrl); + dp_aux_deinit(dp->aux); + dp_power_deinit(dp->power); + disable_irq(dp->irq); + dp->core_initialized = false; +} + +static void dp_display_process_hpd_low(struct dp_display_private *dp) +{ + dp_display_send_hpd_notification(dp, false); + + dp_aux_deinit(dp->aux); +} + +static int dp_display_usbpd_configure_cb(struct device *dev) +{ + int rc = 0; + struct dp_display_private *dp; + + if (!dev) { + DRM_ERROR("invalid dev\n"); + rc = -EINVAL; + goto end; + } + + dp = dev_get_drvdata(dev); + if (!dp) { + DRM_ERROR("no driver data found\n"); + rc = -ENODEV; + goto end; + } + + dp_display_host_init(dp); + + if (dp->usbpd->hpd_high) + dp_display_process_hpd_high(dp); +end: + return rc; +} + +static void dp_display_clean(struct dp_display_private *dp) +{ + dp_ctrl_push_idle(dp->ctrl); + dp_ctrl_off(dp->ctrl); +} + +static int dp_display_usbpd_disconnect_cb(struct device *dev) +{ + int rc = 0; + struct dp_display_private *dp; + + dp = dev_get_drvdata(dev); + + rc = dp_display_send_hpd_notification(dp, false); + + /* if cable is disconnected, reset psm_enabled flag */ + if (!dp->usbpd->alt_mode_cfg_done) + dp->link->psm_enabled = false; + + if ((rc < 0) && dp->power_on) + dp_display_clean(dp); + + dp_display_host_deinit(dp); + return rc; +} + +static void dp_display_handle_video_request(struct dp_display_private *dp) +{ + if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) { + /* force disconnect followed by connect */ + dp->usbpd->connect(dp->usbpd, false); + dp->panel->video_test = true; + dp->usbpd->connect(dp->usbpd, true); + dp_link_send_test_response(dp->link); + } +} + +static int dp_display_handle_hpd_irq(struct dp_display_private *dp) +{ + if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { + dp_display_send_hpd_notification(dp, false); + + if (dp_display_is_sink_count_zero(dp)) { + DRM_DEBUG_DP("sink count is zero, nothing to do\n"); + return 0; + } + + return dp_display_process_hpd_high(dp); + } + + dp_ctrl_handle_sink_request(dp->ctrl); + + dp_display_handle_video_request(dp); + + return 0; +} + +static int dp_display_usbpd_attention_cb(struct device *dev) +{ + int rc = 0; + struct dp_display_private *dp; + + if (!dev) { + DRM_ERROR("invalid dev\n"); + return -EINVAL; + } + + dp = dev_get_drvdata(dev); + if (!dp) { + DRM_ERROR("no driver data found\n"); + return -ENODEV; + } + + if (dp->usbpd->hpd_irq) { + dp->hpd_irq_on = true; + + rc = dp_link_process_request(dp->link); + /* check for any test request issued by sink */ + if (!rc) + dp_display_handle_hpd_irq(dp); + + dp->hpd_irq_on = false; + goto end; + } + + if (!dp->usbpd->hpd_high) { + dp_display_process_hpd_low(dp); + goto end; + } + + if (dp->usbpd->alt_mode_cfg_done) + dp_display_process_hpd_high(dp); +end: + return rc; +} + +static void dp_display_deinit_sub_modules(struct dp_display_private *dp) +{ + dp_ctrl_put(dp->ctrl); + dp_panel_put(dp->panel); + dp_aux_put(dp->aux); +} + +static int dp_init_sub_modules(struct dp_display_private *dp) +{ + int rc = 0; + struct device *dev = &dp->pdev->dev; + struct dp_usbpd_cb *cb = &dp->usbpd_cb; + struct dp_panel_in panel_in = { + .dev = dev, + }; + + /* Callback APIs used for cable status change event */ + cb->configure = dp_display_usbpd_configure_cb; + cb->disconnect = dp_display_usbpd_disconnect_cb; + cb->attention = dp_display_usbpd_attention_cb; + + dp->usbpd = dp_hpd_get(dev, cb); + if (IS_ERR(dp->usbpd)) { + rc = PTR_ERR(dp->usbpd); + DRM_ERROR("failed to initialize hpd, rc = %d\n", rc); + dp->usbpd = NULL; + goto error; + } + + dp->parser = dp_parser_get(dp->pdev); + if (IS_ERR(dp->parser)) { + rc = PTR_ERR(dp->parser); + DRM_ERROR("failed to initialize parser, rc = %d\n", rc); + dp->parser = NULL; + goto error; + } + + dp->catalog = dp_catalog_get(dev, &dp->parser->io); + 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->power = dp_power_get(dp->parser); + if (IS_ERR(dp->power)) { + rc = PTR_ERR(dp->power); + DRM_ERROR("failed to initialize power, rc = %d\n", rc); + dp->power = NULL; + goto error; + } + + dp->aux = dp_aux_get(dev, dp->catalog); + if (IS_ERR(dp->aux)) { + rc = PTR_ERR(dp->aux); + DRM_ERROR("failed to initialize aux, rc = %d\n", rc); + dp->aux = NULL; + goto error; + } + + dp->link = dp_link_get(dev, dp->aux); + if (IS_ERR(dp->link)) { + rc = PTR_ERR(dp->link); + DRM_ERROR("failed to initialize link, rc = %d\n", rc); + dp->link = NULL; + goto error_link; + } + + panel_in.aux = dp->aux; + panel_in.catalog = dp->catalog; + panel_in.link = dp->link; + + dp->panel = dp_panel_get(&panel_in); + if (IS_ERR(dp->panel)) { + rc = PTR_ERR(dp->panel); + DRM_ERROR("failed to initialize panel, rc = %d\n", rc); + dp->panel = NULL; + goto error_link; + } + + dp->ctrl = dp_ctrl_get(dev, dp->link, dp->panel, dp->aux, + dp->power, dp->catalog, dp->parser); + if (IS_ERR(dp->ctrl)) { + rc = PTR_ERR(dp->ctrl); + DRM_ERROR("failed to initialize ctrl, rc = %d\n", rc); + dp->ctrl = NULL; + goto error_ctrl; + } + + return rc; +error_ctrl: + dp_panel_put(dp->panel); +error_link: + dp_aux_put(dp->aux); +error: + return rc; +} + +static int dp_display_set_mode(struct msm_dp *dp_display, + struct dp_display_mode *mode) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp->panel->dp_mode.drm_mode = mode->drm_mode; + dp->panel->dp_mode.bpp = mode->bpp; + dp->panel->dp_mode.capabilities = mode->capabilities; + dp_panel_init_panel_info(dp->panel); + return 0; +} + +static int dp_display_prepare(struct msm_dp *dp) +{ + return 0; +} + +static void dp_display_dump(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp_panel_dump_regs(dp->panel); +} + +static int dp_display_enable(struct msm_dp *dp_display) +{ + int rc = 0; + struct dp_display_private *dp; + bool dump_dp = false; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + if (dp->power_on) { + DRM_DEBUG_DP("Link already setup, return\n"); + return 0; + } + + rc = dp_ctrl_on(dp->ctrl); + if (!rc) + dp->power_on = true; + + if (dump_dp != false) + dp_display_dump(dp_display); + + return rc; +} + +static int dp_display_post_enable(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + complete_all(&dp->notification_comp); + return 0; +} + +static int dp_display_pre_disable(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + if (dp->usbpd->alt_mode_cfg_done) + dp_link_psm_config(dp->link, &dp->panel->link_info, true); + + dp_ctrl_push_idle(dp->ctrl); + return 0; +} + +static int dp_display_disable(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + if (!dp->power_on || !dp->core_initialized) + return -EINVAL; + + dp_ctrl_off(dp->ctrl); + + dp->power_on = false; + + complete_all(&dp->notification_comp); + return 0; +} + +int dp_display_request_irq(struct msm_dp *dp_display) +{ + int rc = 0; + struct dp_display_private *dp; + + if (!dp_display) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); + if (dp->irq < 0) { + rc = dp->irq; + DRM_ERROR("failed to get irq: %d\n", rc); + return rc; + } + + rc = devm_request_irq(&dp->pdev->dev, dp->irq, dp_display_irq, + IRQF_TRIGGER_HIGH, "dp_display_isr", dp); + if (rc < 0) { + DRM_ERROR("failed to request IRQ%u: %d\n", + dp->irq, rc); + return rc; + } + disable_irq(dp->irq); + + return 0; +} + +static int dp_display_unprepare(struct msm_dp *dp) +{ + return 0; +} + +int dp_display_validate_mode(struct msm_dp *dp, u32 mode_pclk_khz) +{ + const u32 num_components = 3, default_bpp = 24; + struct dp_display_private *dp_display; + struct dp_link_info *link_info; + u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0; + + if (!dp || !mode_pclk_khz || !dp->connector) { + DRM_ERROR("invalid params\n"); + return -EINVAL; + } + + dp_display = container_of(dp, struct dp_display_private, dp_display); + link_info = &dp_display->panel->link_info; + + mode_bpp = dp->connector->display_info.bpc * num_components; + if (!mode_bpp) + mode_bpp = default_bpp; + + mode_bpp = dp_panel_get_mode_bpp(dp_display->panel, + mode_bpp, mode_pclk_khz); + + mode_rate_khz = mode_pclk_khz * mode_bpp; + supported_rate_khz = link_info->num_lanes * link_info->rate * 8; + + if (mode_rate_khz > supported_rate_khz) + return MODE_BAD; + + return MODE_OK; +} + +int dp_display_get_modes(struct msm_dp *dp, + struct dp_display_mode *dp_mode) +{ + struct dp_display_private *dp_display; + int ret = 0; + + if (!dp) { + DRM_ERROR("invalid params\n"); + return 0; + } + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + ret = dp_panel_get_modes(dp_display->panel, + dp->connector, dp_mode); + if (dp_mode->drm_mode.clock) + dp->max_pclk_khz = dp_mode->drm_mode.clock; + return ret; +} + +bool dp_display_check_video_test(struct msm_dp *dp) +{ + struct dp_display_private *dp_display; + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + return dp_display->panel->video_test; +} + +int dp_display_get_test_bpp(struct msm_dp *dp) +{ + struct dp_display_private *dp_display; + + if (!dp) { + DRM_ERROR("invalid params\n"); + return 0; + } + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + return dp_link_bit_depth_to_bpp( + dp_display->link->test_video.test_bit_depth); +} + +static int dp_display_probe(struct platform_device *pdev) +{ + int rc = 0; + struct dp_display_private *dp; + + if (!pdev || !pdev->dev.of_node) { + DRM_ERROR("pdev not found\n"); + return -ENODEV; + } + + dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + init_completion(&dp->notification_comp); + + dp->pdev = pdev; + dp->name = "drm_dp"; + + rc = dp_init_sub_modules(dp); + if (rc) { + DRM_ERROR("init sub module failed\n"); + return -EPROBE_DEFER; + } + + platform_set_drvdata(pdev, dp); + + mutex_init(&dp->dp_display.connect_mutex); + g_dp_display = &dp->dp_display; + + rc = component_add(&pdev->dev, &dp_display_comp_ops); + if (rc) { + DRM_ERROR("component add failed, rc=%d\n", rc); + dp_display_deinit_sub_modules(dp); + } + + return rc; +} + +static int dp_display_remove(struct platform_device *pdev) +{ + struct dp_display_private *dp; + + dp = platform_get_drvdata(pdev); + + dp_display_deinit_sub_modules(dp); + + component_del(&pdev->dev, &dp_display_comp_ops); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static int dp_pm_resume(struct device *dev) +{ + return 0; +} + +static int dp_pm_suspend(struct device *dev) +{ + return 0; +} + +static int dp_pm_prepare(struct device *dev) +{ + return 0; +} + +static void dp_pm_complete(struct device *dev) +{ + +} + +static const struct dev_pm_ops dp_pm_ops = { + .suspend = dp_pm_suspend, + .resume = dp_pm_resume, + .prepare = dp_pm_prepare, + .complete = dp_pm_complete, +}; + +static struct platform_driver dp_display_driver = { + .probe = dp_display_probe, + .remove = dp_display_remove, + .driver = { + .name = "msm-dp-display", + .of_match_table = dp_dt_match, + .suppress_bind_attrs = true, + .pm = &dp_pm_ops, + }, +}; + +int __init msm_dp_register(void) +{ + int ret; + + ret = platform_driver_register(&dp_display_driver); + if (ret) + DRM_ERROR("Dp display driver register failed"); + + return ret; +} + +void __exit msm_dp_unregister(void) +{ + platform_driver_unregister(&dp_display_driver); +} + +int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, + struct drm_encoder *encoder) +{ + struct msm_drm_private *priv; + int ret; + + if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev)) + return -EINVAL; + + priv = dev->dev_private; + dp_display->drm_dev = dev; + + ret = dp_display_request_irq(dp_display); + if (ret) { + DRM_ERROR("request_irq failed, ret=%d\n", ret); + return ret; + } + + dp_display->encoder = encoder; + + dp_display->connector = dp_drm_connector_init(dp_display); + if (IS_ERR(dp_display->connector)) { + ret = PTR_ERR(dp_display->connector); + DRM_DEV_ERROR(dev->dev, + "failed to create dp connector: %d\n", ret); + dp_display->connector = NULL; + return ret; + } + + priv->connectors[priv->num_connectors++] = dp_display->connector; + return 0; +} + +int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder) +{ + int rc = 0; + struct dp_display_private *dp_display; + + dp_display = container_of(dp, struct dp_display_private, dp_display); + if (!dp_display->dp_mode.drm_mode.clock) { + DRM_ERROR("invalid params\n"); + return -EINVAL; + } + + rc = dp_display_set_mode(dp, &dp_display->dp_mode); + if (rc) { + DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); + return rc; + } + + rc = dp_display_prepare(dp); + if (rc) { + DRM_ERROR("DP display prepare failed, rc=%d\n", rc); + return rc; + } + + rc = dp_display_enable(dp); + if (rc) { + DRM_ERROR("DP display enable failed, rc=%d\n", rc); + dp_display_unprepare(dp); + return rc; + } + + rc = dp_display_post_enable(dp); + if (rc) { + DRM_ERROR("DP display post enable failed, rc=%d\n", rc); + dp_display_disable(dp); + dp_display_unprepare(dp); + } + return rc; +} + +int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder) +{ + int rc = 0; + + rc = dp_display_pre_disable(dp); + if (rc) { + DRM_ERROR("DP display pre disable failed, rc=%d\n", rc); + return rc; + } + + rc = dp_display_disable(dp); + if (rc) { + DRM_ERROR("DP display disable failed, rc=%d\n", rc); + return rc; + } + + rc = dp_display_unprepare(dp); + if (rc) + DRM_ERROR("DP display unprepare failed, rc=%d\n", rc); + + return rc; +} + +void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct dp_display_private *dp_display; + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + memset(&dp_display->dp_mode, 0x0, sizeof(struct dp_display_mode)); + + if (dp_display_check_video_test(dp)) + dp_display->dp_mode.bpp = dp_display_get_test_bpp(dp); + else /* Default num_components per pixel = 3 */ + dp_display->dp_mode.bpp = dp->connector->display_info.bpc * 3; + + if (!dp_display->dp_mode.bpp) + dp_display->dp_mode.bpp = 24; /* Default bpp */ + + drm_mode_copy(&dp_display->dp_mode.drm_mode, adjusted_mode); + + dp_display->dp_mode.v_active_low = + !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NVSYNC); + + dp_display->dp_mode.h_active_low = + !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC); +} diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h new file mode 100644 index 0000000000000..dad8610685a6d --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_DISPLAY_H_ +#define _DP_DISPLAY_H_ + +#include "dp_panel.h" + +struct msm_dp { + struct drm_device *drm_dev; + struct drm_connector *connector; + struct drm_encoder *encoder; + bool is_connected; + struct mutex connect_mutex; + u32 max_pclk_khz; + u32 max_dp_lanes; +}; + +int dp_display_validate_mode(struct msm_dp *dp_display, u32 mode_pclk_khz); +int dp_display_get_modes(struct msm_dp *dp_display, + struct dp_display_mode *dp_mode); +int dp_display_request_irq(struct msm_dp *dp_display); +bool dp_display_check_video_test(struct msm_dp *dp_display); +int dp_display_get_test_bpp(struct msm_dp *dp_display); + +#endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c new file mode 100644 index 0000000000000..e58906f4ae1e2 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic.h> +#include <drm/drm_crtc.h> + +#include "msm_drv.h" +#include "msm_kms.h" +#include "dp_drm.h" + +struct dp_connector { + struct drm_connector base; + struct msm_dp *dp_display; +}; +#define to_dp_connector(x) container_of(x, struct dp_connector, base) + +/** + * dp_connector_detect - callback to determine if connector is connected + * @conn: Pointer to drm connector structure + * @force: Force detect setting from drm framework + * Returns: Connector 'is connected' status + */ +static enum drm_connector_status dp_connector_detect(struct drm_connector *conn, + bool force) +{ + struct msm_dp *dp; + + dp = to_dp_connector(conn)->dp_display; + + DRM_DEBUG_DP("is_connected = %s\n", + (dp->is_connected) ? "true" : "false"); + + return (dp->is_connected) ? connector_status_connected : + connector_status_disconnected; +} + +/** + * dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add() + * @connector: Pointer to drm connector structure + * Returns: Number of modes added + */ +static int dp_connector_get_modes(struct drm_connector *connector) +{ + int rc = 0; + struct msm_dp *dp; + struct dp_display_mode *dp_mode = NULL; + struct drm_display_mode *m, drm_mode; + + if (!connector) + return 0; + + dp = to_dp_connector(connector)->dp_display; + + dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL); + if (!dp_mode) + return 0; + + mutex_lock(&dp->connect_mutex); + /* pluggable case assumes EDID is read when HPD */ + if (dp->is_connected) { + /* + *The get_modes() function might return one mode that is stored + * in dp_mode when compliance test is in progress. If not, the + * return value is equal to the total number of modes supported + * by the sink + */ + rc = dp_display_get_modes(dp, dp_mode); + if (rc <= 0) { + DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc); + kfree(dp_mode); + mutex_unlock(&dp->connect_mutex); + return rc; + } + if (dp_mode->drm_mode.clock) { /* valid DP mode */ + memset(&drm_mode, 0x0, sizeof(drm_mode)); + drm_mode_copy(&drm_mode, &dp_mode->drm_mode); + m = drm_mode_duplicate(connector->dev, &drm_mode); + if (!m) { + DRM_ERROR("failed to add mode %ux%u\n", + drm_mode.hdisplay, + drm_mode.vdisplay); + kfree(dp_mode); + mutex_unlock(&dp->connect_mutex); + return 0; + } + drm_mode_probed_add(connector, m); + } + } else { + DRM_DEBUG_DP("No sink connected\n"); + } + mutex_unlock(&dp->connect_mutex); + kfree(dp_mode); + return rc; +} + +/** + * dp_connector_mode_valid - callback to determine if specified mode is valid + * @connector: Pointer to drm connector structure + * @mode: Pointer to drm mode structure + * Returns: Validity status for specified mode + */ +static enum drm_mode_status dp_connector_mode_valid( + struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct msm_dp *dp_disp; + + dp_disp = to_dp_connector(connector)->dp_display; + + if ((dp_disp->max_pclk_khz <= 0) || + (dp_disp->max_pclk_khz > DP_MAX_PIXEL_CLK_KHZ) || + (mode->clock > dp_disp->max_pclk_khz)) + return MODE_BAD; + + return dp_display_validate_mode(dp_disp, mode->clock); +} + +static const struct drm_connector_funcs dp_connector_funcs = { + .detect = dp_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .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 dp_connector_helper_funcs = { + .get_modes = dp_connector_get_modes, + .mode_valid = dp_connector_mode_valid, +}; + +/* connector initialization */ +struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) +{ + struct drm_connector *connector = NULL; + struct dp_connector *dp_connector; + int ret; + + dp_connector = devm_kzalloc(dp_display->drm_dev->dev, + sizeof(*dp_connector), + GFP_KERNEL); + if (!dp_connector) + return ERR_PTR(-ENOMEM); + + dp_connector->dp_display = dp_display; + + connector = &dp_connector->base; + + ret = drm_connector_init(dp_display->drm_dev, connector, + &dp_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) + return ERR_PTR(ret); + + drm_connector_helper_add(connector, &dp_connector_helper_funcs); + + /* + * Enable HPD to let hpd event is handled when cable is connected. + */ + connector->polled = DRM_CONNECTOR_POLL_HPD; + + drm_connector_attach_encoder(connector, dp_display->encoder); + + return connector; +} diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h new file mode 100644 index 0000000000000..c27bfceefdf00 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_DRM_H_ +#define _DP_DRM_H_ + +#include <linux/types.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> + +#include "msm_drv.h" +#include "dp_display.h" + +struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display); + +#endif /* _DP_DRM_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.c b/drivers/gpu/drm/msm/dp/dp_hpd.c new file mode 100644 index 0000000000000..5b08ce580702b --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_hpd.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/slab.h> +#include <linux/device.h> + +#include "dp_hpd.h" + +/* DP specific VDM commands */ +#define DP_USBPD_VDM_STATUS 0x10 +#define DP_USBPD_VDM_CONFIGURE 0x11 + +/* USBPD-TypeC specific Macros */ +#define VDM_VERSION 0x0 +#define USB_C_DP_SID 0xFF01 + +struct dp_hpd_private { + struct device *dev; + struct dp_usbpd_cb *dp_cb; + struct dp_usbpd dp_usbpd; +}; + +static int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd) +{ + int rc = 0; + struct dp_hpd_private *hpd_priv; + + hpd_priv = container_of(dp_usbpd, struct dp_hpd_private, + dp_usbpd); + + dp_usbpd->hpd_high = hpd; + + if (!hpd_priv->dp_cb && !hpd_priv->dp_cb->configure + && !hpd_priv->dp_cb->disconnect) { + pr_err("hpd dp_cb not initialized\n"); + return -EINVAL; + } + if (hpd) + hpd_priv->dp_cb->configure(hpd_priv->dev); + else + hpd_priv->dp_cb->disconnect(hpd_priv->dev); + + return rc; +} + +struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb) +{ + struct dp_hpd_private *dp_hpd; + + if (!cb) { + pr_err("invalid cb data\n"); + return ERR_PTR(-EINVAL); + } + + dp_hpd = devm_kzalloc(dev, sizeof(*dp_hpd), GFP_KERNEL); + if (!dp_hpd) + return ERR_PTR(-ENOMEM); + + dp_hpd->dev = dev; + dp_hpd->dp_cb = cb; + + dp_hpd->dp_usbpd.connect = dp_hpd_connect; + + return &dp_hpd->dp_usbpd; +} diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.h b/drivers/gpu/drm/msm/dp/dp_hpd.h new file mode 100644 index 0000000000000..c0178524bec71 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_hpd.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_HPD_H_ +#define _DP_HPD_H_ + +//#include <linux/usb/usbpd.h> + +#include <linux/types.h> +#include <linux/device.h> + +enum plug_orientation { + ORIENTATION_NONE, + ORIENTATION_CC1, + ORIENTATION_CC2, +}; + +/** + * struct dp_usbpd - DisplayPort status + * + * @orientation: plug orientation configuration + * @low_pow_st: low power state + * @adaptor_dp_en: adaptor functionality enabled + * @multi_func: multi-function preferred + * @usb_config_req: request to switch to usb + * @exit_dp_mode: request exit from displayport mode + * @hpd_high: Hot Plug Detect signal is high. + * @hpd_irq: Change in the status since last message + * @alt_mode_cfg_done: bool to specify alt mode status + * @debug_en: bool to specify debug mode + * @connect: simulate disconnect or connect for debug mode + */ +struct dp_usbpd { + enum plug_orientation orientation; + bool low_pow_st; + bool adaptor_dp_en; + bool multi_func; + bool usb_config_req; + bool exit_dp_mode; + bool hpd_high; + bool hpd_irq; + bool alt_mode_cfg_done; + bool debug_en; + + int (*connect)(struct dp_usbpd *dp_usbpd, bool hpd); +}; + +/** + * struct dp_usbpd_cb - callback functions provided by the client + * + * @configure: called by usbpd module when PD communication has + * been completed and the usb peripheral has been configured on + * dp mode. + * @disconnect: notify the cable disconnect issued by usb. + * @attention: notify any attention message issued by usb. + */ +struct dp_usbpd_cb { + int (*configure)(struct device *dev); + int (*disconnect)(struct device *dev); + int (*attention)(struct device *dev); +}; + +/** + * dp_hpd_get() - setup hpd module + * + * @dev: device instance of the caller + * @cb: struct containing callback function pointers. + * + * This function allows the client to initialize the usbpd + * module. The module will communicate with HPD module. + */ +struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb); + +int dp_hpd_register(struct dp_usbpd *dp_usbpd); +void dp_hpd_unregister(struct dp_usbpd *dp_usbpd); + +#endif /* _DP_HPD_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c new file mode 100644 index 0000000000000..9156a7f3dbf88 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -0,0 +1,1214 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ + +#include "dp_link.h" +#include "dp_panel.h" + +#define DP_TEST_REQUEST_MASK 0x7F + +enum audio_sample_rate { + AUDIO_SAMPLE_RATE_32_KHZ = 0x00, + AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01, + AUDIO_SAMPLE_RATE_48_KHZ = 0x02, + AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03, + AUDIO_SAMPLE_RATE_96_KHZ = 0x04, + AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05, + AUDIO_SAMPLE_RATE_192_KHZ = 0x06, +}; + +enum audio_pattern_type { + AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00, + AUDIO_TEST_PATTERN_SAWTOOTH = 0x01, +}; + +struct dp_link_request { + u32 test_requested; + u32 test_link_rate; + u32 test_lane_count; +}; + +struct dp_link_private { + u32 prev_sink_count; + struct device *dev; + struct drm_dp_aux *aux; + struct dp_link dp_link; + + struct dp_link_request request; + struct mutex test_response_mutex; + struct mutex psm_mutex; + u8 link_status[DP_LINK_STATUS_SIZE]; +}; + +static int dp_aux_link_power_up(struct drm_dp_aux *aux, + struct dp_link_info *link) +{ + u8 value; + int err; + + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + usleep_range(1000, 2000); + + return 0; +} + +static int dp_aux_link_power_down(struct drm_dp_aux *aux, + struct dp_link_info *link) +{ + u8 value; + int err; + + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D3; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + return 0; +} + +static int dp_link_get_period(struct dp_link_private *link, int const addr) +{ + int ret = 0; + u8 data; + u32 const max_audio_period = 0xA; + + /* TEST_AUDIO_PERIOD_CH_XX */ + if (drm_dp_dpcd_readb(link->aux, addr, &data) < 0) { + DRM_ERROR("failed to read test_audio_period (0x%x)\n", addr); + ret = -EINVAL; + goto exit; + } + + /* Period - Bits 3:0 */ + data = data & 0xF; + if ((int)data > max_audio_period) { + DRM_ERROR("invalid test_audio_period_ch_1 = 0x%x\n", data); + ret = -EINVAL; + goto exit; + } + + ret = data; +exit: + return ret; +} + +static int dp_link_parse_audio_channel_period(struct dp_link_private *link) +{ + int ret = 0; + struct dp_link_test_audio *req = &link->dp_link.test_audio; + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_1 = ret; + DRM_DEBUG_DP("test_audio_period_ch_1 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_2 = ret; + DRM_DEBUG_DP("test_audio_period_ch_2 = 0x%x\n", ret); + + /* TEST_AUDIO_PERIOD_CH_3 (Byte 0x275) */ + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_3 = ret; + DRM_DEBUG_DP("test_audio_period_ch_3 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_4 = ret; + DRM_DEBUG_DP("test_audio_period_ch_4 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_5 = ret; + DRM_DEBUG_DP("test_audio_period_ch_5 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_6 = ret; + DRM_DEBUG_DP("test_audio_period_ch_6 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_7 = ret; + DRM_DEBUG_DP("test_audio_period_ch_7 = 0x%x\n", ret); + + ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8); + if (ret == -EINVAL) + goto exit; + + req->test_audio_period_ch_8 = ret; + DRM_DEBUG_DP("test_audio_period_ch_8 = 0x%x\n", ret); +exit: + return ret; +} + +static int dp_link_parse_audio_pattern_type(struct dp_link_private *link) +{ + int ret = 0; + u8 data; + ssize_t rlen; + int const max_audio_pattern_type = 0x1; + + rlen = drm_dp_dpcd_readb(link->aux, + DP_TEST_AUDIO_PATTERN_TYPE, &data); + if (rlen < 0) { + DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen); + return rlen; + } + + /* Audio Pattern Type - Bits 7:0 */ + if ((int)data > max_audio_pattern_type) { + DRM_ERROR("invalid audio pattern type = 0x%x\n", data); + ret = -EINVAL; + goto exit; + } + + link->dp_link.test_audio.test_audio_pattern_type = data; + DRM_DEBUG_DP("audio pattern type = 0x%x\n", data); +exit: + return ret; +} + +static int dp_link_parse_audio_mode(struct dp_link_private *link) +{ + int ret = 0; + u8 data; + ssize_t rlen; + int const max_audio_sampling_rate = 0x6; + int const max_audio_channel_count = 0x8; + int sampling_rate = 0x0; + int channel_count = 0x0; + + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_AUDIO_MODE, &data); + if (rlen < 0) { + DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen); + return rlen; + } + + /* Sampling Rate - Bits 3:0 */ + sampling_rate = data & 0xF; + if (sampling_rate > max_audio_sampling_rate) { + DRM_ERROR("sampling rate (0x%x) greater than max (0x%x)\n", + sampling_rate, max_audio_sampling_rate); + ret = -EINVAL; + goto exit; + } + + /* Channel Count - Bits 7:4 */ + channel_count = ((data & 0xF0) >> 4) + 1; + if (channel_count > max_audio_channel_count) { + DRM_ERROR("channel_count (0x%x) greater than max (0x%x)\n", + channel_count, max_audio_channel_count); + ret = -EINVAL; + goto exit; + } + + link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate; + link->dp_link.test_audio.test_audio_channel_count = channel_count; + DRM_DEBUG_DP("sampling_rate = 0x%x, channel_count = 0x%x\n", + sampling_rate, channel_count); +exit: + return ret; +} + +static int dp_link_parse_audio_pattern_params(struct dp_link_private *link) +{ + int ret = 0; + + ret = dp_link_parse_audio_mode(link); + if (ret) + goto exit; + + ret = dp_link_parse_audio_pattern_type(link); + if (ret) + goto exit; + + ret = dp_link_parse_audio_channel_period(link); + +exit: + return ret; +} + +static bool dp_link_is_video_pattern_valid(u32 pattern) +{ + switch (pattern) { + case DP_NO_TEST_PATTERN: + case DP_COLOR_RAMP: + case DP_BLACK_AND_WHITE_VERTICAL_LINES: + case DP_COLOR_SQUARE: + return true; + default: + return false; + } +} + +/** + * dp_link_is_bit_depth_valid() - validates the bit depth requested + * @tbd: bit depth requested by the sink + * + * Returns true if the requested bit depth is supported. + */ +static bool dp_link_is_bit_depth_valid(u32 tbd) +{ + /* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */ + switch (tbd) { + case DP_TEST_BIT_DEPTH_6: + case DP_TEST_BIT_DEPTH_8: + case DP_TEST_BIT_DEPTH_10: + return true; + default: + return false; + } +} + +static int dp_link_parse_timing_params1(struct dp_link_private *link, + int addr, int len, u32 *val) +{ + u8 bp[2]; + int rlen; + + if (len != 2) + return -EINVAL; + + /* Read the requested video link pattern (Byte 0x221). */ + rlen = drm_dp_dpcd_read(link->aux, addr, bp, len); + if (rlen < len) { + DRM_ERROR("failed to read 0x%x\n", addr); + return -EINVAL; + } + + *val = bp[1] | (bp[0] << 8); + + return 0; +} + +static int dp_link_parse_timing_params2(struct dp_link_private *link, + int addr, int len, + u32 *val1, u32 *val2) +{ + u8 bp[2]; + int rlen; + + if (len != 2) + return -EINVAL; + + /* Read the requested video link pattern (Byte 0x221). */ + rlen = drm_dp_dpcd_read(link->aux, addr, bp, len); + if (rlen < len) { + DRM_ERROR("failed to read 0x%x\n", addr); + return -EINVAL; + } + + *val1 = (bp[0] & BIT(7)) >> 7; + *val2 = bp[1] | ((bp[0] & 0x7F) << 8); + + return 0; +} + +static int dp_link_parse_timing_params3(struct dp_link_private *link, + int addr, u32 *val) +{ + u8 bp; + u32 len = 1; + int rlen; + + rlen = drm_dp_dpcd_read(link->aux, addr, &bp, len); + if (rlen < 1) { + DRM_ERROR("failed to read 0x%x\n", addr); + return -EINVAL; + } + *val = bp; + + return 0; +} + +/** + * dp_parse_video_pattern_params() - parses video pattern parameters from DPCD + * @link: Display Port Driver data + * + * Returns 0 if it successfully parses the video link pattern and the link + * bit depth requested by the sink and, and if the values parsed are valid. + */ +static int dp_link_parse_video_pattern_params(struct dp_link_private *link) +{ + int ret = 0; + ssize_t rlen; + u8 bp; + + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_PATTERN, &bp); + if (rlen < 0) { + DRM_ERROR("failed to read link video pattern. rlen=%zd\n", + rlen); + return rlen; + } + + if (!dp_link_is_video_pattern_valid(bp)) { + DRM_ERROR("invalid link video pattern = 0x%x\n", bp); + ret = -EINVAL; + return ret; + } + + link->dp_link.test_video.test_video_pattern = bp; + + /* Read the requested color bit depth and dynamic range (Byte 0x232) */ + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_MISC0, &bp); + if (rlen < 0) { + DRM_ERROR("failed to read link bit depth. rlen=%zd\n", rlen); + return rlen; + } + + /* Dynamic Range */ + link->dp_link.test_video.test_dyn_range = + (bp & DP_TEST_DYNAMIC_RANGE_CEA); + + /* Color bit depth */ + bp &= DP_TEST_BIT_DEPTH_MASK; + if (!dp_link_is_bit_depth_valid(bp)) { + DRM_ERROR("invalid link bit depth = 0x%x\n", bp); + ret = -EINVAL; + return ret; + } + + link->dp_link.test_video.test_bit_depth = bp; + + /* resolution timing params */ + ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2, + &link->dp_link.test_video.test_h_total); + if (ret) { + DRM_ERROR("failed to parse test_htotal(DP_TEST_H_TOTAL_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2, + &link->dp_link.test_video.test_v_total); + if (ret) { + DRM_ERROR("failed to parse test_v_total(DP_TEST_V_TOTAL_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2, + &link->dp_link.test_video.test_h_start); + if (ret) { + DRM_ERROR("failed to parse test_h_start(DP_TEST_H_START_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2, + &link->dp_link.test_video.test_v_start); + if (ret) { + DRM_ERROR("failed to parse test_v_start(DP_TEST_V_START_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2, + &link->dp_link.test_video.test_hsync_pol, + &link->dp_link.test_video.test_hsync_width); + if (ret) { + DRM_ERROR("failed to parse (DP_TEST_HSYNC_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2, + &link->dp_link.test_video.test_vsync_pol, + &link->dp_link.test_video.test_vsync_width); + if (ret) { + DRM_ERROR("failed to parse (DP_TEST_VSYNC_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2, + &link->dp_link.test_video.test_h_width); + if (ret) { + DRM_ERROR("failed to parse test_h_width(DP_TEST_H_WIDTH_HI)\n"); + return ret; + } + + ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2, + &link->dp_link.test_video.test_v_height); + if (ret) { + DRM_ERROR("failed to parse test_v_height\n"); + return ret; + } + + ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1, + &link->dp_link.test_video.test_rr_d); + link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR; + if (ret) { + DRM_ERROR("failed to parse test_rr_d (DP_TEST_MISC1)\n"); + return ret; + } + + ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR, + &link->dp_link.test_video.test_rr_n); + if (ret) { + DRM_ERROR("failed to parse test_rr_n\n"); + return ret; + } + + DRM_DEBUG_DP("link video pattern = 0x%x\n" + "link dynamic range = 0x%x\n" + "link bit depth = 0x%x\n" + "TEST_H_TOTAL = %d, TEST_V_TOTAL = %d\n" + "TEST_H_START = %d, TEST_V_START = %d\n" + "TEST_HSYNC_POL = %d\n" + "TEST_HSYNC_WIDTH = %d\n" + "TEST_VSYNC_POL = %d\n" + "TEST_VSYNC_WIDTH = %d\n" + "TEST_H_WIDTH = %d\n" + "TEST_V_HEIGHT = %d\n" + "TEST_REFRESH_DENOMINATOR = %d\n" + "TEST_REFRESH_NUMERATOR = %d\n", + link->dp_link.test_video.test_video_pattern, + link->dp_link.test_video.test_dyn_range, + link->dp_link.test_video.test_bit_depth, + link->dp_link.test_video.test_h_total, + link->dp_link.test_video.test_v_total, + link->dp_link.test_video.test_h_start, + link->dp_link.test_video.test_v_start, + link->dp_link.test_video.test_hsync_pol, + link->dp_link.test_video.test_hsync_width, + link->dp_link.test_video.test_vsync_pol, + link->dp_link.test_video.test_vsync_width, + link->dp_link.test_video.test_h_width, + link->dp_link.test_video.test_v_height, + link->dp_link.test_video.test_rr_d, + link->dp_link.test_video.test_rr_n); + + return ret; +} + +/** + * dp_link_parse_link_training_params() - parses link training parameters from + * DPCD + * @link: Display Port Driver data + * + * Returns 0 if it successfully parses the link rate (Byte 0x219) and lane + * count (Byte 0x220), and if these values parse are valid. + */ +static int dp_link_parse_link_training_params(struct dp_link_private *link) +{ + u8 bp; + ssize_t rlen; + + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_LINK_RATE, &bp); + if (rlen < 0) { + DRM_ERROR("failed to read link rate. rlen=%zd\n", rlen); + return rlen; + } + + if (!is_link_rate_valid(bp)) { + DRM_ERROR("invalid link rate = 0x%x\n", bp); + return -EINVAL; + } + + link->request.test_link_rate = bp; + DRM_DEBUG_DP("link rate = 0x%x\n", link->request.test_link_rate); + + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_LANE_COUNT, &bp); + if (rlen < 0) { + DRM_ERROR("failed to read lane count. rlen=%zd\n", rlen); + return rlen; + } + bp &= DP_MAX_LANE_COUNT_MASK; + + if (!is_lane_count_valid(bp)) { + DRM_ERROR("invalid lane count = 0x%x\n", bp); + return -EINVAL; + } + + link->request.test_lane_count = bp; + DRM_DEBUG_DP("lane count = 0x%x\n", link->request.test_lane_count); + return 0; +} + +/** + * dp_parse_phy_test_params() - parses the phy link parameters + * @link: Display Port Driver data + * + * Parses the DPCD (Byte 0x248) for the DP PHY link pattern that is being + * requested. + */ +static int dp_link_parse_phy_test_params(struct dp_link_private *link) +{ + u8 data; + ssize_t rlen; + + rlen = drm_dp_dpcd_readb(link->aux, DP_PHY_TEST_PATTERN, + &data); + if (rlen < 0) { + DRM_ERROR("failed to read phy link pattern. rlen=%zd\n", rlen); + return rlen; + } + + link->dp_link.phy_params.phy_test_pattern_sel = data; + + DRM_DEBUG_DP("phy_test_pattern_sel = 0x%x\n", data); + + switch (data) { + case DP_LINK_QUAL_PATTERN_DISABLE: + case DP_LINK_QUAL_PATTERN_D10_2: + case DP_LINK_QUAL_PATTERN_ERROR_RATE: + case DP_LINK_QUAL_PATTERN_PRBS7: + case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM: + case DP_LINK_QUAL_PATTERN_HBR2_EYE: + return 0; + default: + return -EINVAL; + } +} + +/** + * dp_link_is_video_audio_test_requested() - checks for audio/video link request + * @link: link requested by the sink + * + * Returns true if the requested link is a permitted audio/video link. + */ +static bool dp_link_is_video_audio_test_requested(u32 link) +{ + u8 video_audio_test = (DP_TEST_LINK_VIDEO_PATTERN | + DP_TEST_LINK_AUDIO_PATTERN | + DP_TEST_LINK_AUDIO_DISABLED_VIDEO); + + return ((link & video_audio_test) && + !(link & ~video_audio_test)); +} + +/** + * dp_link_parse_request() - parses link request parameters from sink + * @link: Display Port Driver data + * + * Parses the DPCD to check if an automated link is requested (Byte 0x201), + * and what type of link automation is being requested (Byte 0x218). + */ +static int dp_link_parse_request(struct dp_link_private *link) +{ + int ret = 0; + u8 data; + ssize_t rlen; + + /** + * Read the device service IRQ vector (Byte 0x201) to determine + * whether an automated link has been requested by the sink. + */ + rlen = drm_dp_dpcd_readb(link->aux, + DP_DEVICE_SERVICE_IRQ_VECTOR, &data); + if (rlen < 0) { + DRM_ERROR("aux read failed. rlen=%zd\n", rlen); + return rlen; + } + + DRM_DEBUG_DP("device service irq vector = 0x%x\n", data); + + if (!(data & DP_AUTOMATED_TEST_REQUEST)) { + DRM_DEBUG_DP("no test requested\n"); + return 0; + } + + /** + * Read the link request byte (Byte 0x218) to determine what type + * of automated link has been requested by the sink. + */ + rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_REQUEST, &data); + if (rlen < 0) { + DRM_ERROR("aux read failed. rlen=%zd\n", rlen); + return rlen; + } + + if (!data || (data == DP_TEST_LINK_FAUX_PATTERN)) { + DRM_DEBUG_DP("link 0x%x not supported\n", data); + goto end; + } + + DRM_DEBUG_DP("Test:(0x%x) requested\n", data); + link->request.test_requested = data; + + if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) { + ret = dp_link_parse_phy_test_params(link); + if (ret) + goto end; + ret = dp_link_parse_link_training_params(link); + if (ret) + goto end; + } + + if (link->request.test_requested == DP_TEST_LINK_TRAINING) { + ret = dp_link_parse_link_training_params(link); + if (ret) + goto end; + } + + if (dp_link_is_video_audio_test_requested( + link->request.test_requested)) { + ret = dp_link_parse_video_pattern_params(link); + if (ret) + goto end; + + ret = dp_link_parse_audio_pattern_params(link); + } +end: + /* + * Send a DP_TEST_ACK if all link parameters are valid, otherwise send + * a DP_TEST_NAK. + */ + if (ret) { + link->dp_link.test_response = DP_TEST_NAK; + } else { + if (link->request.test_requested != DP_TEST_LINK_EDID_READ) + link->dp_link.test_response = DP_TEST_ACK; + else + link->dp_link.test_response = + DP_TEST_EDID_CHECKSUM_WRITE; + } + + return ret; +} + +/** + * dp_link_parse_sink_count() - parses the sink count + * @dp_link: pointer to link module data + * + * Parses the DPCD to check if there is an update to the sink count + * (Byte 0x200), and whether all the sink devices connected have Content + * Protection enabled. + */ +static int dp_link_parse_sink_count(struct dp_link *dp_link) +{ + ssize_t rlen; + bool cp_ready; + + struct dp_link_private *link = container_of(dp_link, + struct dp_link_private, dp_link); + + rlen = drm_dp_dpcd_readb(link->aux, DP_SINK_COUNT, + &link->dp_link.sink_count); + if (rlen < 0) { + DRM_ERROR("sink count read failed. rlen=%zd\n", rlen); + return rlen; + } + + cp_ready = link->dp_link.sink_count & DP_SINK_CP_READY; + + link->dp_link.sink_count = + DP_GET_SINK_COUNT(link->dp_link.sink_count); + + DRM_DEBUG_DP("sink_count = 0x%x, cp_ready = 0x%x\n", + link->dp_link.sink_count, cp_ready); + return 0; +} + +static void dp_link_parse_sink_status_field(struct dp_link_private *link) +{ + int len = 0; + + link->prev_sink_count = link->dp_link.sink_count; + dp_link_parse_sink_count(&link->dp_link); + + len = drm_dp_dpcd_read_link_status(link->aux, + link->link_status); + if (len < DP_LINK_STATUS_SIZE) + DRM_ERROR("DP link status read failed\n"); + dp_link_parse_request(link); +} + +/** + * dp_link_process_link_training_request() - processes new training requests + * @link: Display Port link data + * + * This function will handle new link training requests that are initiated by + * the sink. In particular, it will update the requested lane count and link + * rate, and then trigger the link retraining procedure. + * + * The function will return 0 if a link training request has been processed, + * otherwise it will return -EINVAL. + */ +static int dp_link_process_link_training_request(struct dp_link_private *link) +{ + if (link->request.test_requested != DP_TEST_LINK_TRAINING) + return -EINVAL; + + DRM_DEBUG_DP("Test:0x%x link rate = 0x%x, lane count = 0x%x\n", + DP_TEST_LINK_TRAINING, + link->request.test_link_rate, + link->request.test_lane_count); + + link->dp_link.link_params.num_lanes = link->request.test_lane_count; + link->dp_link.link_params.rate = link->request.test_link_rate; + + return 0; +} + +bool dp_link_send_test_response(struct dp_link *dp_link) +{ + struct dp_link_private *link = NULL; + int ret = 0; + + if (!dp_link) { + DRM_ERROR("invalid input\n"); + return false; + } + + link = container_of(dp_link, struct dp_link_private, dp_link); + + mutex_lock(&link->test_response_mutex); + ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_RESPONSE, + dp_link->test_response); + mutex_unlock(&link->test_response_mutex); + + return ret == 1; +} + +int dp_link_psm_config(struct dp_link *dp_link, + struct dp_link_info *link_info, bool enable) +{ + struct dp_link_private *link = NULL; + int ret = 0; + + if (!dp_link) { + DRM_ERROR("invalid params\n"); + return -EINVAL; + } + + link = container_of(dp_link, struct dp_link_private, dp_link); + + mutex_lock(&link->psm_mutex); + if (enable) + ret = dp_aux_link_power_down(link->aux, link_info); + else + ret = dp_aux_link_power_up(link->aux, link_info); + + if (ret) + DRM_ERROR("Failed to %s low power mode\n", enable ? + "enter" : "exit"); + else + dp_link->psm_enabled = enable; + + mutex_unlock(&link->psm_mutex); + return ret; +} + +bool dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum) +{ + struct dp_link_private *link = NULL; + int ret = 0; + + if (!dp_link) { + DRM_ERROR("invalid input\n"); + return false; + } + + link = container_of(dp_link, struct dp_link_private, dp_link); + + ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_EDID_CHECKSUM, + checksum); + return ret == 1; +} + +static int dp_link_parse_vx_px(struct dp_link_private *link) +{ + int ret = 0; + + DRM_DEBUG_DP("vx: 0=%d, 1=%d, 2=%d, 3=%d\n", + drm_dp_get_adjust_request_voltage(link->link_status, 0), + drm_dp_get_adjust_request_voltage(link->link_status, 1), + drm_dp_get_adjust_request_voltage(link->link_status, 2), + drm_dp_get_adjust_request_voltage(link->link_status, 3)); + + DRM_DEBUG_DP("px: 0=%d, 1=%d, 2=%d, 3=%d\n", + drm_dp_get_adjust_request_pre_emphasis(link->link_status, 0), + drm_dp_get_adjust_request_pre_emphasis(link->link_status, 1), + drm_dp_get_adjust_request_pre_emphasis(link->link_status, 2), + drm_dp_get_adjust_request_pre_emphasis(link->link_status, 3)); + + /** + * Update the voltage and pre-emphasis levels as per DPCD request + * vector. + */ + DRM_DEBUG_DP("Current: v_level = 0x%x, p_level = 0x%x\n", + link->dp_link.phy_params.v_level, + link->dp_link.phy_params.p_level); + link->dp_link.phy_params.v_level = + drm_dp_get_adjust_request_voltage(link->link_status, 0); + link->dp_link.phy_params.p_level = + drm_dp_get_adjust_request_pre_emphasis(link->link_status, 0); + DRM_DEBUG_DP("Requested: v_level = 0x%x, p_level = 0x%x\n", + link->dp_link.phy_params.v_level, + link->dp_link.phy_params.p_level); + + return ret; +} + +/** + * dp_link_process_phy_test_pattern_request() - process new phy link requests + * @link: Display Port Driver data + * + * This function will handle new phy link pattern requests that are initiated + * by the sink. The function will return 0 if a phy link pattern has been + * processed, otherwise it will return -EINVAL. + */ +static int dp_link_process_phy_test_pattern_request( + struct dp_link_private *link) +{ + int ret = 0; + + if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) { + DRM_DEBUG_DP("no phy test\n"); + return -EINVAL; + } + + if (!is_link_rate_valid(link->request.test_link_rate) || + !is_lane_count_valid(link->request.test_lane_count)) { + DRM_ERROR("Invalid: link rate = 0x%x,lane count = 0x%x\n", + link->request.test_link_rate, + link->request.test_lane_count); + return -EINVAL; + } + + DRM_DEBUG_DP("Current: rate = 0x%x, lane count = 0x%x\n", + link->dp_link.link_params.rate, + link->dp_link.link_params.num_lanes); + + DRM_DEBUG_DP("Requested: rate = 0x%x, lane count = 0x%x\n", + link->request.test_link_rate, + link->request.test_lane_count); + + link->dp_link.link_params.num_lanes = link->request.test_lane_count; + link->dp_link.link_params.rate = link->request.test_link_rate; + + ret = dp_link_parse_vx_px(link); + + if (ret) + DRM_ERROR("parse_vx_px failed. ret=%d\n", ret); + + return ret; +} + +static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r) +{ + return link_status[r - DP_LANE0_1_STATUS]; +} + +/** + * dp_link_process_link_status_update() - processes link status updates + * @link: Display Port link module data + * + * This function will check for changes in the link status, e.g. clock + * recovery done on all lanes, and trigger link training if there is a + * failure/error on the link. + * + * The function will return 0 if the a link status update has been processed, + * otherwise it will return -EINVAL. + */ +static int dp_link_process_link_status_update(struct dp_link_private *link) +{ + if (!(get_link_status(link->link_status, + DP_LANE_ALIGN_STATUS_UPDATED) & + DP_LINK_STATUS_UPDATED) || + (drm_dp_clock_recovery_ok(link->link_status, + link->dp_link.link_params.num_lanes) && + drm_dp_channel_eq_ok(link->link_status, + link->dp_link.link_params.num_lanes))) + return -EINVAL; + + DRM_DEBUG_DP("channel_eq_done = %d, clock_recovery_done = %d\n", + drm_dp_clock_recovery_ok(link->link_status, + link->dp_link.link_params.num_lanes), + drm_dp_clock_recovery_ok(link->link_status, + link->dp_link.link_params.num_lanes)); + + return 0; +} + +/** + * dp_link_process_downstream_port_status_change() - process port status changes + * @link: Display Port Driver data + * + * This function will handle downstream port updates that are initiated by + * the sink. If the downstream port status has changed, the EDID is read via + * AUX. + * + * The function will return 0 if a downstream port update has been + * processed, otherwise it will return -EINVAL. + */ +static int dp_link_process_ds_port_status_change(struct dp_link_private *link) +{ + if (get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) & + DP_DOWNSTREAM_PORT_STATUS_CHANGED) + goto reset; + + if (link->prev_sink_count == link->dp_link.sink_count) + return -EINVAL; + +reset: + /* reset prev_sink_count */ + link->prev_sink_count = link->dp_link.sink_count; + + return 0; +} + +static bool dp_link_is_video_pattern_requested(struct dp_link_private *link) +{ + return (link->request.test_requested & DP_TEST_LINK_VIDEO_PATTERN) + && !(link->request.test_requested & + DP_TEST_LINK_AUDIO_DISABLED_VIDEO); +} + +static bool dp_link_is_audio_pattern_requested(struct dp_link_private *link) +{ + return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN); +} + +static void dp_link_reset_data(struct dp_link_private *link) +{ + link->request = (const struct dp_link_request){ 0 }; + link->dp_link.test_video = (const struct dp_link_test_video){ 0 }; + link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN; + link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 }; + link->dp_link.phy_params.phy_test_pattern_sel = 0; + link->dp_link.sink_request = 0; + link->dp_link.test_response = 0; +} + +/** + * dp_link_process_request() - handle HPD IRQ transition to HIGH + * @dp_link: pointer to link module data + * + * This function will handle the HPD IRQ state transitions from LOW to HIGH + * (including cases when there are back to back HPD IRQ HIGH) indicating + * the start of a new link training request or sink status update. + */ +int dp_link_process_request(struct dp_link *dp_link) +{ + int ret = 0; + struct dp_link_private *link; + + if (!dp_link) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + link = container_of(dp_link, struct dp_link_private, dp_link); + + mutex_lock(&link->test_response_mutex); + dp_link_reset_data(link); + + dp_link_parse_sink_status_field(link); + mutex_unlock(&link->test_response_mutex); + + if (link->request.test_requested == DP_TEST_LINK_EDID_READ) { + dp_link->sink_request |= DP_TEST_LINK_EDID_READ; + return ret; + } + + ret = dp_link_process_ds_port_status_change(link); + if (!ret) { + dp_link->sink_request |= DS_PORT_STATUS_CHANGED; + return ret; + } + + ret = dp_link_process_link_training_request(link); + if (!ret) { + dp_link->sink_request |= DP_TEST_LINK_TRAINING; + return ret; + } + + ret = dp_link_process_phy_test_pattern_request(link); + if (!ret) { + dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN; + return ret; + } + + ret = dp_link_process_link_status_update(link); + if (!ret) { + dp_link->sink_request |= DP_LINK_STATUS_UPDATED; + return ret; + } + + if (dp_link_is_video_pattern_requested(link)) { + dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN; + return -EINVAL; + } + + if (dp_link_is_audio_pattern_requested(link)) { + dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN; + return -EINVAL; + } + + return ret; +} + +int dp_link_get_colorimetry_config(struct dp_link *dp_link) +{ + u32 cc; + struct dp_link_private *link; + + if (!dp_link) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + link = container_of(dp_link, struct dp_link_private, dp_link); + + /* + * Unless a video pattern CTS test is ongoing, use RGB_VESA + * Only RGB_VESA and RGB_CEA supported for now + */ + if (dp_link_is_video_pattern_requested(link)) + cc = link->dp_link.test_video.test_dyn_range; + else + cc = DP_TEST_DYNAMIC_RANGE_VESA; + + return cc; +} + +int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status) +{ + int i; + int v_max = 0, p_max = 0; + + if (!dp_link) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + /* use the max level across lanes */ + for (i = 0; i < dp_link->link_params.num_lanes; i++) { + u8 data_v = drm_dp_get_adjust_request_voltage(link_status, i); + u8 data_p = drm_dp_get_adjust_request_pre_emphasis(link_status, + i); + DRM_DEBUG_DP("lane=%d req_vol_swing=%d req_pre_emphasis=%d\n", + i, data_v, data_p); + if (v_max < data_v) + v_max = data_v; + if (p_max < data_p) + p_max = data_p; + } + + dp_link->phy_params.v_level = v_max >> DP_TRAIN_VOLTAGE_SWING_SHIFT; + dp_link->phy_params.p_level = p_max >> DP_TRAIN_PRE_EMPHASIS_SHIFT; + + /** + * Adjust the voltage swing and pre-emphasis level combination to within + * the allowable range. + */ + if (dp_link->phy_params.v_level > DP_TRAIN_VOLTAGE_SWING_MAX) { + DRM_DEBUG_DP("Requested vSwingLevel=%d, change to %d\n", + dp_link->phy_params.v_level, + DP_TRAIN_VOLTAGE_SWING_MAX); + dp_link->phy_params.v_level = DP_TRAIN_VOLTAGE_SWING_MAX; + } + + if (dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_MAX) { + DRM_DEBUG_DP("Requested preEmphasisLevel=%d, change to %d\n", + dp_link->phy_params.p_level, + DP_TRAIN_PRE_EMPHASIS_MAX); + dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_MAX; + } + + if ((dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_LVL_1) + && (dp_link->phy_params.v_level == + DP_TRAIN_VOLTAGE_SWING_LVL_2)) { + DRM_DEBUG_DP("Requested preEmphasisLevel=%d, change to %d\n", + dp_link->phy_params.p_level, + DP_TRAIN_PRE_EMPHASIS_LVL_1); + dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_LVL_1; + } + + DRM_DEBUG_DP("adjusted: v_level=%d, p_level=%d\n", + dp_link->phy_params.v_level, dp_link->phy_params.p_level); + + return 0; +} + +u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) +{ + u32 tbd; + + /* + * Few simplistic rules and assumptions made here: + * 1. Test bit depth is bit depth per color component + * 2. Assume 3 color components + */ + switch (bpp) { + case 18: + tbd = DP_TEST_BIT_DEPTH_6; + break; + case 24: + tbd = DP_TEST_BIT_DEPTH_8; + break; + case 30: + tbd = DP_TEST_BIT_DEPTH_10; + break; + default: + tbd = DP_TEST_BIT_DEPTH_UNKNOWN; + break; + } + + if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN) + tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); + + return tbd; +} + +struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux) +{ + struct dp_link_private *link; + struct dp_link *dp_link; + + if (!dev || !aux) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-EINVAL); + } + + link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL); + if (!link) + return ERR_PTR(-ENOMEM); + + link->dev = dev; + link->aux = aux; + + mutex_init(&link->test_response_mutex); + mutex_init(&link->psm_mutex); + dp_link = &link->dp_link; + + return dp_link; +} diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h new file mode 100644 index 0000000000000..e9d54db8fb612 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_LINK_H_ +#define _DP_LINK_H_ + +#include "dp_aux.h" + +#define DS_PORT_STATUS_CHANGED 0x200 +#define DP_TEST_BIT_DEPTH_UNKNOWN 0xFFFFFFFF +#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) + +struct dp_link_info { + unsigned char revision; + unsigned int rate; + unsigned int num_lanes; + unsigned long capabilities; +}; + +enum dp_link_voltage_level { + DP_TRAIN_VOLTAGE_SWING_LVL_0 = 0, + DP_TRAIN_VOLTAGE_SWING_LVL_1 = 1, + DP_TRAIN_VOLTAGE_SWING_LVL_2 = 2, + DP_TRAIN_VOLTAGE_SWING_MAX = DP_TRAIN_VOLTAGE_SWING_LVL_2, +}; + +enum dp_link_preemaphasis_level { + DP_TRAIN_PRE_EMPHASIS_LVL_0 = 0, + DP_TRAIN_PRE_EMPHASIS_LVL_1 = 1, + DP_TRAIN_PRE_EMPHASIS_LVL_2 = 2, + DP_TRAIN_PRE_EMPHASIS_MAX = DP_TRAIN_PRE_EMPHASIS_LVL_2, +}; + +struct dp_link_test_video { + u32 test_video_pattern; + u32 test_bit_depth; + u32 test_dyn_range; + u32 test_h_total; + u32 test_v_total; + u32 test_h_start; + u32 test_v_start; + u32 test_hsync_pol; + u32 test_hsync_width; + u32 test_vsync_pol; + u32 test_vsync_width; + u32 test_h_width; + u32 test_v_height; + u32 test_rr_d; + u32 test_rr_n; +}; + +struct dp_link_test_audio { + u32 test_audio_sampling_rate; + u32 test_audio_channel_count; + u32 test_audio_pattern_type; + u32 test_audio_period_ch_1; + u32 test_audio_period_ch_2; + u32 test_audio_period_ch_3; + u32 test_audio_period_ch_4; + u32 test_audio_period_ch_5; + u32 test_audio_period_ch_6; + u32 test_audio_period_ch_7; + u32 test_audio_period_ch_8; +}; + +struct dp_link_phy_params { + u32 phy_test_pattern_sel; + u8 v_level; + u8 p_level; +}; + +struct dp_link { + u32 sink_request; + u32 test_response; + bool psm_enabled; + + u8 sink_count; + struct dp_link_test_video test_video; + struct dp_link_test_audio test_audio; + struct dp_link_phy_params phy_params; + struct dp_link_info link_params; +}; + +/** + * mdss_dp_test_bit_depth_to_bpp() - convert test bit depth to bpp + * @tbd: test bit depth + * + * Returns the bits per pixel (bpp) to be used corresponding to the + * git bit depth value. This function assumes that bit depth has + * already been validated. + */ +static inline u32 dp_link_bit_depth_to_bpp(u32 tbd) +{ + /* + * Few simplistic rules and assumptions made here: + * 1. Bit depth is per color component + * 2. If bit depth is unknown return 0 + * 3. Assume 3 color components + */ + switch (tbd) { + case DP_TEST_BIT_DEPTH_6: + return 18; + case DP_TEST_BIT_DEPTH_8: + return 24; + case DP_TEST_BIT_DEPTH_10: + return 30; + case DP_TEST_BIT_DEPTH_UNKNOWN: + default: + return 0; + } +} + +u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp); +int dp_link_process_request(struct dp_link *dp_link); +int dp_link_get_colorimetry_config(struct dp_link *dp_link); +int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status); +bool dp_link_send_test_response(struct dp_link *dp_link); +int dp_link_psm_config(struct dp_link *dp_link, + struct dp_link_info *link_info, bool enable); +bool dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum); + +/** + * dp_link_get() - get the functionalities of dp test module + * + * + * return: a pointer to dp_link struct + */ +struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux); + +#endif /* _DP_LINK_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c new file mode 100644 index 0000000000000..5ac4b017da8fd --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -0,0 +1,486 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#include "dp_panel.h" + +#include <drm/drm_connector.h> +#include <drm/drm_edid.h> + +#define DP_MAX_DS_PORT_COUNT 1 + +struct dp_panel_private { + struct device *dev; + struct dp_panel dp_panel; + struct drm_dp_aux *aux; + struct dp_link *link; + struct dp_catalog *catalog; + bool panel_on; + bool aux_cfg_update_done; +}; + +static int dp_panel_read_dpcd(struct dp_panel *dp_panel) +{ + int rc = 0; + size_t rlen; + struct dp_panel_private *panel; + struct dp_link_info *link_info; + u8 *dpcd, major = 0, minor = 0, temp; + u32 dfp_count = 0, offset = DP_DPCD_REV; + + dpcd = dp_panel->dpcd; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + link_info = &dp_panel->link_info; + + rlen = drm_dp_dpcd_read(panel->aux, + DP_TRAINING_AUX_RD_INTERVAL, &temp, 1); + if (rlen < 0) { + DRM_ERROR("err reading DP_TRAINING_AUX_RD_INTERVAL,rlen=%zd\n", + rlen); + rc = -EINVAL; + goto end; + } + + /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */ + if (temp & BIT(7)) { + DRM_DEBUG_DP("using EXTENDED_RECEIVER_CAPABILITY_FIELD\n"); + offset = DPRX_EXTENDED_DPCD_FIELD; + } + + rlen = drm_dp_dpcd_read(panel->aux, offset, + dpcd, (DP_RECEIVER_CAP_SIZE + 1)); + if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { + DRM_ERROR("dpcd read failed, rlen=%zd\n", rlen); + if (rlen == -ETIMEDOUT) + rc = rlen; + else + rc = -EINVAL; + + goto end; + } + + print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ", + DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false); + + link_info->revision = dpcd[DP_DPCD_REV]; + major = (link_info->revision >> 4) & 0x0f; + minor = link_info->revision & 0x0f; + + link_info->rate = drm_dp_bw_code_to_link_rate(dpcd[DP_MAX_LINK_RATE]); + link_info->num_lanes = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; + + if (link_info->num_lanes > dp_panel->max_dp_lanes) + link_info->num_lanes = dp_panel->max_dp_lanes; + + /* Limit support upto HBR2 until HBR3 support is added */ + if (link_info->rate >= (drm_dp_bw_code_to_link_rate(DP_LINK_BW_5_4))) + link_info->rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_5_4); + + DRM_DEBUG_DP("version: %d.%d\n", major, minor); + DRM_DEBUG_DP("link_rate=%d\n", link_info->rate); + DRM_DEBUG_DP("lane_count=%d\n", link_info->num_lanes); + + if (drm_dp_enhanced_frame_cap(dpcd)) + link_info->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; + + dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & + DP_DOWN_STREAM_PORT_COUNT; + + if (dfp_count > DP_MAX_DS_PORT_COUNT) { + DRM_ERROR("DS port count %d greater that max (%d) supported\n", + dfp_count, DP_MAX_DS_PORT_COUNT); + return -EINVAL; + } +end: + return rc; +} + +static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel, + u32 mode_edid_bpp, u32 mode_pclk_khz) +{ + struct dp_link_info *link_info; + const u32 max_supported_bpp = 30, min_supported_bpp = 18; + u32 bpp = 0, data_rate_khz = 0; + + bpp = min_t(u32, mode_edid_bpp, max_supported_bpp); + + link_info = &dp_panel->link_info; + data_rate_khz = link_info->num_lanes * link_info->rate * 8; + + while (bpp > min_supported_bpp) { + if (mode_pclk_khz * bpp <= data_rate_khz) + break; + bpp -= 6; + } + + return bpp; +} + +static void dp_panel_set_test_mode(struct dp_panel_private *panel, + struct dp_display_mode *mode) +{ + struct drm_display_mode *drm_mode = NULL; + struct dp_link_test_video *test_info = NULL; + + drm_mode = &mode->drm_mode; + test_info = &panel->link->test_video; + + drm_mode->hdisplay = test_info->test_h_width; + drm_mode->hsync_start = drm_mode->hdisplay + test_info->test_h_total - + (test_info->test_h_start + test_info->test_h_width); + drm_mode->hsync_end = drm_mode->hsync_start + + test_info->test_hsync_width; + drm_mode->htotal = drm_mode->hsync_end + test_info->test_h_start - + test_info->test_hsync_width; + + drm_mode->vdisplay = test_info->test_v_height; + drm_mode->vsync_start = drm_mode->vdisplay + test_info->test_v_total - + (test_info->test_v_start + test_info->test_v_height); + drm_mode->vsync_end = drm_mode->vsync_start + + test_info->test_vsync_width; + drm_mode->vtotal = drm_mode->vsync_end + test_info->test_v_start - + test_info->test_vsync_width; + + drm_mode->clock = test_info->test_h_total * + test_info->test_v_total * test_info->test_rr_n; + + drm_mode->type = 0x48; + drm_mode_set_name(drm_mode); + + if (test_info->test_rr_d == 0) + drm_mode->clock /= 1000; + else + drm_mode->clock /= 1001; + + if (test_info->test_h_width == 640) + drm_mode->clock = 25170; +} + +static int dp_panel_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int rc = 0; + + if (edid) { + rc = drm_connector_update_edid_property(connector, edid); + if (rc) { + DRM_ERROR("failed to update edid property %d\n", rc); + return rc; + } + rc = drm_add_edid_modes(connector, edid); + DRM_DEBUG_DP("%s -", __func__); + return rc; + } + + rc = drm_connector_update_edid_property(connector, NULL); + if (rc) + DRM_ERROR("failed to update edid property %d\n", rc); + + return rc; +} + +int dp_panel_read_sink_caps(struct dp_panel *dp_panel, + struct drm_connector *connector) +{ + int rc = 0, bw_code; + struct dp_panel_private *panel; + + if (!dp_panel || !connector) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + + rc = dp_panel_read_dpcd(dp_panel); + bw_code = drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate); + if (rc || !is_link_rate_valid(bw_code) || + !is_lane_count_valid(dp_panel->link_info.num_lanes) || + (bw_code > dp_panel->max_bw_code)) { + DRM_ERROR("read dpcd failed %d\n", rc); + return rc; + } + rc = drm_dp_read_desc(panel->aux, &dp_panel->desc, + drm_dp_is_branch(dp_panel->dpcd)); + if (rc) { + DRM_ERROR("read sink/branch descriptor failed %d\n", rc); + return rc; + } + + kfree(dp_panel->edid); + dp_panel->edid = NULL; + + dp_panel->edid = drm_get_edid(connector, + &panel->aux->ddc); + if (!dp_panel->edid) { + DRM_ERROR("panel edid read failed\n"); + return -EINVAL; + } + + if (panel->aux_cfg_update_done) { + DRM_DEBUG_DP("read DPCD with updated AUX config\n"); + rc = dp_panel_read_dpcd(dp_panel); + bw_code = drm_dp_link_rate_to_bw_code(dp_panel->link_info.rate); + if (rc || !is_link_rate_valid(bw_code) || + !is_lane_count_valid(dp_panel->link_info.num_lanes) + || (bw_code > dp_panel->max_bw_code)) { + DRM_ERROR("read dpcd failed %d\n", rc); + return rc; + } + panel->aux_cfg_update_done = false; + } + + return 0; +} + +u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, + u32 mode_edid_bpp, u32 mode_pclk_khz) +{ + struct dp_panel_private *panel; + u32 bpp = mode_edid_bpp; + + if (!dp_panel || !mode_edid_bpp || !mode_pclk_khz) { + DRM_ERROR("invalid input\n"); + return 0; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + + if (dp_panel->video_test) + bpp = dp_link_bit_depth_to_bpp( + panel->link->test_video.test_bit_depth); + else + bpp = dp_panel_get_supported_bpp(dp_panel, mode_edid_bpp, + mode_pclk_khz); + + return bpp; +} + +int dp_panel_get_modes(struct dp_panel *dp_panel, + struct drm_connector *connector, struct dp_display_mode *mode) +{ + struct dp_panel_private *panel; + + if (!dp_panel) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + + if (dp_panel->video_test) { + dp_panel_set_test_mode(panel, mode); + return 1; + } else if (dp_panel->edid) { + return dp_panel_update_modes(connector, dp_panel->edid); + } + + return 0; +} + +static u8 dp_panel_get_edid_checksum(struct edid *edid) +{ + struct edid *last_block; + u8 *raw_edid; + bool is_edid_corrupt; + + if (!edid) { + DRM_ERROR("invalid edid input\n"); + return 0; + } + + raw_edid = (u8 *)edid; + raw_edid += (edid->extensions * EDID_LENGTH); + last_block = (struct edid *)raw_edid; + + /* block type extension */ + drm_edid_block_valid(raw_edid, 1, false, &is_edid_corrupt); + if (!is_edid_corrupt) + return last_block->checksum; + + DRM_ERROR("Invalid block, no checksum\n"); + return 0; +} + +void dp_panel_handle_sink_request(struct dp_panel *dp_panel) +{ + struct dp_panel_private *panel; + + if (!dp_panel) { + DRM_ERROR("invalid input\n"); + return; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + + if (panel->link->sink_request & DP_TEST_LINK_EDID_READ) { + u8 checksum = dp_panel_get_edid_checksum(dp_panel->edid); + + dp_link_send_edid_checksum(panel->link, checksum); + dp_link_send_test_response(panel->link); + } +} + +void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable) +{ + struct dp_catalog *catalog; + struct dp_panel_private *panel; + + if (!dp_panel) { + DRM_ERROR("invalid input\n"); + return; + } + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + catalog = panel->catalog; + + if (!panel->panel_on) { + DRM_DEBUG_DP("DP panel not enabled, handle TPG on next on\n"); + return; + } + + if (!enable) { + dp_catalog_panel_tpg_disable(catalog); + return; + } + + DRM_DEBUG_DP("%s: calling catalog tpg_enable\n", __func__); + dp_catalog_panel_tpg_enable(catalog, &panel->dp_panel.dp_mode.drm_mode); +} + +void dp_panel_dump_regs(struct dp_panel *dp_panel) +{ + struct dp_catalog *catalog; + struct dp_panel_private *panel; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + catalog = panel->catalog; + + dp_catalog_dump_regs(catalog); +} + +int dp_panel_timing_cfg(struct dp_panel *dp_panel) +{ + int rc = 0; + u32 data, total_ver, total_hor; + struct dp_catalog *catalog; + struct dp_panel_private *panel; + struct drm_display_mode *drm_mode; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + catalog = panel->catalog; + drm_mode = &panel->dp_panel.dp_mode.drm_mode; + + DRM_DEBUG_DP("width=%d hporch= %d %d %d\n", + drm_mode->hdisplay, drm_mode->htotal - drm_mode->hsync_end, + drm_mode->hsync_start - drm_mode->hdisplay, + drm_mode->hsync_end - drm_mode->hsync_start); + + DRM_DEBUG_DP("height=%d vporch= %d %d %d\n", + drm_mode->vdisplay, drm_mode->vtotal - drm_mode->vsync_end, + drm_mode->vsync_start - drm_mode->vdisplay, + drm_mode->vsync_end - drm_mode->vsync_start); + + total_hor = drm_mode->htotal; + + total_ver = drm_mode->vtotal; + + data = total_ver; + data <<= 16; + data |= total_hor; + + catalog->total = data; + + data = (drm_mode->vtotal - drm_mode->vsync_start); + data <<= 16; + data |= (drm_mode->htotal - drm_mode->hsync_start); + + catalog->sync_start = data; + + data = drm_mode->vsync_end - drm_mode->vsync_start; + data <<= 16; + data |= (panel->dp_panel.dp_mode.v_active_low << 31); + data |= drm_mode->hsync_end - drm_mode->hsync_start; + data |= (panel->dp_panel.dp_mode.h_active_low << 15); + + catalog->width_blanking = data; + + data = drm_mode->vdisplay; + data <<= 16; + data |= drm_mode->hdisplay; + + catalog->dp_active = data; + + dp_catalog_panel_timing_cfg(catalog); + panel->panel_on = true; + + return rc; +} + +int dp_panel_init_panel_info(struct dp_panel *dp_panel) +{ + int rc = 0; + struct drm_display_mode *drm_mode; + + drm_mode = &dp_panel->dp_mode.drm_mode; + + /* + * print resolution info as this is a result + * of user initiated action of cable connection + */ + DRM_DEBUG_DP("SET NEW RESOLUTION:\n"); + DRM_DEBUG_DP("%dx%d@%dfps\n", drm_mode->hdisplay, + drm_mode->vdisplay, drm_mode_vrefresh(drm_mode)); + DRM_DEBUG_DP("h_porches(back|front|width) = (%d|%d|%d)\n", + drm_mode->htotal - drm_mode->hsync_end, + drm_mode->hsync_start - drm_mode->hdisplay, + drm_mode->hsync_end - drm_mode->hsync_start); + DRM_DEBUG_DP("v_porches(back|front|width) = (%d|%d|%d)\n", + drm_mode->vtotal - drm_mode->vsync_end, + drm_mode->vsync_start - drm_mode->vdisplay, + drm_mode->vsync_end - drm_mode->vsync_start); + DRM_DEBUG_DP("pixel clock (KHz)=(%d)\n", drm_mode->clock); + DRM_DEBUG_DP("bpp = %d\n", dp_panel->dp_mode.bpp); + + dp_panel->dp_mode.bpp = max_t(u32, 18, + min_t(u32, dp_panel->dp_mode.bpp, 30)); + DRM_DEBUG_DP("updated bpp = %d\n", dp_panel->dp_mode.bpp); + + return rc; +} + +struct dp_panel *dp_panel_get(struct dp_panel_in *in) +{ + struct dp_panel_private *panel; + struct dp_panel *dp_panel; + + if (!in->dev || !in->catalog || !in->aux || !in->link) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-EINVAL); + } + + panel = devm_kzalloc(in->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; + + dp_panel = &panel->dp_panel; + dp_panel->max_bw_code = DP_LINK_BW_8_1; + panel->aux_cfg_update_done = false; + + return dp_panel; +} + +void dp_panel_put(struct dp_panel *dp_panel) +{ + if (!dp_panel) + return; + + kfree(dp_panel->edid); +} diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h new file mode 100644 index 0000000000000..f6f417eef2e9c --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_PANEL_H_ +#define _DP_PANEL_H_ + +#include <drm/msm_drm.h> + +#include "dp_aux.h" +#include "dp_link.h" +#include "dp_hpd.h" + +struct edid; + +#define DP_MAX_DOWNSTREAM_PORTS 0x10 +#define DPRX_EXTENDED_DPCD_FIELD 0x2200 + +struct dp_display_mode { + struct drm_display_mode drm_mode; + u32 capabilities; + u32 bpp; + u32 h_active_low; + u32 v_active_low; +}; + +struct dp_panel_in { + struct device *dev; + struct drm_dp_aux *aux; + struct dp_link *link; + struct dp_catalog *catalog; +}; + +struct dp_panel { + /* dpcd raw data */ + u8 dpcd[DP_RECEIVER_CAP_SIZE + 1]; + + struct dp_link_info link_info; + struct drm_dp_desc desc; + struct edid *edid; + struct drm_connector *connector; + struct dp_display_mode dp_mode; + bool video_test; + + u32 vic; + u32 max_pclk_khz; + u32 max_dp_lanes; + + u32 max_bw_code; +}; + +int dp_panel_init_panel_info(struct dp_panel *dp_panel); +int dp_panel_deinit(struct dp_panel *dp_panel); +int dp_panel_timing_cfg(struct dp_panel *dp_panel); +void dp_panel_dump_regs(struct dp_panel *dp_panel); +int dp_panel_read_sink_caps(struct dp_panel *dp_panel, + struct drm_connector *connector); +u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, u32 mode_max_bpp, + u32 mode_pclk_khz); +int dp_panel_get_modes(struct dp_panel *dp_panel, + struct drm_connector *connector, struct dp_display_mode *mode); +void dp_panel_handle_sink_request(struct dp_panel *dp_panel); +void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable); + +/** + * is_link_rate_valid() - validates the link rate + * @lane_rate: link rate requested by the sink + * + * Returns true if the requested link rate is supported. + */ +static inline bool is_link_rate_valid(u32 bw_code) +{ + return (bw_code == DP_LINK_BW_1_62 || + bw_code == DP_LINK_BW_2_7 || + bw_code == DP_LINK_BW_5_4 || + bw_code == DP_LINK_BW_8_1); +} + +/** + * dp_link_is_lane_count_valid() - validates the lane count + * @lane_count: lane count requested by the sink + * + * Returns true if the requested lane count is supported. + */ +static inline bool is_lane_count_valid(u32 lane_count) +{ + return (lane_count == 1 || + lane_count == 2 || + lane_count == 4); +} + +struct dp_panel *dp_panel_get(struct dp_panel_in *in); +void dp_panel_put(struct dp_panel *dp_panel); +#endif /* _DP_PANEL_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c new file mode 100644 index 0000000000000..19c14c1ddbb4d --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/of_gpio.h> + +#include "dp_parser.h" + +static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { + .num = 2, + .regs = { + {"vdda-1p2", 21800, 4 }, /* 1.2 V */ + {"vdda-0p9", 36000, 32 }, /* 0.9 V */ + }, +}; + +static int msm_dss_ioremap(struct platform_device *pdev, + struct dss_io_data *io_data) +{ + struct resource *res = NULL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + DRM_ERROR("%pS->%s: msm_dss_get_res failed\n", + __builtin_return_address(0), __func__); + return -ENODEV; + } + + io_data->len = (u32)resource_size(res); + io_data->base = ioremap(res->start, io_data->len); + if (!io_data->base) { + DRM_ERROR("%pS->%s: ioremap failed\n", + __builtin_return_address(0), __func__); + return -EIO; + } + + return 0; +} + +static void msm_dss_iounmap(struct dss_io_data *io_data) +{ + if (io_data->base) { + iounmap(io_data->base); + io_data->base = NULL; + } + io_data->len = 0; +} + +static void dp_parser_unmap_io_resources(struct dp_parser *parser) +{ + struct dp_io *io = &parser->io; + + msm_dss_iounmap(&io->dp_controller); + msm_dss_iounmap(&io->usb3_dp_com); +} + +static int dp_parser_ctrl_res(struct dp_parser *parser) +{ + int rc = 0; + struct platform_device *pdev = parser->pdev; + struct dp_io *io = &parser->io; + + rc = msm_dss_ioremap(pdev, &io->dp_controller); + if (rc) { + DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); + goto err; + } + + return 0; +err: + dp_parser_unmap_io_resources(parser); + return rc; +} + +static int dp_parser_misc(struct dp_parser *parser) +{ + struct device_node *of_node = parser->pdev->dev.of_node; + int len = 0; + const char *data_lane_property = "data-lanes"; + + len = of_property_count_elems_of_size(of_node, + data_lane_property, sizeof(u32)); + if (len < 0) { + DRM_WARN("Invalid property %s, default max DP lanes = %d\n", + data_lane_property, DP_MAX_NUM_DP_LANES); + len = DP_MAX_NUM_DP_LANES; + } + + parser->max_dp_lanes = len; + + return 0; +} + +static inline bool dp_parser_check_prefix(const char *clk_prefix, + const char *clk_name) +{ + return !strncmp(clk_prefix, clk_name, strlen(clk_prefix)); +} + +static int dp_parser_init_clk_data(struct dp_parser *parser) +{ + int num_clk, i, rc; + int core_clk_count = 0, ctrl_clk_count = 0; + const char *clk_name; + struct device *dev = &parser->pdev->dev; + struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; + struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; + + num_clk = of_property_count_strings(dev->of_node, "clock-names"); + if (num_clk <= 0) { + DRM_ERROR("no clocks are defined\n"); + return -EINVAL; + } + + for (i = 0; i < num_clk; i++) { + rc = of_property_read_string_index(dev->of_node, + "clock-names", i, &clk_name); + if (rc < 0) + return rc; + + if (dp_parser_check_prefix("core", clk_name)) + core_clk_count++; + + if (dp_parser_check_prefix("ctrl", clk_name)) + ctrl_clk_count++; + + if (dp_parser_check_prefix("stream", clk_name)) + ctrl_clk_count++; + } + + /* Initialize the CORE power module */ + if (core_clk_count == 0) { + DRM_ERROR("no core clocks are defined\n"); + return -EINVAL; + } + + core_power->num_clk = core_clk_count; + core_power->clk_config = devm_kzalloc(dev, + sizeof(struct dss_clk) * core_power->num_clk, + GFP_KERNEL); + if (!core_power->clk_config) + return -EINVAL; + + /* Initialize the CTRL power module */ + if (ctrl_clk_count == 0) { + DRM_ERROR("no ctrl clocks are defined\n"); + return -EINVAL; + } + + ctrl_power->num_clk = ctrl_clk_count; + ctrl_power->clk_config = devm_kzalloc(dev, + sizeof(struct dss_clk) * ctrl_power->num_clk, + GFP_KERNEL); + if (!ctrl_power->clk_config) { + ctrl_power->num_clk = 0; + return -EINVAL; + } + + return 0; +} + +static int dp_parser_clock(struct dp_parser *parser) +{ + int rc = 0, i = 0; + int num_clk = 0; + int core_clk_index = 0, ctrl_clk_index = 0; + int core_clk_count = 0, ctrl_clk_count = 0; + const char *clk_name; + struct device *dev = &parser->pdev->dev; + struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; + struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; + + core_power = &parser->mp[DP_CORE_PM]; + ctrl_power = &parser->mp[DP_CTRL_PM]; + + rc = dp_parser_init_clk_data(parser); + if (rc) { + DRM_ERROR("failed to initialize power data %d\n", rc); + return -EINVAL; + } + + core_clk_count = core_power->num_clk; + ctrl_clk_count = ctrl_power->num_clk; + + num_clk = core_clk_count + ctrl_clk_count; + + for (i = 0; i < num_clk; i++) { + rc = of_property_read_string_index(dev->of_node, "clock-names", + i, &clk_name); + if (rc) { + DRM_ERROR("error reading clock-names %d\n", rc); + return rc; + } + if (dp_parser_check_prefix("core", clk_name) && + core_clk_index < core_clk_count) { + struct dss_clk *clk = + &core_power->clk_config[core_clk_index]; + strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); + clk->type = DSS_CLK_AHB; + core_clk_index++; + } else if ((dp_parser_check_prefix("ctrl", clk_name) || + dp_parser_check_prefix("stream", clk_name)) && + ctrl_clk_index < ctrl_clk_count) { + struct dss_clk *clk = + &ctrl_power->clk_config[ctrl_clk_index]; + strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); + ctrl_clk_index++; + + if (dp_parser_check_prefix("ctrl_link", clk_name) || + dp_parser_check_prefix("stream_pixel", clk_name)) + clk->type = DSS_CLK_PCLK; + else + clk->type = DSS_CLK_AHB; + } + } + + DRM_DEBUG_DP("clock parsing successful\n"); + + return 0; +} + +static int dp_parser_parse(struct dp_parser *parser) +{ + int rc = 0; + + if (!parser) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + rc = dp_parser_ctrl_res(parser); + if (rc) + return rc; + + rc = dp_parser_misc(parser); + if (rc) + return rc; + + rc = dp_parser_clock(parser); + if (rc) + return rc; + + /* Map the corresponding regulator information according to + * version. Currently, since we only have one supported platform, + * mapping the regulator directly. + */ + parser->regulator_cfg = &sdm845_dp_reg_cfg; + + return 0; +} + +struct dp_parser *dp_parser_get(struct platform_device *pdev) +{ + struct dp_parser *parser; + + parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL); + if (!parser) + return ERR_PTR(-ENOMEM); + + parser->parse = dp_parser_parse; + parser->pdev = pdev; + + return parser; +} diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h new file mode 100644 index 0000000000000..2085b15aa4cf1 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_PARSER_H_ +#define _DP_PARSER_H_ + +#include <linux/platform_device.h> + +#include "dpu_io_util.h" +#include "msm_drv.h" + +#define DP_LABEL "MDSS DP DISPLAY" +#define DP_MAX_PIXEL_CLK_KHZ 675000 +#define DP_MAX_NUM_DP_LANES 4 + +enum dp_pm_type { + DP_CORE_PM, + DP_CTRL_PM, + DP_PHY_PM, + DP_MAX_PM +}; + +struct dss_io_data { + u32 len; + void __iomem *base; +}; + +static inline const char *dp_parser_pm_name(enum dp_pm_type module) +{ + switch (module) { + case DP_CORE_PM: return "DP_CORE_PM"; + case DP_CTRL_PM: return "DP_CTRL_PM"; + case DP_PHY_PM: return "DP_PHY_PM"; + default: return "???"; + } +} + +/** + * struct dp_display_data - display related device tree data. + * + * @ctrl_node: referece to controller device + * @phy_node: reference to phy device + * @is_active: is the controller currently active + * @name: name of the display + * @display_type: type of the display + */ +struct dp_display_data { + struct device_node *ctrl_node; + struct device_node *phy_node; + bool is_active; + const char *name; + const char *display_type; +}; + +/** + * struct dp_ctrl_resource - controller's IO related data + * + * @dp_controller: Display Port controller mapped memory address + * @phy_io: phy's mapped memory address + * @ln_tx0_io: USB-DP lane TX0's mapped memory address + * @ln_tx1_io: USB-DP lane TX1's mapped memory address + * @dp_pll_io: DP PLL mapped memory address + * @usb3_dp_com: USB3 DP PHY combo mapped memory address + */ +struct dp_io { + struct dss_io_data dp_controller; + struct dss_io_data phy_io; + struct dss_io_data ln_tx0_io; + struct dss_io_data ln_tx1_io; + struct dss_io_data dp_pll_io; + struct dss_io_data usb3_dp_com; +}; + +/** + * struct dp_pinctrl - DP's pin control + * + * @pin: pin-controller's instance + * @state_active: active state pin control + * @state_hpd_active: hpd active state pin control + * @state_suspend: suspend state pin control + */ +struct dp_pinctrl { + struct pinctrl *pin; + struct pinctrl_state *state_active; + struct pinctrl_state *state_hpd_active; + struct pinctrl_state *state_suspend; +}; + +#define DP_DEV_REGULATOR_MAX 4 + +/* Regulators for DP devices */ +struct dp_reg_entry { + char name[32]; + int enable_load; + int disable_load; +}; + +struct dp_regulator_cfg { + int num; + struct dp_reg_entry regs[DP_DEV_REGULATOR_MAX]; +}; + +/** + * struct dp_parser - DP parser's data exposed to clients + * + * @pdev: platform data of the client + * @mp: gpio, regulator and clock related data + * @pinctrl: pin-control related data + * @disp_data: controller's display related data + * @parse: function to be called by client to parse device tree. + */ +struct dp_parser { + struct platform_device *pdev; + struct dss_module_power mp[DP_MAX_PM]; + struct dp_pinctrl pinctrl; + struct dp_io io; + struct dp_display_data disp_data; + const struct dp_regulator_cfg *regulator_cfg; + u32 max_dp_lanes; + + int (*parse)(struct dp_parser *parser); +}; + +/** + * dp_parser_get() - get the DP's device tree parser module + * + * @pdev: platform data of the client + * return: pointer to dp_parser structure. + * + * This function provides client capability to parse the + * device tree and populate the data structures. The data + * related to clock, regulators, pin-control and other + * can be parsed using this module. + */ +struct dp_parser *dp_parser_get(struct platform_device *pdev); + +#endif diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c new file mode 100644 index 0000000000000..4aaa0aae48832 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/regulator/consumer.h> +#include "dp_power.h" + +struct dp_power_private { + struct dp_parser *parser; + struct platform_device *pdev; + struct clk *link_clk_src; + struct clk *pixel_provider; + struct clk *link_provider; + struct regulator_bulk_data supplies[DP_DEV_REGULATOR_MAX]; + + struct dp_power dp_power; +}; + +static void dp_power_regulator_disable(struct dp_power_private *power) +{ + struct regulator_bulk_data *s = power->supplies; + const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; + int num = power->parser->regulator_cfg->num; + int i; + + DBG(""); + for (i = num - 1; i >= 0; i--) + if (regs[i].disable_load >= 0) + regulator_set_load(s[i].consumer, + regs[i].disable_load); + + regulator_bulk_disable(num, s); +} + +static int dp_power_regulator_enable(struct dp_power_private *power) +{ + struct regulator_bulk_data *s = power->supplies; + const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; + int num = power->parser->regulator_cfg->num; + int ret, i; + + DBG(""); + for (i = 0; i < num; i++) { + if (regs[i].enable_load >= 0) { + ret = regulator_set_load(s[i].consumer, + regs[i].enable_load); + if (ret < 0) { + pr_err("regulator %d set op mode failed, %d\n", + i, ret); + goto fail; + } + } + } + + ret = regulator_bulk_enable(num, s); + if (ret < 0) { + pr_err("regulator enable failed, %d\n", ret); + goto fail; + } + + return 0; + +fail: + for (i--; i >= 0; i--) + regulator_set_load(s[i].consumer, regs[i].disable_load); + return ret; +} + +static int dp_power_regulator_init(struct dp_power_private *power) +{ + struct regulator_bulk_data *s = power->supplies; + const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; + struct platform_device *pdev = power->pdev; + int num = power->parser->regulator_cfg->num; + int i, ret; + + for (i = 0; i < num; i++) + s[i].supply = regs[i].name; + + ret = devm_regulator_bulk_get(&pdev->dev, num, s); + if (ret < 0) { + pr_err("%s: failed to init regulator, ret=%d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int dp_power_clk_init(struct dp_power_private *power) +{ + int rc = 0; + struct dss_module_power *core, *ctrl; + struct device *dev = &power->pdev->dev; + + core = &power->parser->mp[DP_CORE_PM]; + ctrl = &power->parser->mp[DP_CTRL_PM]; + + rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk); + if (rc) { + DRM_ERROR("failed to get %s clk. err=%d\n", + dp_parser_pm_name(DP_CORE_PM), rc); + return rc; + } + + rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk); + if (rc) { + DRM_ERROR("failed to get %s clk. err=%d\n", + dp_parser_pm_name(DP_CTRL_PM), rc); + msm_dss_put_clk(core->clk_config, core->num_clk); + return -ENODEV; + } + + return 0; +} + +static int dp_power_clk_deinit(struct dp_power_private *power) +{ + struct dss_module_power *core, *ctrl; + + core = &power->parser->mp[DP_CORE_PM]; + ctrl = &power->parser->mp[DP_CTRL_PM]; + + if (!core || !ctrl) + return -EINVAL; + + msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk); + msm_dss_put_clk(core->clk_config, core->num_clk); + return 0; +} + +static int dp_power_clk_set_rate(struct dp_power_private *power, + enum dp_pm_type module, bool enable) +{ + int rc = 0; + struct dss_module_power *mp = &power->parser->mp[module]; + + if (enable) { + rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); + if (rc) { + DRM_ERROR("failed to set clks rate.\n"); + return rc; + } + } + + rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); + if (rc) { + DRM_ERROR("failed to %d clks, err: %d\n", enable, rc); + return rc; + } + + return 0; +} + +int dp_power_clk_enable(struct dp_power *dp_power, + enum dp_pm_type pm_type, bool enable) +{ + int rc = 0; + struct dp_power_private *power; + + power = container_of(dp_power, struct dp_power_private, dp_power); + + if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM) { + DRM_ERROR("unsupported power module: %s\n", + dp_parser_pm_name(pm_type)); + return -EINVAL; + } + + if (enable) { + if (pm_type == DP_CORE_PM && dp_power->core_clks_on) { + DRM_DEBUG_DP("core clks already enabled\n"); + return 0; + } + + if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) { + DRM_DEBUG_DP("links clks already enabled\n"); + return 0; + } + + if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) { + DRM_DEBUG_DP("Enable core clks before link clks\n"); + + rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable); + if (rc) { + DRM_ERROR("fail to enable clks: %s. err=%d\n", + dp_parser_pm_name(DP_CORE_PM), rc); + return rc; + } + dp_power->core_clks_on = true; + } + } + + rc = dp_power_clk_set_rate(power, pm_type, enable); + if (rc) { + DRM_ERROR("failed to '%s' clks for: %s. err=%d\n", + enable ? "enable" : "disable", + dp_parser_pm_name(pm_type), rc); + return rc; + } + + if (pm_type == DP_CORE_PM) + dp_power->core_clks_on = enable; + else + dp_power->link_clks_on = enable; + + DRM_DEBUG_DP("%s clocks for %s\n", + enable ? "enable" : "disable", + dp_parser_pm_name(pm_type)); + DRM_DEBUG_DP("link_clks:%s core_clks:%s\n", + dp_power->link_clks_on ? "on" : "off", + dp_power->core_clks_on ? "on" : "off"); + + return 0; +} + +int dp_power_client_init(struct dp_power *dp_power) +{ + int rc = 0; + struct dp_power_private *power; + + if (!dp_power) { + DRM_ERROR("invalid power data\n"); + return -EINVAL; + } + + power = container_of(dp_power, struct dp_power_private, dp_power); + + pm_runtime_enable(&power->pdev->dev); + + rc = dp_power_regulator_init(power); + if (rc) { + DRM_ERROR("failed to init regulators %d\n", rc); + goto error; + } + + rc = dp_power_clk_init(power); + if (rc) { + DRM_ERROR("failed to init clocks %d\n", rc); + goto error; + } + return 0; + +error: + pm_runtime_disable(&power->pdev->dev); + return rc; +} + +void dp_power_client_deinit(struct dp_power *dp_power) +{ + struct dp_power_private *power; + + if (!dp_power) { + DRM_ERROR("invalid power data\n"); + return; + } + + power = container_of(dp_power, struct dp_power_private, dp_power); + + dp_power_clk_deinit(power); + pm_runtime_disable(&power->pdev->dev); + +} + +int dp_power_set_link_clk_parent(struct dp_power *dp_power) +{ + int rc = 0; + struct dp_power_private *power; + u32 num; + struct dss_clk *cfg; + char *name = "ctrl_link"; + + if (!dp_power) { + DRM_ERROR("invalid power data\n"); + rc = -EINVAL; + goto exit; + } + + power = container_of(dp_power, struct dp_power_private, dp_power); + + num = power->parser->mp[DP_CTRL_PM].num_clk; + cfg = power->parser->mp[DP_CTRL_PM].clk_config; + + while (num && strcmp(cfg->clk_name, name)) { + num--; + cfg++; + } + +exit: + return rc; +} + +int dp_power_init(struct dp_power *dp_power, bool flip) +{ + int rc = 0; + struct dp_power_private *power = NULL; + + if (!dp_power) { + DRM_ERROR("invalid power data\n"); + return -EINVAL; + } + + power = container_of(dp_power, struct dp_power_private, dp_power); + + pm_runtime_get_sync(&power->pdev->dev); + rc = dp_power_regulator_enable(power); + if (rc) { + DRM_ERROR("failed to enable regulators, %d\n", rc); + goto exit; + } + + rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); + if (rc) { + DRM_ERROR("failed to enable DP core clocks, %d\n", rc); + goto err_clk; + } + + return 0; + +err_clk: + dp_power_regulator_disable(power); +exit: + pm_runtime_put_sync(&power->pdev->dev); + return rc; +} + +int dp_power_deinit(struct dp_power *dp_power) +{ + struct dp_power_private *power; + + power = container_of(dp_power, struct dp_power_private, dp_power); + + dp_power_clk_enable(dp_power, DP_CORE_PM, false); + dp_power_regulator_disable(power); + pm_runtime_put_sync(&power->pdev->dev); + return 0; +} + +struct dp_power *dp_power_get(struct dp_parser *parser) +{ + struct dp_power_private *power; + struct dp_power *dp_power; + + if (!parser) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-EINVAL); + } + + power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL); + if (!power) + return ERR_PTR(-ENOMEM); + + power->parser = parser; + power->pdev = parser->pdev; + + dp_power = &power->dp_power; + + return dp_power; +} diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h new file mode 100644 index 0000000000000..ae55b78bf54a1 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_power.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_POWER_H_ +#define _DP_POWER_H_ + +#include "dp_parser.h" + +/** + * sruct dp_power - DisplayPort's power related data + * + * @init: initializes the regulators/core clocks/GPIOs/pinctrl + * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl + * @clk_enable: enable/disable the DP clocks + * @set_link_clk_parent: set the parent of DP link clock + * @set_pixel_clk_parent: set the parent of DP pixel clock + */ +struct dp_power { + bool core_clks_on; + bool link_clks_on; +}; + +int dp_power_init(struct dp_power *power, bool flip); +int dp_power_deinit(struct dp_power *power); +int dp_power_clk_enable(struct dp_power *power, enum dp_pm_type pm_type, + bool enable); +int dp_power_set_link_clk_parent(struct dp_power *power); + +/** + * dp_power_client_init() - initialize clock and regulator modules + * + * @power: instance of power module + * return: 0 for success, error for failure. + * + * This API will configure the DisplayPort's clocks and regulator + * modules. + */ +int dp_power_client_init(struct dp_power *power); + +/** + * dp_power_clinet_deinit() - de-initialize clock and regulator modules + * + * @power: instance of power module + * return: 0 for success, error for failure. + * + * This API will de-initialize the DisplayPort's clocks and regulator + * modueles. + */ +void dp_power_client_deinit(struct dp_power *power); + +/** + * dp_power_get() - configure and get the DisplayPort power module data + * + * @parser: instance of parser module + * return: pointer to allocated power module data + * + * This API will configure the DisplayPort's power module and provides + * methods to be called by the client to configure the power related + * modueles. + */ +struct dp_power *dp_power_get(struct dp_parser *parser); + +#endif /* _DP_POWER_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h new file mode 100644 index 0000000000000..67a2d040b221a --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_REG_H_ +#define _DP_REG_H_ + +/* DP_TX Registers */ +#define REG_DP_HW_VERSION (0x00000000) + +#define REG_DP_SW_RESET (0x00000010) +#define DP_SW_RESET (0x00000001) + +#define REG_DP_PHY_CTRL (0x00000014) +#define DP_PHY_CTRL_SW_RESET_PLL (0x00000001) +#define DP_PHY_CTRL_SW_RESET (0x00000004) + +#define REG_DP_CLK_CTRL (0x00000018) +#define REG_DP_CLK_ACTIVE (0x0000001C) +#define REG_DP_INTR_STATUS (0x00000020) +#define REG_DP_INTR_STATUS2 (0x00000024) +#define REG_DP_INTR_STATUS3 (0x00000028) + +#define REG_DP_DP_HPD_CTRL (0x00000000) +#define DP_DP_HPD_CTRL_HPD_EN (0x00000001) + +#define REG_DP_DP_HPD_INT_STATUS (0x00000004) + +#define REG_DP_DP_HPD_INT_ACK (0x00000008) +#define DP_DP_HPD_PLUG_INT_ACK (0x00000001) +#define DP_DP_IRQ_HPD_INT_ACK (0x00000002) +#define DP_DP_HPD_REPLUG_INT_ACK (0x00000004) +#define DP_DP_HPD_UNPLUG_INT_ACK (0x00000008) + +#define REG_DP_DP_HPD_INT_MASK (0x0000000C) +#define DP_DP_HPD_PLUG_INT_MASK (0x00000001) +#define DP_DP_IRQ_HPD_INT_MASK (0x00000002) +#define DP_DP_HPD_REPLUG_INT_MASK (0x00000004) +#define DP_DP_HPD_UNPLUG_INT_MASK (0x00000008) + +#define REG_DP_DP_HPD_REFTIMER (0x00000018) +#define REG_DP_DP_HPD_EVENT_TIME_0 (0x0000001C) +#define REG_DP_DP_HPD_EVENT_TIME_1 (0x00000020) + +#define REG_DP_AUX_CTRL (0x00000030) +#define DP_AUX_CTRL_ENABLE (0x00000001) +#define DP_AUX_CTRL_RESET (0x00000002) + +#define REG_DP_AUX_DATA (0x00000034) +#define DP_AUX_DATA_READ (0x00000001) +#define DP_AUX_DATA_WRITE (0x00000000) +#define DP_AUX_DATA_OFFSET (0x00000008) +#define DP_AUX_DATA_INDEX_OFFSET (0x00000010) +#define DP_AUX_DATA_MASK (0x0000ff00) +#define DP_AUX_DATA_INDEX_WRITE (0x80000000) + +#define REG_DP_AUX_TRANS_CTRL (0x00000038) +#define DP_AUX_TRANS_CTRL_I2C (0x00000100) +#define DP_AUX_TRANS_CTRL_GO (0x00000200) +#define DP_AUX_TRANS_CTRL_NO_SEND_ADDR (0x00000400) +#define DP_AUX_TRANS_CTRL_NO_SEND_STOP (0x00000800) + +#define REG_DP_TIMEOUT_COUNT (0x0000003C) +#define REG_DP_AUX_LIMITS (0x00000040) +#define REG_DP_AUX_STATUS (0x00000044) + +#define DP_DPCD_CP_IRQ (0x201) +#define DP_DPCD_RXSTATUS (0x69493) + +#define DP_INTERRUPT_TRANS_NUM (0x000000A0) + +#define REG_DP_MAINLINK_CTRL (0x00000000) +#define DP_MAINLINK_CTRL_ENABLE (0x00000001) +#define DP_MAINLINK_CTRL_RESET (0x00000002) +#define DP_MAINLINK_FB_BOUNDARY_SEL (0x02000000) + +#define REG_DP_STATE_CTRL (0x00000004) +#define DP_STATE_CTRL_LINK_TRAINING_PATTERN1 (0x00000001) +#define DP_STATE_CTRL_LINK_TRAINING_PATTERN2 (0x00000002) +#define DP_STATE_CTRL_LINK_TRAINING_PATTERN3 (0x00000004) +#define DP_STATE_CTRL_LINK_TRAINING_PATTERN4 (0x00000008) +#define DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE (0x00000010) +#define DP_STATE_CTRL_LINK_PRBS7 (0x00000020) +#define DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN (0x00000040) +#define DP_STATE_CTRL_SEND_VIDEO (0x00000080) +#define DP_STATE_CTRL_PUSH_IDLE (0x00000100) + +#define REG_DP_CONFIGURATION_CTRL (0x00000008) +#define DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK (0x00000001) +#define DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN (0x00000002) +#define DP_CONFIGURATION_CTRL_P_INTERLACED (0x00000004) +#define DP_CONFIGURATION_CTRL_INTERLACED_BTF (0x00000008) +#define DP_CONFIGURATION_CTRL_NUM_OF_LANES (0x00000010) +#define DP_CONFIGURATION_CTRL_ENHANCED_FRAMING (0x00000040) +#define DP_CONFIGURATION_CTRL_SEND_VSC (0x00000080) +#define DP_CONFIGURATION_CTRL_BPC (0x00000100) +#define DP_CONFIGURATION_CTRL_ASSR (0x00000400) +#define DP_CONFIGURATION_CTRL_RGB_YUV (0x00000800) +#define DP_CONFIGURATION_CTRL_LSCLK_DIV (0x00002000) +#define DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT (0x04) +#define DP_CONFIGURATION_CTRL_BPC_SHIFT (0x08) +#define DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT (0x0D) + +#define REG_DP_SOFTWARE_MVID (0x00000010) +#define REG_DP_SOFTWARE_NVID (0x00000018) +#define REG_DP_TOTAL_HOR_VER (0x0000001C) +#define REG_DP_START_HOR_VER_FROM_SYNC (0x00000020) +#define REG_DP_HSYNC_VSYNC_WIDTH_POLARITY (0x00000024) +#define REG_DP_ACTIVE_HOR_VER (0x00000028) + +#define REG_DP_MISC1_MISC0 (0x0000002C) +#define DP_MISC0_SYNCHRONOUS_CLK (0x00000001) +#define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001) +#define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005) + +#define REG_DP_VALID_BOUNDARY (0x00000030) +#define REG_DP_VALID_BOUNDARY_2 (0x00000034) + +#define REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING (0x00000038) +#define LANE0_MAPPING_SHIFT (0x00000000) +#define LANE1_MAPPING_SHIFT (0x00000002) +#define LANE2_MAPPING_SHIFT (0x00000004) +#define LANE3_MAPPING_SHIFT (0x00000006) + +#define REG_DP_MAINLINK_READY (0x00000040) +#define DP_MAINLINK_READY_FOR_VIDEO (0x00000001) +#define DP_MAINLINK_READY_LINK_TRAINING_SHIFT (0x00000003) + +#define REG_DP_MAINLINK_LEVELS (0x00000044) +#define DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2 (0x00000002) + + +#define REG_DP_TU (0x0000004C) + +#define REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET (0x00000054) +#define DP_HBR2_ERM_PATTERN (0x00010000) + +#define REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0 (0x000000C0) +#define REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1 (0x000000C4) +#define REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2 (0x000000C8) + +#define MMSS_DP_MISC1_MISC0 (0x0000002C) +#define MMSS_DP_AUDIO_TIMING_GEN (0x00000080) +#define MMSS_DP_AUDIO_TIMING_RBR_32 (0x00000084) +#define MMSS_DP_AUDIO_TIMING_HBR_32 (0x00000088) +#define MMSS_DP_AUDIO_TIMING_RBR_44 (0x0000008C) +#define MMSS_DP_AUDIO_TIMING_HBR_44 (0x00000090) +#define MMSS_DP_AUDIO_TIMING_RBR_48 (0x00000094) +#define MMSS_DP_AUDIO_TIMING_HBR_48 (0x00000098) + +#define MMSS_DP_PSR_CRC_RG (0x00000154) +#define MMSS_DP_PSR_CRC_B (0x00000158) + +#define REG_DP_COMPRESSION_MODE_CTRL (0x00000180) + +#define MMSS_DP_AUDIO_CFG (0x00000200) +#define MMSS_DP_AUDIO_STATUS (0x00000204) +#define MMSS_DP_AUDIO_PKT_CTRL (0x00000208) +#define MMSS_DP_AUDIO_PKT_CTRL2 (0x0000020C) +#define MMSS_DP_AUDIO_ACR_CTRL (0x00000210) +#define MMSS_DP_AUDIO_CTRL_RESET (0x00000214) + +#define MMSS_DP_SDP_CFG (0x00000228) +#define MMSS_DP_SDP_CFG2 (0x0000022C) +#define MMSS_DP_AUDIO_TIMESTAMP_0 (0x00000230) +#define MMSS_DP_AUDIO_TIMESTAMP_1 (0x00000234) + +#define MMSS_DP_AUDIO_STREAM_0 (0x00000240) +#define MMSS_DP_AUDIO_STREAM_1 (0x00000244) + +#define MMSS_DP_EXTENSION_0 (0x00000250) +#define MMSS_DP_EXTENSION_1 (0x00000254) +#define MMSS_DP_EXTENSION_2 (0x00000258) +#define MMSS_DP_EXTENSION_3 (0x0000025C) +#define MMSS_DP_EXTENSION_4 (0x00000260) +#define MMSS_DP_EXTENSION_5 (0x00000264) +#define MMSS_DP_EXTENSION_6 (0x00000268) +#define MMSS_DP_EXTENSION_7 (0x0000026C) +#define MMSS_DP_EXTENSION_8 (0x00000270) +#define MMSS_DP_EXTENSION_9 (0x00000274) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_0 (0x00000278) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_1 (0x0000027C) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_2 (0x00000280) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_3 (0x00000284) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_4 (0x00000288) +#define MMSS_DP_AUDIO_COPYMANAGEMENT_5 (0x0000028C) +#define MMSS_DP_AUDIO_ISRC_0 (0x00000290) +#define MMSS_DP_AUDIO_ISRC_1 (0x00000294) +#define MMSS_DP_AUDIO_ISRC_2 (0x00000298) +#define MMSS_DP_AUDIO_ISRC_3 (0x0000029C) +#define MMSS_DP_AUDIO_ISRC_4 (0x000002A0) +#define MMSS_DP_AUDIO_ISRC_5 (0x000002A4) +#define MMSS_DP_AUDIO_INFOFRAME_0 (0x000002A8) +#define MMSS_DP_AUDIO_INFOFRAME_1 (0x000002AC) +#define MMSS_DP_AUDIO_INFOFRAME_2 (0x000002B0) + +#define MMSS_DP_GENERIC0_0 (0x00000300) +#define MMSS_DP_GENERIC0_1 (0x00000304) +#define MMSS_DP_GENERIC0_2 (0x00000308) +#define MMSS_DP_GENERIC0_3 (0x0000030C) +#define MMSS_DP_GENERIC0_4 (0x00000310) +#define MMSS_DP_GENERIC0_5 (0x00000314) +#define MMSS_DP_GENERIC0_6 (0x00000318) +#define MMSS_DP_GENERIC0_7 (0x0000031C) +#define MMSS_DP_GENERIC0_8 (0x00000320) +#define MMSS_DP_GENERIC0_9 (0x00000324) +#define MMSS_DP_GENERIC1_0 (0x00000328) +#define MMSS_DP_GENERIC1_1 (0x0000032C) +#define MMSS_DP_GENERIC1_2 (0x00000330) +#define MMSS_DP_GENERIC1_3 (0x00000334) +#define MMSS_DP_GENERIC1_4 (0x00000338) +#define MMSS_DP_GENERIC1_5 (0x0000033C) +#define MMSS_DP_GENERIC1_6 (0x00000340) +#define MMSS_DP_GENERIC1_7 (0x00000344) +#define MMSS_DP_GENERIC1_8 (0x00000348) +#define MMSS_DP_GENERIC1_9 (0x0000034C) + +#define MMSS_DP_VSCEXT_0 (0x000002D0) +#define MMSS_DP_VSCEXT_1 (0x000002D4) +#define MMSS_DP_VSCEXT_2 (0x000002D8) +#define MMSS_DP_VSCEXT_3 (0x000002DC) +#define MMSS_DP_VSCEXT_4 (0x000002E0) +#define MMSS_DP_VSCEXT_5 (0x000002E4) +#define MMSS_DP_VSCEXT_6 (0x000002E8) +#define MMSS_DP_VSCEXT_7 (0x000002EC) +#define MMSS_DP_VSCEXT_8 (0x000002F0) +#define MMSS_DP_VSCEXT_9 (0x000002F4) + +#define MMSS_DP_BIST_ENABLE (0x00000000) +#define DP_BIST_ENABLE_DPBIST_EN (0x00000001) + +#define MMSS_DP_TIMING_ENGINE_EN (0x00000010) +#define DP_TIMING_ENGINE_EN_EN (0x00000001) + +#define MMSS_DP_INTF_CONFIG (0x00000014) +#define MMSS_DP_INTF_HSYNC_CTL (0x00000018) +#define MMSS_DP_INTF_VSYNC_PERIOD_F0 (0x0000001C) +#define MMSS_DP_INTF_VSYNC_PERIOD_F1 (0x00000020) +#define MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F0 (0x00000024) +#define MMSS_DP_INTF_VSYNC_PULSE_WIDTH_F1 (0x00000028) +#define MMSS_INTF_DISPLAY_V_START_F0 (0x0000002C) +#define MMSS_INTF_DISPLAY_V_START_F1 (0x00000030) +#define MMSS_DP_INTF_DISPLAY_V_END_F0 (0x00000034) +#define MMSS_DP_INTF_DISPLAY_V_END_F1 (0x00000038) +#define MMSS_DP_INTF_ACTIVE_V_START_F0 (0x0000003C) +#define MMSS_DP_INTF_ACTIVE_V_START_F1 (0x00000040) +#define MMSS_DP_INTF_ACTIVE_V_END_F0 (0x00000044) +#define MMSS_DP_INTF_ACTIVE_V_END_F1 (0x00000048) +#define MMSS_DP_INTF_DISPLAY_HCTL (0x0000004C) +#define MMSS_DP_INTF_ACTIVE_HCTL (0x00000050) +#define MMSS_DP_INTF_POLARITY_CTL (0x00000058) + +#define MMSS_DP_TPG_MAIN_CONTROL (0x00000060) +#define MMSS_DP_DSC_DTO (0x0000007C) +#define DP_TPG_CHECKERED_RECT_PATTERN (0x00000100) + +#define MMSS_DP_TPG_VIDEO_CONFIG (0x00000064) +#define DP_TPG_VIDEO_CONFIG_BPP_8BIT (0x00000001) +#define DP_TPG_VIDEO_CONFIG_RGB (0x00000004) + +#define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000088) + +/*DP PHY Register offsets */ +#define REG_DP_PHY_REVISION_ID0 (0x00000000) +#define REG_DP_PHY_REVISION_ID1 (0x00000004) +#define REG_DP_PHY_REVISION_ID2 (0x00000008) +#define REG_DP_PHY_REVISION_ID3 (0x0000000C) + +#define REG_DP_PHY_CFG (0x00000010) + +#define REG_DP_PHY_PD_CTL (0x00000018) +#define DP_PHY_PD_CTL_PWRDN (0x00000001) +#define DP_PHY_PD_CTL_PSR_PWRDN (0x00000002) +#define DP_PHY_PD_CTL_AUX_PWRDN (0x00000004) +#define DP_PHY_PD_CTL_LANE_0_1_PWRDN (0x00000008) +#define DP_PHY_PD_CTL_LANE_2_3_PWRDN (0x00000010) +#define DP_PHY_PD_CTL_PLL_PWRDN (0x00000020) +#define DP_PHY_PD_CTL_DP_CLAMP_EN (0x00000040) + +#define REG_DP_PHY_MODE (0x0000001C) + +#define REG_DP_PHY_AUX_CFG0 (0x00000020) +#define REG_DP_PHY_AUX_CFG1 (0x00000024) +#define REG_DP_PHY_AUX_CFG2 (0x00000028) +#define REG_DP_PHY_AUX_CFG3 (0x0000002C) +#define REG_DP_PHY_AUX_CFG4 (0x00000030) +#define REG_DP_PHY_AUX_CFG5 (0x00000034) +#define REG_DP_PHY_AUX_CFG6 (0x00000038) +#define REG_DP_PHY_AUX_CFG7 (0x0000003C) +#define REG_DP_PHY_AUX_CFG8 (0x00000040) +#define REG_DP_PHY_AUX_CFG9 (0x00000044) + +#define REG_DP_PHY_AUX_INTERRUPT_MASK (0x00000048) +#define PHY_AUX_STOP_ERR_MASK (0x00000001) +#define PHY_AUX_DEC_ERR_MASK (0x00000002) +#define PHY_AUX_SYNC_ERR_MASK (0x00000004) +#define PHY_AUX_ALIGN_ERR_MASK (0x00000008) +#define PHY_AUX_REQ_ERR_MASK (0x00000010) + + +#define REG_DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C) +#define REG_DP_PHY_AUX_BIST_CFG (0x00000050) +#define REG_DP_PHY_AUX_INTERRUPT_STATUS (0x000000BC) + +#define REG_DP_PHY_VCO_DIV 0x0064 +#define REG_DP_PHY_TX0_TX1_LANE_CTL 0x006C +#define REG_DP_PHY_TX2_TX3_LANE_CTL 0x0088 + +#define REG_DP_PHY_SPARE0 (0x00AC) +#define DP_PHY_SPARE0_MASK (0x000F) +#define DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT (0x0004) + +#define REG_DP_PHY_STATUS (0x00C0) + +/* Tx registers */ +#define REG_DP_PHY_TXn_BIST_MODE_LANENO 0x0000 +#define REG_DP_PHY_TXn_CLKBUF_ENABLE 0x0008 + +#define REG_DP_PHY_TXn_TX_EMP_POST1_LVL 0x000C +#define DP_PHY_TXn_TX_EMP_POST1_LVL_MASK 0x001F +#define DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN 0x0020 + +#define REG_DP_PHY_TXn_TX_DRV_LVL 0x001C +#define DP_PHY_TXn_TX_DRV_LVL_MASK 0x001F +#define DP_PHY_TXn_TX_DRV_LVL_MUX_EN 0x0020 + +#define REG_DP_PHY_TXn_RESET_TSYNC_EN 0x0024 +#define REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN 0x0028 +#define REG_DP_PHY_TXn_TX_BAND 0x002C +#define REG_DP_PHY_TXn_SLEW_CNTL 0x0030 +#define REG_DP_PHY_TXn_INTERFACE_SELECT 0x0034 + +#define REG_DP_PHY_TXn_RES_CODE_LANE_TX 0x003C +#define REG_DP_PHY_TXn_RES_CODE_LANE_RX 0x0040 +#define REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX 0x0044 +#define REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX 0x0048 + +#define REG_DP_PHY_TXn_DEBUG_BUS_SEL 0x0058 +#define REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN 0x005C +#define REG_DP_PHY_TXn_HIGHZ_DRVR_EN 0x0060 +#define REG_DP_PHY_TXn_TX_POL_INV 0x0064 +#define REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 + +#define REG_DP_PHY_TXn_LANE_MODE_1 0x008C + +#define REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN 0x00C0 +#define REG_DP_PHY_TXn_TX_INTERFACE_MODE 0x00C4 + +#define REG_DP_PHY_TXn_VMODE_CTRL1 0x00F0 + +/* PLL register offset */ +#define QSERDES_COM_ATB_SEL1 0x0000 +#define QSERDES_COM_ATB_SEL2 0x0004 +#define QSERDES_COM_FREQ_UPDATE 0x0008 +#define QSERDES_COM_BG_TIMER 0x000C +#define QSERDES_COM_SSC_EN_CENTER 0x0010 +#define QSERDES_COM_SSC_ADJ_PER1 0x0014 +#define QSERDES_COM_SSC_ADJ_PER2 0x0018 +#define QSERDES_COM_SSC_PER1 0x001C +#define QSERDES_COM_SSC_PER2 0x0020 +#define QSERDES_COM_SSC_STEP_SIZE1 0x0024 +#define QSERDES_COM_SSC_STEP_SIZE2 0x0028 +#define QSERDES_COM_POST_DIV 0x002C +#define QSERDES_COM_POST_DIV_MUX 0x0030 + +#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0034 +#define QSERDES_COM_BIAS_EN 0x0001 +#define QSERDES_COM_BIAS_EN_MUX 0x0002 +#define QSERDES_COM_CLKBUF_R_EN 0x0004 +#define QSERDES_COM_CLKBUF_L_EN 0x0008 +#define QSERDES_COM_EN_SYSCLK_TX_SEL 0x0010 +#define QSERDES_COM_CLKBUF_RX_DRIVE_L 0x0020 +#define QSERDES_COM_CLKBUF_RX_DRIVE_R 0x0040 + +#define QSERDES_COM_CLK_ENABLE1 0x0038 +#define QSERDES_COM_SYS_CLK_CTRL 0x003C +#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0040 +#define QSERDES_COM_PLL_EN 0x0044 +#define QSERDES_COM_PLL_IVCO 0x0048 +#define QSERDES_COM_CMN_IETRIM 0x004C +#define QSERDES_COM_CMN_IPTRIM 0x0050 + +#define QSERDES_COM_CP_CTRL_MODE0 0x0060 +#define QSERDES_COM_CP_CTRL_MODE1 0x0064 +#define QSERDES_COM_PLL_RCTRL_MODE0 0x0068 +#define QSERDES_COM_PLL_RCTRL_MODE1 0x006C +#define QSERDES_COM_PLL_CCTRL_MODE0 0x0070 +#define QSERDES_COM_PLL_CCTRL_MODE1 0x0074 +#define QSERDES_COM_PLL_CNTRL 0x0078 +#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x007C +#define QSERDES_COM_SYSCLK_EN_SEL 0x0080 +#define QSERDES_COM_CML_SYSCLK_SEL 0x0084 +#define QSERDES_COM_RESETSM_CNTRL 0x0088 +#define QSERDES_COM_RESETSM_CNTRL2 0x008C +#define QSERDES_COM_LOCK_CMP_EN 0x0090 +#define QSERDES_COM_LOCK_CMP_CFG 0x0094 +#define QSERDES_COM_LOCK_CMP1_MODE0 0x0098 +#define QSERDES_COM_LOCK_CMP2_MODE0 0x009C +#define QSERDES_COM_LOCK_CMP3_MODE0 0x00A0 + +#define QSERDES_COM_DEC_START_MODE0 0x00B0 +#define QSERDES_COM_DEC_START_MODE1 0x00B4 +#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00B8 +#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00BC +#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00C0 +#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x00C4 +#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x00C8 +#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x00CC +#define QSERDES_COM_INTEGLOOP_INITVAL 0x00D0 +#define QSERDES_COM_INTEGLOOP_EN 0x00D4 +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x00D8 +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x00DC +#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x00E0 +#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x00E4 +#define QSERDES_COM_VCOCAL_DEADMAN_CTRL 0x00E8 +#define QSERDES_COM_VCO_TUNE_CTRL 0x00EC +#define QSERDES_COM_VCO_TUNE_MAP 0x00F0 + +#define QSERDES_COM_CMN_STATUS 0x0124 +#define QSERDES_COM_RESET_SM_STATUS 0x0128 + +#define QSERDES_COM_CLK_SEL 0x0138 +#define QSERDES_COM_HSCLK_SEL 0x013C + +#define QSERDES_COM_CORECLK_DIV_MODE0 0x0148 + +#define QSERDES_COM_SW_RESET 0x0150 +#define QSERDES_COM_CORE_CLK_EN 0x0154 +#define QSERDES_COM_C_READY_STATUS 0x0158 +#define QSERDES_COM_CMN_CONFIG 0x015C + +#define QSERDES_COM_SVS_MODE_CLK_SEL 0x0164 + +/* DP MMSS_CC registers */ +#define MMSS_DP_LINK_CMD_RCGR (0x0138) +#define MMSS_DP_LINK_CFG_RCGR (0x013C) +#define MMSS_DP_PIXEL_M (0x01B4) +#define MMSS_DP_PIXEL_N (0x01B8) + +/* DP HDCP 1.3 registers */ +#define DP_HDCP_CTRL (0x0A0) +#define DP_HDCP_STATUS (0x0A4) +#define DP_HDCP_SW_UPPER_AKSV (0x098) +#define DP_HDCP_SW_LOWER_AKSV (0x09C) +#define DP_HDCP_ENTROPY_CTRL0 (0x350) +#define DP_HDCP_ENTROPY_CTRL1 (0x35C) +#define DP_HDCP_SHA_STATUS (0x0C8) +#define DP_HDCP_RCVPORT_DATA2_0 (0x0B0) +#define DP_HDCP_RCVPORT_DATA3 (0x0A4) +#define DP_HDCP_RCVPORT_DATA4 (0x0A8) +#define DP_HDCP_RCVPORT_DATA5 (0x0C0) +#define DP_HDCP_RCVPORT_DATA6 (0x0C4) + +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL (0x024) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_DATA (0x028) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0 (0x004) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1 (0x008) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7 (0x00C) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8 (0x010) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9 (0x014) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10 (0x018) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) +#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) + +/* USB3 DP COM registers */ +#define REG_USB3_DP_COM_RESET_OVRD_CTRL (0x1C) +#define USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET (0x01) +#define USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX (0x02) +#define USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET (0x04) +#define USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX (0x08) + +#define REG_USB3_DP_COM_PHY_MODE_CTRL (0x00) +#define USB3_DP_COM_PHY_MODE_DP (0x03) + +#define REG_USB3_DP_COM_SW_RESET (0x04) +#define USB3_DP_COM_SW_RESET_SET (0x01) + +#define REG_USB3_DP_COM_TYPEC_CTRL (0x10) +#define USB3_DP_COM_TYPEC_CTRL_PORTSEL (0x01) +#define USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX (0x02) + +#define REG_USB3_DP_COM_SWI_CTRL (0x0c) + +#define REG_USB3_DP_COM_POWER_DOWN_CTRL (0x08) +#define USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN (0x01) + + + +#endif /* _DP_REG_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index abf5799d9a22b..49685571dc0ee 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1352,6 +1352,7 @@ static int __init msm_drm_register(void) msm_dsi_register(); msm_edp_register(); msm_hdmi_register(); + msm_dp_register(); adreno_register(); return platform_driver_register(&msm_platform_driver); } @@ -1360,6 +1361,7 @@ static void __exit msm_drm_unregister(void) { DBG("fini"); platform_driver_unregister(&msm_platform_driver); + msm_dp_unregister(); msm_hdmi_unregister(); adreno_unregister(); msm_edp_unregister(); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 2ca9c3c038451..ff165dafa6c6f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -160,6 +160,8 @@ struct msm_drm_private { /* DSI is shared by mdp4 and mdp5 */ struct msm_dsi *dsi[2]; + struct msm_dp *dp; + /* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu; struct msm_file_private *lastctx; @@ -383,6 +385,49 @@ static inline int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, } #endif +#ifdef CONFIG_DRM_MSM_DP +int __init msm_dp_register(void); +void __exit msm_dp_unregister(void); +int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, + struct drm_encoder *encoder); +int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder); +int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder); +void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + +#else +static inline int __init msm_dp_register(void) +{ + return -EINVAL; +} +static inline void __exit msm_dp_unregister(void) +{ +} +static inline int msm_dp_modeset_init(struct msm_dp *dp_display, + struct drm_device *dev, + struct drm_encoder *encoder) +{ + return -EINVAL; +} +static inline int msm_dp_display_enable(struct msm_dp *dp, + struct drm_encoder *encoder) +{ + return -EINVAL; +} +static inline int msm_dp_display_disable(struct msm_dp *dp, + struct drm_encoder *encoder) +{ + return -EINVAL; +} +static inline void msm_dp_display_mode_set(struct msm_dp *dp, + struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ +} +#endif + void __init msm_mdp_register(void); void __exit msm_mdp_unregister(void); void __init msm_dpu_register(void); @@ -403,8 +448,9 @@ void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); #else static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } __printf(3, 4) -static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, - const char *fmt, ...) {} +static inline void msm_rd_dump_submit(struct msm_rd_state *rd, + struct msm_gem_submit *submit, + const char *fmt, ...) {} static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {} #endif @@ -424,7 +470,8 @@ struct msm_gpu_submitqueue; 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, u32 id); -int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, +int msm_submitqueue_create(struct drm_device *drm, + struct msm_file_private *ctx, u32 prio, u32 flags, u32 *id); int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, struct drm_msm_submitqueue_query *args); -- GitLab From 14975cff5b1d076d067ccebf1046be7d2e4fcfbc Mon Sep 17 00:00:00 2001 From: Chandan Uddaraju <chandanu@codeaurora.org> Date: Thu, 27 Aug 2020 14:16:56 -0700 Subject: [PATCH 1119/1494] drm/msm/dp: add support for DP PLL driver Add the needed DP PLL specific files to support display port interface on msm targets. The DP driver calls the DP PLL driver registration. The DP driver sets the link and pixel clock sources. Changes in v2: -- Update copyright markings on all relevant files. -- Use DRM_DEBUG_DP for debug msgs. Changes in v4: -- Update the DP link clock provider names Changes in V5: -- Addressed comments from Stephen Boyd, Rob clark. Changes in V6: -- Remove PLL as separate driver and include PLL as DP module -- Remove redundant clock parsing from PLL module and make DP as clock provider -- Map USB3 DPCOM and PHY IO using hardcoded register address and move mapping form parser to PLL module -- Access DP PHY modules from same base address using offsets instead of deriving base address of individual module from device tree. -- Remove dp_pll_10nm_util.c and include its functionality in dp_pll_10nm.c -- Introduce new data structures private to PLL module Changes in v7: -- Remove DRM_MSM_DP_PLL config from Makefile and Kconfig -- Remove set_parent from determin_rate API -- Remove phy_pll_vco_div_clk from parent list -- Remove flag CLK_DIVIDER_ONE_BASED -- Remove redundant cell-index property parsing Changes in v8: -- Unregister hardware clocks during driver cleanup Changes in v9: -- Remove redundant Kconfig option DRM_MSM_DP_10NM_PLL Changes in v10: -- Limit 10nm PLL function scope Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> Signed-off-by: Vara Reddy <varar@codeaurora.org> Signed-off-by: Tanmay Shah <tanmay@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile | 4 +- drivers/gpu/drm/msm/dp/dp_catalog.c | 31 +- drivers/gpu/drm/msm/dp/dp_display.c | 18 +- drivers/gpu/drm/msm/dp/dp_display.h | 3 + drivers/gpu/drm/msm/dp/dp_parser.c | 2 + drivers/gpu/drm/msm/dp/dp_parser.h | 7 +- drivers/gpu/drm/msm/dp/dp_pll.c | 99 +++ drivers/gpu/drm/msm/dp/dp_pll.h | 61 ++ drivers/gpu/drm/msm/dp/dp_pll_10nm.c | 930 ++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_pll_private.h | 89 +++ drivers/gpu/drm/msm/dp/dp_power.c | 10 + drivers/gpu/drm/msm/dp/dp_power.h | 40 +- drivers/gpu/drm/msm/dp/dp_reg.h | 16 + 14 files changed, 1294 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_pll.c create mode 100644 drivers/gpu/drm/msm/dp/dp_pll.h create mode 100644 drivers/gpu/drm/msm/dp/dp_pll_10nm.c create mode 100644 drivers/gpu/drm/msm/dp/dp_pll_private.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index a5fa0f87d1280..8c399bc9f3d4c 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -61,6 +61,7 @@ config DRM_MSM_HDMI_HDCP config DRM_MSM_DP bool "Enable DisplayPort support in MSM DRM driver" depends on DRM_MSM + default y help Compile in support for DP driver in MSM DRM driver. DP external display support is enabled through this config option. It can diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index fd5a3d580f274..6db6423cca935 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -109,7 +109,9 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_link.o \ dp/dp_panel.o \ dp/dp_parser.o \ - dp/dp_power.o + dp/dp_power.o \ + dp/dp_pll.o \ + dp/dp_pll_10nm.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 0ffde1a748529..d27e17d7d18cd 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -5,6 +5,7 @@ #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ +#include <linux/rational.h> #include <linux/delay.h> #include <linux/iopoll.h> #include <linux/rational.h> @@ -131,51 +132,58 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog, static inline void dp_write_phy(struct dp_catalog_private *catalog, u32 offset, u32 data) { + offset += DP_PHY_REG_OFFSET; /* * To make sure phy reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->phy_io.base + offset); + writel(data, catalog->io->phy_reg.base + offset); } static inline u32 dp_read_phy(struct dp_catalog_private *catalog, u32 offset) { + offset += DP_PHY_REG_OFFSET; /* * To make sure phy reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(catalog->io->phy_io.base + offset); + return readl_relaxed(catalog->io->phy_reg.base + offset); } static inline void dp_write_pll(struct dp_catalog_private *catalog, u32 offset, u32 data) { - writel_relaxed(data, catalog->io->dp_pll_io.base + offset); + offset += DP_PHY_PLL_OFFSET; + writel_relaxed(data, catalog->io->phy_reg.base + offset); } static inline void dp_write_ln_tx0(struct dp_catalog_private *catalog, u32 offset, u32 data) { - writel_relaxed(data, catalog->io->ln_tx0_io.base + offset); + offset += DP_PHY_LN_TX0_OFFSET; + writel_relaxed(data, catalog->io->phy_reg.base + offset); } static inline void dp_write_ln_tx1(struct dp_catalog_private *catalog, u32 offset, u32 data) { - writel_relaxed(data, catalog->io->ln_tx1_io.base + offset); + offset += DP_PHY_LN_TX1_OFFSET; + writel_relaxed(data, catalog->io->phy_reg.base + offset); } static inline u32 dp_read_ln_tx0(struct dp_catalog_private *catalog, u32 offset) { - return readl_relaxed(catalog->io->ln_tx0_io.base + offset); + offset += DP_PHY_LN_TX0_OFFSET; + return readl_relaxed(catalog->io->phy_reg.base + offset); } static inline u32 dp_read_ln_tx1(struct dp_catalog_private *catalog, u32 offset) { - return readl_relaxed(catalog->io->ln_tx1_io.base + offset); + offset += DP_PHY_LN_TX1_OFFSET; + return readl_relaxed(catalog->io->phy_reg.base + offset); } static inline void dp_write_usb_cm(struct dp_catalog_private *catalog, @@ -398,13 +406,16 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) dump_regs(catalog->io->usb3_dp_com.base, catalog->io->usb3_dp_com.len); pr_info("LN TX0 regs\n"); - dump_regs(catalog->io->ln_tx0_io.base, catalog->io->ln_tx0_io.len); + dump_regs(catalog->io->phy_reg.base + DP_PHY_LN_TX0_OFFSET, + DP_PHY_LN_TX0_SIZE); pr_info("LN TX1 regs\n"); - dump_regs(catalog->io->ln_tx1_io.base, catalog->io->ln_tx1_io.len); + dump_regs(catalog->io->phy_reg.base + DP_PHY_LN_TX1_OFFSET, + DP_PHY_LN_TX1_SIZE); pr_info("DP PHY regs\n"); - dump_regs(catalog->io->phy_io.base, catalog->io->phy_io.len); + dump_regs(catalog->io->phy_reg.base + DP_PHY_REG_OFFSET, + DP_PHY_REG_SIZE); } void dp_catalog_aux_setup(struct dp_catalog *dp_catalog) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ff381807e350a..c8851f4bbf727 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -22,6 +22,7 @@ #include "dp_ctrl.h" #include "dp_display.h" #include "dp_drm.h" +#include "dp_pll.h" static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 @@ -42,6 +43,7 @@ struct dp_display_private { struct dp_usbpd *usbpd; struct dp_parser *parser; + struct msm_dp_pll *pll; struct dp_power *power; struct dp_catalog *catalog; struct drm_dp_aux *aux; @@ -232,7 +234,6 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) edid = dp->panel->edid; dp->audio_supported = drm_detect_monitor_audio(edid); - dp_panel_handle_sink_request(dp->panel); dp->dp_display.max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; @@ -410,6 +411,7 @@ static void dp_display_deinit_sub_modules(struct dp_display_private *dp) dp_ctrl_put(dp->ctrl); dp_panel_put(dp->panel); dp_aux_put(dp->aux); + dp_pll_put(dp->pll); } static int dp_init_sub_modules(struct dp_display_private *dp) @@ -420,6 +422,9 @@ static int dp_init_sub_modules(struct dp_display_private *dp) struct dp_panel_in panel_in = { .dev = dev, }; + struct dp_pll_in pll_in = { + .pdev = dp->pdev, + }; /* Callback APIs used for cable status change event */ cb->configure = dp_display_usbpd_configure_cb; @@ -450,6 +455,17 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } + pll_in.parser = dp->parser; + dp->pll = dp_pll_get(&pll_in); + if (IS_ERR_OR_NULL(dp->pll)) { + rc = -EINVAL; + DRM_ERROR("failed to initialize pll, rc = %d\n", rc); + dp->pll = NULL; + goto error; + } + + dp->parser->pll = dp->pll; + dp->power = dp_power_get(dp->parser); if (IS_ERR(dp->power)) { rc = PTR_ERR(dp->power); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index dad8610685a6d..4c53ed55d1cca 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -25,4 +25,7 @@ int dp_display_request_irq(struct msm_dp *dp_display); bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); +void __init msm_dp_pll_driver_register(void); +void __exit msm_dp_pll_driver_unregister(void); + #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 19c14c1ddbb4d..1e480d01ddbb3 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -6,6 +6,7 @@ #include <linux/of_gpio.h> #include "dp_parser.h" +#include "dp_reg.h" static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { .num = 2, @@ -52,6 +53,7 @@ static void dp_parser_unmap_io_resources(struct dp_parser *parser) struct dp_io *io = &parser->io; msm_dss_iounmap(&io->dp_controller); + msm_dss_iounmap(&io->phy_reg); msm_dss_iounmap(&io->usb3_dp_com); } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 2085b15aa4cf1..aa0380b6a2806 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -10,6 +10,7 @@ #include "dpu_io_util.h" #include "msm_drv.h" +#include "dp_pll.h" #define DP_LABEL "MDSS DP DISPLAY" #define DP_MAX_PIXEL_CLK_KHZ 675000 @@ -66,10 +67,7 @@ struct dp_display_data { */ struct dp_io { struct dss_io_data dp_controller; - struct dss_io_data phy_io; - struct dss_io_data ln_tx0_io; - struct dss_io_data ln_tx1_io; - struct dss_io_data dp_pll_io; + struct dss_io_data phy_reg; struct dss_io_data usb3_dp_com; }; @@ -117,6 +115,7 @@ struct dp_parser { struct dp_pinctrl pinctrl; struct dp_io io; struct dp_display_data disp_data; + struct msm_dp_pll *pll; const struct dp_regulator_cfg *regulator_cfg; u32 max_dp_lanes; diff --git a/drivers/gpu/drm/msm/dp/dp_pll.c b/drivers/gpu/drm/msm/dp/dp_pll.c new file mode 100644 index 0000000000000..53f82cd970277 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_pll.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/device.h> + +#include "dp_parser.h" +#include "dp_pll.h" +#include "dp_pll_private.h" + +static int dp_pll_get_phy_io(struct dp_parser *parser) +{ + struct dp_io *io = &parser->io; + + io->usb3_dp_com.base = ioremap(REG_USB3_DP_COM_REGION_BASE, + REG_USB3_DP_COM_REGION_SIZE); + if (!io->usb3_dp_com.base) { + DRM_ERROR("unable to map USB3 DP COM IO\n"); + return -EIO; + } + + /* ToDo(user): DP PLL and DP PHY will not be part of + * DP driver eventually so for now Hardcode Base and offsets + * of PHY registers so we can remove them from dts and bindings + */ + io->phy_reg.base = ioremap(REG_DP_PHY_REGION_BASE, + REG_DP_PHY_REGION_SIZE); + if (!io->phy_reg.base) { + DRM_ERROR("DP PHY io region mapping failed\n"); + return -EIO; + } + io->phy_reg.len = REG_DP_PHY_REGION_SIZE; + + return 0; +} + +static int msm_dp_pll_init(struct msm_dp_pll *pll, + enum msm_dp_pll_type type, int id) +{ + struct device *dev = &pll->pdev->dev; + int ret = 0; + + switch (type) { + case MSM_DP_PLL_10NM: + ret = msm_dp_pll_10nm_init(pll, id); + break; + default: + DRM_DEV_ERROR(dev, "%s: Wrong PLL type %d\n", __func__, type); + return -ENXIO; + } + + if (ret) { + DRM_DEV_ERROR(dev, "%s: failed to init DP PLL\n", __func__); + return ret; + } + + pll->type = type; + + DRM_DEBUG_DP("DP:%d PLL registered", id); + + return ret; +} + +struct msm_dp_pll *dp_pll_get(struct dp_pll_in *pll_in) +{ + struct msm_dp_pll *dp_pll; + struct dp_parser *parser = pll_in->parser; + struct dp_io_pll *pll_io; + int ret; + + dp_pll = devm_kzalloc(&pll_in->pdev->dev, sizeof(*dp_pll), GFP_KERNEL); + if (!dp_pll) + return ERR_PTR(-ENOMEM); + + pll_io = &dp_pll->pll_io; + dp_pll->pdev = pll_in->pdev; + + dp_pll_get_phy_io(parser); + + pll_io->pll_base = parser->io.phy_reg.base + DP_PHY_PLL_OFFSET; + pll_io->phy_base = parser->io.phy_reg.base + DP_PHY_REG_OFFSET; + pll_io->ln_tx0_base = parser->io.phy_reg.base + DP_PHY_LN_TX0_OFFSET; + pll_io->ln_tx1_base = parser->io.phy_reg.base + DP_PHY_LN_TX1_OFFSET; + + ret = msm_dp_pll_init(dp_pll, MSM_DP_PLL_10NM, 0); + if (ret) { + kfree(dp_pll); + return ERR_PTR(ret); + } + + return dp_pll; +} + +void dp_pll_put(struct msm_dp_pll *dp_pll) +{ + if (dp_pll->type == MSM_DP_PLL_10NM) + msm_dp_pll_10nm_deinit(dp_pll); +} diff --git a/drivers/gpu/drm/msm/dp/dp_pll.h b/drivers/gpu/drm/msm/dp/dp_pll.h new file mode 100644 index 0000000000000..5a10c8f3cfeae --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_pll.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DP_PLL_H +#define __DP_PLL_H + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "dpu_io_util.h" +#include "msm_drv.h" +#include "dp_parser.h" + +#define PLL_REG_W(base, offset, data) \ + writel((data), (base) + (offset)) +#define PLL_REG_R(base, offset) readl((base) + (offset)) + +enum msm_dp_pll_type { + MSM_DP_PLL_10NM, + MSM_DP_PLL_MAX +}; + +struct dp_pll_in { + struct platform_device *pdev; + struct dp_parser *parser; +}; + +struct dp_io_pll { + void __iomem *pll_base; + void __iomem *phy_base; + void __iomem *ln_tx0_base; + void __iomem *ln_tx1_base; +}; + +struct msm_dp_pll { + enum msm_dp_pll_type type; + bool pll_on; + + struct dp_io_pll pll_io; + + /* clock-provider: */ + struct clk_hw_onecell_data *hw_data; + + struct platform_device *pdev; + void *priv; + + /* Pll specific resources like GPIO, power supply, clocks, etc*/ + struct dss_module_power mp; + int (*get_provider)(struct msm_dp_pll *pll, + struct clk **link_clk_provider, + struct clk **pixel_clk_provider); +}; + +struct msm_dp_pll *dp_pll_get(struct dp_pll_in *pll_in); + +void dp_pll_put(struct msm_dp_pll *dp_pll); + +#endif /* __DP_PLL_H */ diff --git a/drivers/gpu/drm/msm/dp/dp_pll_10nm.c b/drivers/gpu/drm/msm/dp/dp_pll_10nm.c new file mode 100644 index 0000000000000..a2bf2fc24d6af --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_pll_10nm.c @@ -0,0 +1,930 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + +/* + * Display Port PLL driver block diagram for branch clocks + * + * +------------------------------+ + * | DP_VCO_CLK | + * | | + * | +-------------------+ | + * | | (DP PLL/VCO) | | + * | +---------+---------+ | + * | v | + * | +----------+-----------+ | + * | | hsclk_divsel_clk_src | | + * | +----------+-----------+ | + * +------------------------------+ + * | + * +---------<---------v------------>----------+ + * | | + * +--------v---------+ | + * | dp_phy_pll | | + * | link_clk | | + * +--------+---------+ | + * | | + * | | + * v v + * Input to DISPCC block | + * for link clk, crypto clk | + * and interface clock | + * | + * | + * +--------<------------+-----------------+---<---+ + * | | | + * +----v---------+ +--------v-----+ +--------v------+ + * | vco_divided | | vco_divided | | vco_divided | + * | _clk_src | | _clk_src | | _clk_src | + * | | | | | | + * |divsel_six | | divsel_two | | divsel_four | + * +-------+------+ +-----+--------+ +--------+------+ + * | | | + * v---->----------v-------------<------v + * | + * +----------+---------+ + * | dp_phy_pll_vco | + * | div_clk | + * +---------+----------+ + * | + * v + * Input to DISPCC block + * for DP pixel clock + * + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/regmap.h> +#include <linux/iopoll.h> + +#include "dp_hpd.h" +#include "dp_pll.h" +#include "dp_pll_private.h" + +#define NUM_PROVIDED_CLKS 2 + +#define DP_LINK_CLK_SRC 0 +#define DP_PIXEL_CLK_SRC 1 + + +static int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate); + +static unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, + unsigned long parent_rate); + +static long dp_vco_round_rate_10nm(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate); + +static int dp_vco_prepare_10nm(struct clk_hw *hw); +static void dp_vco_unprepare_10nm(struct clk_hw *hw); + +static struct dp_pll_db *dp_pdb; + +static const struct clk_ops dp_10nm_vco_clk_ops = { + .recalc_rate = dp_vco_recalc_rate_10nm, + .set_rate = dp_vco_set_rate_10nm, + .round_rate = dp_vco_round_rate_10nm, + .prepare = dp_vco_prepare_10nm, + .unprepare = dp_vco_unprepare_10nm, +}; + +struct dp_pll_10nm_pclksel { + struct clk_hw hw; + + /* divider params */ + u8 shift; + u8 width; + u8 flags; /* same flags as used by clk_divider struct */ + + struct dp_pll_db *pll; +}; + +#define to_pll_10nm_pclksel(_hw) \ + container_of(_hw, struct dp_pll_10nm_pclksel, hw) + +static const struct clk_parent_data disp_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "dp_phy_pll_link_clk", .name = "dp_phy_pll_link_clk" }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static struct dp_pll_vco_clk dp_vco_clk = { + .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000, + .max_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000, +}; + +static int dp_pll_mux_set_parent_10nm(struct clk_hw *hw, u8 val) +{ + struct dp_pll_10nm_pclksel *pclksel = to_pll_10nm_pclksel(hw); + struct dp_pll_db *dp_res = pclksel->pll; + struct dp_io_pll *pll_io = &dp_res->base->pll_io; + u32 auxclk_div; + + auxclk_div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_VCO_DIV); + auxclk_div &= ~0x03; + + if (val == 0) + auxclk_div |= 1; + else if (val == 1) + auxclk_div |= 2; + else if (val == 2) + auxclk_div |= 0; + + PLL_REG_W(pll_io->phy_base, + REG_DP_PHY_VCO_DIV, auxclk_div); + DRM_DEBUG_DP("%s: mux=%d auxclk_div=%x\n", __func__, val, auxclk_div); + + return 0; +} + +static u8 dp_pll_mux_get_parent_10nm(struct clk_hw *hw) +{ + u32 auxclk_div = 0; + struct dp_pll_10nm_pclksel *pclksel = to_pll_10nm_pclksel(hw); + struct dp_pll_db *dp_res = pclksel->pll; + struct dp_io_pll *pll_io = &dp_res->base->pll_io; + u8 val = 0; + + auxclk_div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_VCO_DIV); + auxclk_div &= 0x03; + + if (auxclk_div == 1) /* Default divider */ + val = 0; + else if (auxclk_div == 2) + val = 1; + else if (auxclk_div == 0) + val = 2; + + DRM_DEBUG_DP("%s: auxclk_div=%d, val=%d\n", __func__, auxclk_div, val); + + return val; +} + +static int dp_pll_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long rate = 0; + + rate = clk_get_rate(hw->clk); + + if (rate <= 0) { + DRM_ERROR("Rate is not set properly\n"); + return -EINVAL; + } + + req->rate = rate; + + DRM_DEBUG_DP("%s: rate=%ld\n", __func__, req->rate); + return 0; +} + +static unsigned long dp_pll_mux_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_hw *div_clk_hw = NULL, *vco_clk_hw = NULL; + struct dp_pll_vco_clk *vco; + + div_clk_hw = clk_hw_get_parent(hw); + if (!div_clk_hw) + return 0; + + vco_clk_hw = clk_hw_get_parent(div_clk_hw); + if (!vco_clk_hw) + return 0; + + vco = to_dp_vco_hw(vco_clk_hw); + if (!vco) + return 0; + + if (vco->rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) + return (vco->rate / 6); + else if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) + return (vco->rate / 4); + else + return (vco->rate / 2); +} + +static int dp_pll_10nm_get_provider(struct msm_dp_pll *pll, + struct clk **link_clk_provider, + struct clk **pixel_clk_provider) +{ + struct clk_hw_onecell_data *hw_data = pll->hw_data; + + if (link_clk_provider) + *link_clk_provider = hw_data->hws[DP_LINK_CLK_SRC]->clk; + if (pixel_clk_provider) + *pixel_clk_provider = hw_data->hws[DP_PIXEL_CLK_SRC]->clk; + + return 0; +} + +static const struct clk_ops dp_10nm_pclksel_clk_ops = { + .get_parent = dp_pll_mux_get_parent_10nm, + .set_parent = dp_pll_mux_set_parent_10nm, + .recalc_rate = dp_pll_mux_recalc_rate, + .determine_rate = dp_pll_clk_mux_determine_rate, +}; + +static struct clk_hw *dp_pll_10nm_pixel_clk_sel(struct dp_pll_db *pll_10nm) +{ + struct device *dev = &pll_10nm->pdev->dev; + struct dp_pll_10nm_pclksel *pll_pclksel; + struct clk_init_data pclksel_init = { + .parent_data = disp_cc_parent_data_0, + .num_parents = 3, + .name = "dp_phy_pll_vco_div_clk", + .ops = &dp_10nm_pclksel_clk_ops, + }; + int ret; + + pll_pclksel = devm_kzalloc(dev, sizeof(*pll_pclksel), GFP_KERNEL); + if (!pll_pclksel) + return ERR_PTR(-ENOMEM); + + pll_pclksel->pll = pll_10nm; + pll_pclksel->shift = 0; + pll_pclksel->width = 4; + pll_pclksel->hw.init = &pclksel_init; + + ret = clk_hw_register(dev, &pll_pclksel->hw); + if (ret) + return ERR_PTR(ret); + + return &pll_pclksel->hw; +} + +static void dp_pll_10nm_unregister(struct dp_pll_db *pll_10nm) +{ + int i = 0; + struct clk_hw **hws; + + hws = pll_10nm->hws; + + for (i = 0; i < pll_10nm->num_hws; i++) { + if (pll_10nm->fixed_factor_clk[i] == true) + clk_hw_unregister_fixed_factor(hws[i]); + else + clk_hw_unregister(hws[i]); + } +} + +static int dp_pll_10nm_register(struct dp_pll_db *pll_10nm) +{ + struct clk_hw_onecell_data *hw_data; + int ret = 0; + struct clk_hw *hw; + + struct msm_dp_pll *pll = pll_10nm->base; + struct device *dev = &pll_10nm->pdev->dev; + struct clk_hw **hws = pll_10nm->hws; + int num = 0; + + struct clk_init_data vco_init = { + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .name = "dp_vco_clk", + .ops = &dp_10nm_vco_clk_ops, + }; + + if (!dev) { + DRM_ERROR("DP dev node not available\n"); + return 0; + } + + DRM_DEBUG_DP("DP->id = %d", pll_10nm->id); + + hw_data = devm_kzalloc(dev, sizeof(*hw_data) + + NUM_PROVIDED_CLKS * sizeof(struct clk_hw *), + GFP_KERNEL); + if (!hw_data) + return -ENOMEM; + + dp_vco_clk.hw.init = &vco_init; + ret = clk_hw_register(dev, &dp_vco_clk.hw); + if (ret) + return ret; + hws[num++] = &dp_vco_clk.hw; + + hw = clk_hw_register_fixed_factor(dev, "dp_phy_pll_link_clk", + "dp_vco_clk", CLK_SET_RATE_PARENT, 1, 10); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + pll_10nm->fixed_factor_clk[num] = true; + hws[num++] = hw; + hw_data->hws[DP_LINK_CLK_SRC] = hw; + + hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_two_clk_src", + "dp_vco_clk", 0, 1, 2); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + pll_10nm->fixed_factor_clk[num] = true; + hws[num++] = hw; + + hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_four_clk_src", + "dp_vco_clk", 0, 1, 4); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + pll_10nm->fixed_factor_clk[num] = true; + hws[num++] = hw; + + hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_six_clk_src", + "dp_vco_clk", 0, 1, 6); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + pll_10nm->fixed_factor_clk[num] = true; + hws[num++] = hw; + + hw = dp_pll_10nm_pixel_clk_sel(pll_10nm); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + hws[num++] = hw; + hw_data->hws[DP_PIXEL_CLK_SRC] = hw; + + pll_10nm->num_hws = num; + + hw_data->num = NUM_PROVIDED_CLKS; + pll->hw_data = hw_data; + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + pll->hw_data); + if (ret) { + DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", + ret); + return ret; + } + + return ret; +} + +void msm_dp_pll_10nm_deinit(struct msm_dp_pll *pll) +{ + dp_pll_10nm_unregister(pll->priv); +} + +int msm_dp_pll_10nm_init(struct msm_dp_pll *pll, int id) +{ + struct dp_pll_db *dp_10nm_pll; + struct platform_device *pdev = pll->pdev; + int ret; + + dp_10nm_pll = devm_kzalloc(&pdev->dev, + sizeof(*dp_10nm_pll), GFP_KERNEL); + if (!dp_10nm_pll) + return -ENOMEM; + + DRM_DEBUG_DP("DP PLL%d", id); + + dp_10nm_pll->base = pll; + dp_10nm_pll->pdev = pll->pdev; + dp_10nm_pll->id = id; + dp_pdb = dp_10nm_pll; + pll->priv = (void *)dp_10nm_pll; + dp_vco_clk.priv = pll; + dp_10nm_pll->index = 0; + + ret = dp_pll_10nm_register(dp_10nm_pll); + if (ret) { + DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret); + return ret; + } + + pll->get_provider = dp_pll_10nm_get_provider; + + return ret; +} + +static int dp_vco_pll_init_db_10nm(struct msm_dp_pll *pll, + unsigned long rate) +{ + u32 spare_value = 0; + struct dp_io_pll *pll_io; + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + pll_io = &pll->pll_io; + spare_value = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_SPARE0); + dp_res->lane_cnt = spare_value & 0x0F; + dp_res->orientation = (spare_value & 0xF0) >> 4; + + DRM_DEBUG_DP("%s: spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", + __func__, spare_value, dp_res->lane_cnt, + dp_res->orientation); + + switch (rate) { + case DP_VCO_HSCLK_RATE_1620MHZDIV1000: + DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, + DP_VCO_RATE_9720MHZDIV1000); + dp_res->hsclk_sel = 0x0c; + dp_res->dec_start_mode0 = 0x69; + dp_res->div_frac_start1_mode0 = 0x00; + dp_res->div_frac_start2_mode0 = 0x80; + dp_res->div_frac_start3_mode0 = 0x07; + dp_res->integloop_gain0_mode0 = 0x3f; + dp_res->integloop_gain1_mode0 = 0x00; + dp_res->vco_tune_map = 0x00; + dp_res->lock_cmp1_mode0 = 0x6f; + dp_res->lock_cmp2_mode0 = 0x08; + dp_res->lock_cmp3_mode0 = 0x00; + dp_res->phy_vco_div = 0x1; + dp_res->lock_cmp_en = 0x00; + break; + case DP_VCO_HSCLK_RATE_2700MHZDIV1000: + DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, + DP_VCO_RATE_10800MHZDIV1000); + dp_res->hsclk_sel = 0x04; + dp_res->dec_start_mode0 = 0x69; + dp_res->div_frac_start1_mode0 = 0x00; + dp_res->div_frac_start2_mode0 = 0x80; + dp_res->div_frac_start3_mode0 = 0x07; + dp_res->integloop_gain0_mode0 = 0x3f; + dp_res->integloop_gain1_mode0 = 0x00; + dp_res->vco_tune_map = 0x00; + dp_res->lock_cmp1_mode0 = 0x0f; + dp_res->lock_cmp2_mode0 = 0x0e; + dp_res->lock_cmp3_mode0 = 0x00; + dp_res->phy_vco_div = 0x1; + dp_res->lock_cmp_en = 0x00; + break; + case DP_VCO_HSCLK_RATE_5400MHZDIV1000: + DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, + DP_VCO_RATE_10800MHZDIV1000); + dp_res->hsclk_sel = 0x00; + dp_res->dec_start_mode0 = 0x8c; + dp_res->div_frac_start1_mode0 = 0x00; + dp_res->div_frac_start2_mode0 = 0x00; + dp_res->div_frac_start3_mode0 = 0x0a; + dp_res->integloop_gain0_mode0 = 0x3f; + dp_res->integloop_gain1_mode0 = 0x00; + dp_res->vco_tune_map = 0x00; + dp_res->lock_cmp1_mode0 = 0x1f; + dp_res->lock_cmp2_mode0 = 0x1c; + dp_res->lock_cmp3_mode0 = 0x00; + dp_res->phy_vco_div = 0x2; + dp_res->lock_cmp_en = 0x00; + break; + case DP_VCO_HSCLK_RATE_8100MHZDIV1000: + DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, + DP_VCO_RATE_8100MHZDIV1000); + dp_res->hsclk_sel = 0x03; + dp_res->dec_start_mode0 = 0x69; + dp_res->div_frac_start1_mode0 = 0x00; + dp_res->div_frac_start2_mode0 = 0x80; + dp_res->div_frac_start3_mode0 = 0x07; + dp_res->integloop_gain0_mode0 = 0x3f; + dp_res->integloop_gain1_mode0 = 0x00; + dp_res->vco_tune_map = 0x00; + dp_res->lock_cmp1_mode0 = 0x2f; + dp_res->lock_cmp2_mode0 = 0x2a; + dp_res->lock_cmp3_mode0 = 0x00; + dp_res->phy_vco_div = 0x0; + dp_res->lock_cmp_en = 0x08; + break; + default: + return -EINVAL; + } + return 0; +} + +static int dp_config_vco_rate_10nm(struct dp_pll_vco_clk *vco, + unsigned long rate) +{ + u32 res = 0; + struct msm_dp_pll *pll = vco->priv; + struct dp_io_pll *pll_io = &pll->pll_io; + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + res = dp_vco_pll_init_db_10nm(pll, rate); + if (res) { + DRM_ERROR("VCO Init DB failed\n"); + return res; + } + + if (dp_res->lane_cnt != 4) { + if (dp_res->orientation == ORIENTATION_CC2) + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x6d); + else + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x75); + } else { + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x7d); + } + + PLL_REG_W(pll_io->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CLK_SEL, 0x30); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); + + /* Different for each clock rates */ + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_HSCLK_SEL, dp_res->hsclk_sel); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_DEC_START_MODE0, dp_res->dec_start_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_DIV_FRAC_START1_MODE0, + dp_res->div_frac_start1_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_DIV_FRAC_START2_MODE0, + dp_res->div_frac_start2_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_DIV_FRAC_START3_MODE0, + dp_res->div_frac_start3_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_INTEGLOOP_GAIN0_MODE0, + dp_res->integloop_gain0_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_INTEGLOOP_GAIN1_MODE0, + dp_res->integloop_gain1_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_VCO_TUNE_MAP, dp_res->vco_tune_map); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_LOCK_CMP1_MODE0, dp_res->lock_cmp1_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_LOCK_CMP2_MODE0, dp_res->lock_cmp2_mode0); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_LOCK_CMP3_MODE0, dp_res->lock_cmp3_mode0); + + PLL_REG_W(pll_io->pll_base, QSERDES_COM_BG_TIMER, 0x0a); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CORECLK_DIV_MODE0, 0x0a); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CORE_CLK_EN, 0x1f); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_IVCO, 0x07); + PLL_REG_W(pll_io->pll_base, + QSERDES_COM_LOCK_CMP_EN, dp_res->lock_cmp_en); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); + PLL_REG_W(pll_io->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x06); + + if (dp_res->orientation == ORIENTATION_CC2) + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_MODE, 0x4c); + else + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_MODE, 0x5c); + + /* TX Lane configuration */ + PLL_REG_W(pll_io->phy_base, + REG_DP_PHY_TX0_TX1_LANE_CTL, 0x05); + PLL_REG_W(pll_io->phy_base, + REG_DP_PHY_TX2_TX3_LANE_CTL, 0x05); + + /* TX-0 register configuration */ + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, 0x1a); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_VMODE_CTRL1, 0x40); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN, 0x30); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_INTERFACE_SELECT, 0x3d); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_CLKBUF_ENABLE, 0x0f); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_RESET_TSYNC_EN, 0x03); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN, 0x03); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_TX_INTERFACE_MODE, 0x00); + PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_BAND, 0x4); + + /* TX-1 register configuration */ + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, 0x1a); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_VMODE_CTRL1, 0x40); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN, 0x30); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_INTERFACE_SELECT, 0x3d); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_CLKBUF_ENABLE, 0x0f); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_RESET_TSYNC_EN, 0x03); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN, 0x03); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TX_INTERFACE_MODE, 0x00); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TX_BAND, 0x4); + + /* dependent on the vco frequency */ + PLL_REG_W(pll_io->phy_base, + REG_DP_PHY_VCO_DIV, dp_res->phy_vco_div); + + return res; +} + +static bool dp_10nm_pll_lock_status(struct dp_pll_db *dp_res) +{ + u32 status; + bool pll_locked; + struct dp_io_pll *pll_io = &dp_res->base->pll_io; + + /* poll for PLL lock status */ + if (readl_poll_timeout_atomic((pll_io->pll_base + + QSERDES_COM_C_READY_STATUS), + status, + ((status & BIT(0)) > 0), + DP_PHY_PLL_POLL_SLEEP_US, + DP_PHY_PLL_POLL_TIMEOUT_US)) { + DRM_ERROR("%s: C_READY status is not high. Status=%x\n", + __func__, status); + pll_locked = false; + } else { + pll_locked = true; + } + + return pll_locked; +} + +static bool dp_10nm_phy_rdy_status(struct dp_pll_db *dp_res) +{ + u32 status; + bool phy_ready = true; + struct dp_io_pll *pll_io = &dp_res->base->pll_io; + + /* poll for PHY ready status */ + if (readl_poll_timeout_atomic((pll_io->phy_base + + REG_DP_PHY_STATUS), + status, + ((status & (BIT(1))) > 0), + DP_PHY_PLL_POLL_SLEEP_US, + DP_PHY_PLL_POLL_TIMEOUT_US)) { + DRM_ERROR("%s: Phy_ready is not high. Status=%x\n", + __func__, status); + phy_ready = false; + } + + return phy_ready; +} + +static int dp_pll_enable_10nm(struct clk_hw *hw) +{ + int rc = 0; + u32 bias_en, drvr_en; + struct dp_io_pll *pll_io; + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + struct msm_dp_pll *pll = to_msm_dp_pll(vco); + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + pll_io = &pll->pll_io; + + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_AUX_CFG2, 0x04); + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x01); + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x05); + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x01); + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x09); + + PLL_REG_W(pll_io->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); + + if (!dp_10nm_pll_lock_status(dp_res)) { + rc = -EINVAL; + goto lock_err; + } + + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x19); + /* poll for PHY ready status */ + if (!dp_10nm_phy_rdy_status(dp_res)) { + rc = -EINVAL; + goto lock_err; + } + + DRM_DEBUG_DP("%s: PLL is locked\n", __func__); + + if (dp_res->lane_cnt == 1) { + bias_en = 0x3e; + drvr_en = 0x13; + } else { + bias_en = 0x3f; + drvr_en = 0x10; + } + + if (dp_res->lane_cnt != 4) { + if (dp_res->orientation == ORIENTATION_CC1) { + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); + } else { + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); + } + } else { + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); + } + + PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_POL_INV, 0x0a); + PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_POL_INV, 0x0a); + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x18); + udelay(2000); + + PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x19); + + /* poll for PHY ready status */ + if (!dp_10nm_phy_rdy_status(dp_res)) { + rc = -EINVAL; + goto lock_err; + } + + PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_DRV_LVL, 0x38); + PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_DRV_LVL, 0x38); + PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, 0x20); + PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, 0x20); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX, 0x06); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX, 0x06); + PLL_REG_W(pll_io->ln_tx0_base, + REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX, 0x07); + PLL_REG_W(pll_io->ln_tx1_base, + REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX, 0x07); + +lock_err: + return rc; +} + +static int dp_pll_disable_10nm(struct clk_hw *hw) +{ + int rc = 0; + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + struct msm_dp_pll *pll = to_msm_dp_pll(vco); + + /* Assert DP PHY power down */ + PLL_REG_W(pll->pll_io.phy_base, REG_DP_PHY_PD_CTL, 0x2); + + return rc; +} + + +static int dp_vco_prepare_10nm(struct clk_hw *hw) +{ + int rc = 0; + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + struct msm_dp_pll *pll = (struct msm_dp_pll *)vco->priv; + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + DRM_DEBUG_DP("%s: rate = %ld\n", __func__, vco->rate); + if ((dp_res->vco_cached_rate != 0) + && (dp_res->vco_cached_rate == vco->rate)) { + rc = dp_vco_set_rate_10nm(hw, + dp_res->vco_cached_rate, dp_res->vco_cached_rate); + if (rc) { + DRM_ERROR("index=%d vco_set_rate failed. rc=%d\n", + rc, dp_res->index); + goto error; + } + } + + rc = dp_pll_enable_10nm(hw); + if (rc) { + DRM_ERROR("ndx=%d failed to enable dp pll\n", + dp_res->index); + goto error; + } + + pll->pll_on = true; +error: + return rc; +} + +static void dp_vco_unprepare_10nm(struct clk_hw *hw) +{ + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + struct msm_dp_pll *pll = to_msm_dp_pll(vco); + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + if (!dp_res) { + DRM_ERROR("Invalid input parameter\n"); + return; + } + + if (!pll->pll_on) { + DRM_ERROR("pll resource can't be enabled\n"); + return; + } + dp_res->vco_cached_rate = vco->rate; + dp_pll_disable_10nm(hw); + + pll->pll_on = false; +} + +static int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + int rc; + + DRM_DEBUG_DP("DP lane CLK rate=%ld\n", rate); + + rc = dp_config_vco_rate_10nm(vco, rate); + if (rc) + DRM_ERROR("%s: Failed to set clk rate\n", __func__); + + vco->rate = rate; + + return 0; +} + +static unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, + unsigned long parent_rate) +{ + u32 div, hsclk_div, link_clk_div = 0; + u64 vco_rate; + struct dp_io_pll *pll_io; + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + struct msm_dp_pll *pll = to_msm_dp_pll(vco); + struct dp_pll_db *dp_res = to_dp_pll_db(pll); + + pll_io = &pll->pll_io; + + div = PLL_REG_R(pll_io->pll_base, QSERDES_COM_HSCLK_SEL); + div &= 0x0f; + + if (div == 12) + hsclk_div = 6; /* Default */ + else if (div == 4) + hsclk_div = 4; + else if (div == 0) + hsclk_div = 2; + else if (div == 3) + hsclk_div = 1; + else { + DRM_DEBUG_DP("unknown divider. forcing to default\n"); + hsclk_div = 5; + } + + div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_AUX_CFG2); + div >>= 2; + + if ((div & 0x3) == 0) + link_clk_div = 5; + else if ((div & 0x3) == 1) + link_clk_div = 10; + else if ((div & 0x3) == 2) + link_clk_div = 20; + else + DRM_ERROR("%s: unsupported div. Phy_mode: %d\n", __func__, div); + + if (link_clk_div == 20) { + vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; + } else { + if (hsclk_div == 6) + vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000; + else if (hsclk_div == 4) + vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; + else if (hsclk_div == 2) + vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; + else + vco_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000; + } + + DRM_DEBUG_DP("returning vco rate = %lu\n", (unsigned long)vco_rate); + + dp_res->vco_cached_rate = vco->rate = vco_rate; + return (unsigned long)vco_rate; +} + +long dp_vco_round_rate_10nm(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + unsigned long rrate = rate; + struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); + + if (rate <= vco->min_rate) + rrate = vco->min_rate; + else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000) + rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; + else if (rate <= DP_VCO_HSCLK_RATE_5400MHZDIV1000) + rrate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; + else + rrate = vco->max_rate; + + DRM_DEBUG_DP("%s: rrate=%ld\n", __func__, rrate); + + *parent_rate = rrate; + return rrate; +} diff --git a/drivers/gpu/drm/msm/dp/dp_pll_private.h b/drivers/gpu/drm/msm/dp/dp_pll_private.h new file mode 100644 index 0000000000000..434abdc396f5e --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_pll_private.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __DP_PLL_10NM_H +#define __DP_PLL_10NM_H + +#include "dp_pll.h" +#include "dp_reg.h" + +#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL +#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL +#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL +#define DP_VCO_HSCLK_RATE_8100MHZDIV1000 8100000UL + +#define NUM_DP_CLOCKS_MAX 6 + +#define DP_PHY_PLL_POLL_SLEEP_US 500 +#define DP_PHY_PLL_POLL_TIMEOUT_US 10000 + +#define DP_VCO_RATE_8100MHZDIV1000 8100000UL +#define DP_VCO_RATE_9720MHZDIV1000 9720000UL +#define DP_VCO_RATE_10800MHZDIV1000 10800000UL + +struct dp_pll_vco_clk { + struct clk_hw hw; + unsigned long rate; /* current vco rate */ + u64 min_rate; /* min vco rate */ + u64 max_rate; /* max vco rate */ + void *priv; +}; + +struct dp_pll_db { + struct msm_dp_pll *base; + + int id; + struct platform_device *pdev; + + /* private clocks: */ + bool fixed_factor_clk[NUM_DP_CLOCKS_MAX]; + struct clk_hw *hws[NUM_DP_CLOCKS_MAX]; + u32 num_hws; + + /* lane and orientation settings */ + u8 lane_cnt; + u8 orientation; + + /* COM PHY settings */ + u32 hsclk_sel; + u32 dec_start_mode0; + u32 div_frac_start1_mode0; + u32 div_frac_start2_mode0; + u32 div_frac_start3_mode0; + u32 integloop_gain0_mode0; + u32 integloop_gain1_mode0; + u32 vco_tune_map; + u32 lock_cmp1_mode0; + u32 lock_cmp2_mode0; + u32 lock_cmp3_mode0; + u32 lock_cmp_en; + + /* PHY vco divider */ + u32 phy_vco_div; + /* + * Certain pll's needs to update the same vco rate after resume in + * suspend/resume scenario. Cached the vco rate for such plls. + */ + unsigned long vco_cached_rate; + u32 cached_cfg0; + u32 cached_cfg1; + u32 cached_outdiv; + + uint32_t index; +}; + +static inline struct dp_pll_vco_clk *to_dp_vco_hw(struct clk_hw *hw) +{ + return container_of(hw, struct dp_pll_vco_clk, hw); +} + +#define to_msm_dp_pll(vco) ((struct msm_dp_pll *)vco->priv) + +#define to_dp_pll_db(x) ((struct dp_pll_db *)x->priv) + +int msm_dp_pll_10nm_init(struct msm_dp_pll *dp_pll, int id); +void msm_dp_pll_10nm_deinit(struct msm_dp_pll *dp_pll); + +#endif /* __DP_PLL_10NM_H */ diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 4aaa0aae48832..8b0a276d34a46 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -101,6 +101,16 @@ static int dp_power_clk_init(struct dp_power_private *power) core = &power->parser->mp[DP_CORE_PM]; ctrl = &power->parser->mp[DP_CTRL_PM]; + if (power->parser->pll && power->parser->pll->get_provider) { + rc = power->parser->pll->get_provider(power->parser->pll, + &power->link_provider, &power->pixel_provider); + if (rc) { + DRM_ERROR("%s:provider failed,don't set parent\n", + __func__); + return 0; + } + } + rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk); if (rc) { DRM_ERROR("failed to get %s clk. err=%d\n", diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h index ae55b78bf54a1..756341e290ed0 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ b/drivers/gpu/drm/msm/dp/dp_power.h @@ -14,7 +14,6 @@ * @init: initializes the regulators/core clocks/GPIOs/pinctrl * @deinit: turns off the regulators/core clocks/GPIOs/pinctrl * @clk_enable: enable/disable the DP clocks - * @set_link_clk_parent: set the parent of DP link clock * @set_pixel_clk_parent: set the parent of DP pixel clock */ struct dp_power { @@ -22,10 +21,49 @@ struct dp_power { bool link_clks_on; }; +/** + * dp_power_init() - enable power supplies for display controller + * + * @power: instance of power module + * @flip: bool for flipping gpio direction + * return: 0 if success or error if failure. + * + * This API will turn on the regulators and configures gpio's + * aux/hpd. + */ int dp_power_init(struct dp_power *power, bool flip); + +/** + * dp_power_deinit() - turn off regulators and gpios. + * + * @power: instance of power module + * return: 0 for success + * + * This API turns off power and regulators. + */ int dp_power_deinit(struct dp_power *power); + +/** + * dp_power_clk_enable() - enable display controller clocks + * + * @power: instance of power module + * @pm_type: type of pm, core/ctrl/phy + * @enable: enables or disables + * return: pointer to allocated power module data + * + * This API will call setrate and enable for DP clocks + */ + int dp_power_clk_enable(struct dp_power *power, enum dp_pm_type pm_type, bool enable); +/** + * dp_power_set_link_clk_parent() - configures parent of link clocks + * + * @power: instance of power module + * return: 0 for success, error for failures + * + * This API will set the link clock parent source + */ int dp_power_set_link_clk_parent(struct dp_power *power); /** diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 67a2d040b221a..893fc3250c3e4 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -6,6 +6,22 @@ #ifndef _DP_REG_H_ #define _DP_REG_H_ +/* DP PHY Register Regions */ +#define REG_DP_PHY_REGION_BASE (0x088ea000) +#define REG_DP_PHY_REGION_SIZE (0x00000C00) + +#define REG_USB3_DP_COM_REGION_BASE (0x088e8000) +#define REG_USB3_DP_COM_REGION_SIZE (0x00000020) + +#define DP_PHY_PLL_OFFSET (0x00000000) +#define DP_PHY_PLL_SIZE (0x00000200) +#define DP_PHY_REG_OFFSET (0x00000A00) +#define DP_PHY_REG_SIZE (0x00000200) +#define DP_PHY_LN_TX0_OFFSET (0x00000200) +#define DP_PHY_LN_TX0_SIZE (0x00000200) +#define DP_PHY_LN_TX1_OFFSET (0x00000600) +#define DP_PHY_LN_TX1_SIZE (0x00000200) + /* DP_TX Registers */ #define REG_DP_HW_VERSION (0x00000000) -- GitLab From a10476e45026fefe782c444a39c6fc5d4999a6ac Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran <jsanka@codeaurora.org> Date: Thu, 27 Aug 2020 14:16:57 -0700 Subject: [PATCH 1120/1494] drm/msm/dpu: add display port support in DPU Add display port support in DPU by creating hooks for DP encoder enumeration and encoder mode initialization. changes in v2: - rebase on [2] (Sean Paul) - remove unwanted error checks and switch cases (Jordan Crouse) [1] https://lwn.net/Articles/768265/ [2] https://lkml.org/lkml/2018/11/17/87 changes in V3: -- Moved this change as part of the DP driver changes. -- Addressed compilation issues on the latest code base. Changes in v6: -- Fix checkpatch.pl warning Changes in v7: Remove depends-on tag from commit message. Changes in v8: None Changes in v9: None Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org> Signed-off-by: Chandan Uddaraju <chandanu@codeaurora.org> Signed-off-by: Vara Reddy <varar@codeaurora.org> Signed-off-by: Tanmay Shah <tanmay@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 8 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 65 +++++++++++++++++---- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index eb2ba7e070837..1d12e7cd11fed 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2027,7 +2027,7 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, { int ret = 0; int i = 0; - enum dpu_intf_type intf_type; + enum dpu_intf_type intf_type = INTF_NONE; struct dpu_enc_phys_init_params phys_params; if (!dpu_enc) { @@ -2049,9 +2049,9 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc, case DRM_MODE_ENCODER_DSI: intf_type = INTF_DSI; break; - default: - DPU_ERROR_ENC(dpu_enc, "unsupported display interface type\n"); - return -EINVAL; + case DRM_MODE_ENCODER_TMDS: + intf_type = INTF_DP; + break; } WARN_ON(disp_info->num_of_h_tiles < 1); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 5abf0047c2d32..3469f6ef792ee 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -501,6 +501,33 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev, return rc; } +static int _dpu_kms_initialize_displayport(struct drm_device *dev, + struct msm_drm_private *priv, + struct dpu_kms *dpu_kms) +{ + struct drm_encoder *encoder = NULL; + int rc = 0; + + if (!priv->dp) + return rc; + + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } + + rc = msm_dp_modeset_init(priv->dp, dev, encoder); + if (rc) { + DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); + drm_encoder_cleanup(encoder); + return rc; + } + + priv->encoders[priv->num_encoders++] = encoder; + return rc; +} + /** * _dpu_kms_setup_displays - create encoders, bridges and connectors * for underlying displays @@ -513,12 +540,21 @@ static int _dpu_kms_setup_displays(struct drm_device *dev, struct msm_drm_private *priv, struct dpu_kms *dpu_kms) { - /** - * Extend this function to initialize other - * types of displays - */ + int rc = 0; + + rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms); + if (rc) { + DPU_ERROR("initialize_dsi failed, rc = %d\n", rc); + return rc; + } - return _dpu_kms_initialize_dsi(dev, priv, dpu_kms); + rc = _dpu_kms_initialize_displayport(dev, priv, dpu_kms); + if (rc) { + DPU_ERROR("initialize_DP failed, rc = %d\n", rc); + return rc; + } + + return rc; } static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms) @@ -703,13 +739,20 @@ static void _dpu_kms_set_encoder_mode(struct msm_kms *kms, info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE : MSM_DISPLAY_CAP_VID_MODE; - /* TODO: No support for DSI swap */ - for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { - if (priv->dsi[i]) { - info.h_tile_instance[info.num_of_h_tiles] = i; - info.num_of_h_tiles++; + switch (info.intf_type) { + case DRM_MODE_ENCODER_DSI: + /* TODO: No support for DSI swap */ + for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) { + if (priv->dsi[i]) { + info.h_tile_instance[info.num_of_h_tiles] = i; + info.num_of_h_tiles++; + } } - } + break; + case DRM_MODE_ENCODER_TMDS: + info.num_of_h_tiles = 1; + break; + }; rc = dpu_encoder_setup(encoder->dev, encoder, &info); if (rc) -- GitLab From 220b856a3d3742a22831cb6cd94e48133a58d30e Mon Sep 17 00:00:00 2001 From: Tanmay Shah <tanmay@codeaurora.org> Date: Thu, 27 Aug 2020 14:16:58 -0700 Subject: [PATCH 1121/1494] drm/msm/dp: Add Display Port HPD feature Configure HPD registers in DP controller and enable HPD interrupt. Add interrupt to handle HPD connect and disconnect events. Changes in v8: None Signed-off-by: Tanmay Shah <tanmay@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 18 ++++ drivers/gpu/drm/msm/dp/dp_catalog.c | 67 +++++++++------ drivers/gpu/drm/msm/dp/dp_catalog.h | 5 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 1 - drivers/gpu/drm/msm/dp/dp_display.c | 108 ++++++++++++++++++++++-- drivers/gpu/drm/msm/dp/dp_reg.h | 12 +++ drivers/gpu/drm/msm/msm_drv.h | 6 ++ 7 files changed, 182 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 3469f6ef792ee..bcb5ee50568c7 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -774,6 +774,23 @@ static void dpu_irq_preinstall(struct msm_kms *kms) dpu_core_irq_preinstall(dpu_kms); } +static int dpu_irq_postinstall(struct msm_kms *kms) +{ + struct msm_drm_private *priv; + struct dpu_kms *dpu_kms = to_dpu_kms(kms); + + if (!dpu_kms || !dpu_kms->dev) + return -EINVAL; + + priv = dpu_kms->dev->dev_private; + if (!priv) + return -EINVAL; + + msm_dp_irq_postinstall(priv->dp); + + return 0; +} + static void dpu_irq_uninstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); @@ -784,6 +801,7 @@ static void dpu_irq_uninstall(struct msm_kms *kms) static const struct msm_kms_funcs kms_funcs = { .hw_init = dpu_kms_hw_init, .irq_preinstall = dpu_irq_preinstall, + .irq_postinstall = dpu_irq_postinstall, .irq_uninstall = dpu_irq_uninstall, .irq = dpu_irq, .enable_commit = dpu_kms_enable_commit, diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index d27e17d7d18cd..c16072630d407 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -17,7 +17,6 @@ #define POLLING_SLEEP_US 1000 #define POLLING_TIMEOUT_US 10000 -#define REFTIMER_DEFAULT_VALUE 0x20000 #define SCRAMBLER_RESET_COUNT_VALUE 0xFC #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 @@ -746,35 +745,51 @@ void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, } } -void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog, bool en) +void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, + u32 intr_mask, bool en) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - if (en) { - u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); - - dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, - DP_DP_HPD_PLUG_INT_ACK | - DP_DP_IRQ_HPD_INT_ACK | - DP_DP_HPD_REPLUG_INT_ACK | - DP_DP_HPD_UNPLUG_INT_ACK); - dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, - DP_DP_HPD_PLUG_INT_MASK | - DP_DP_IRQ_HPD_INT_MASK | - DP_DP_HPD_REPLUG_INT_MASK | - DP_DP_HPD_UNPLUG_INT_MASK); - - /* Configure REFTIMER */ - reftimer |= REFTIMER_DEFAULT_VALUE; - dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); - /* Enable HPD */ - dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, - DP_DP_HPD_CTRL_HPD_EN); - } else { - /* Disable HPD */ - dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, 0x0); - } + u32 config = dp_read_aux(catalog, REG_DP_DP_HPD_INT_MASK); + + config = (en ? config | intr_mask : config & ~intr_mask); + + dp_write_aux(catalog, REG_DP_DP_HPD_INT_MASK, + config & DP_DP_HPD_INT_MASK); +} + +void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + u32 reftimer = dp_read_aux(catalog, REG_DP_DP_HPD_REFTIMER); + + /* enable HPD interrupts */ + dp_catalog_hpd_config_intr(dp_catalog, + DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK + | DP_DP_HPD_UNPLUG_INT_MASK, true); + + /* Configure REFTIMER and enable it */ + reftimer |= DP_DP_HPD_REFTIMER_ENABLE; + dp_write_aux(catalog, REG_DP_DP_HPD_REFTIMER, reftimer); + + /* Enable HPD */ + dp_write_aux(catalog, REG_DP_DP_HPD_CTRL, DP_DP_HPD_CTRL_HPD_EN); +} + +u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + int isr = 0; + + isr = dp_read_aux(catalog, REG_DP_DP_HPD_INT_STATUS); + dp_write_aux(catalog, REG_DP_DP_HPD_INT_ACK, + (isr & DP_DP_HPD_INT_MASK)); + + return isr; } int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index 012570be16353..35c90b248b5d1 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -76,7 +76,10 @@ void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_usb_reset(struct dp_catalog *dp_catalog, bool flip); bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); -void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog, bool enable); +void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, + u32 intr_mask, bool en); +void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog); +u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog *dp_catalog, bool flipped, u8 lane_cnt); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 9a06cbf40af1b..ae07e43b541b6 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1563,7 +1563,6 @@ int dp_ctrl_on(struct dp_ctrl *dp_ctrl) rate = ctrl->panel->link_info.rate; dp_power_clk_enable(ctrl->power, DP_CORE_PM, true); - dp_catalog_ctrl_hpd_config(ctrl->catalog, true); if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { DRM_DEBUG_DP("using phy test link parameters\n"); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c8851f4bbf727..925c89720a16e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -17,6 +17,7 @@ #include "dp_power.h" #include "dp_catalog.h" #include "dp_aux.h" +#include "dp_reg.h" #include "dp_link.h" #include "dp_panel.h" #include "dp_ctrl.h" @@ -36,6 +37,7 @@ struct dp_display_private { bool power_on; bool hpd_irq_on; bool audio_supported; + atomic_t hpd_isr_status; struct platform_device *pdev; struct dentry *root; @@ -54,6 +56,8 @@ struct dp_display_private { struct dp_usbpd_cb usbpd_cb; struct dp_display_mode dp_mode; struct msm_dp dp_display; + + struct delayed_work config_hpd_work; }; static const struct of_device_id dp_dt_match[] = { @@ -64,6 +68,20 @@ static const struct of_device_id dp_dt_match[] = { static irqreturn_t dp_display_irq(int irq, void *dev_id) { struct dp_display_private *dp = dev_id; + irqreturn_t ret = IRQ_HANDLED; + u32 hpd_isr_status; + + if (!dp) { + DRM_ERROR("invalid data\n"); + return IRQ_NONE; + } + + hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog); + + if (hpd_isr_status & DP_DP_HPD_INT_MASK) { + atomic_set(&dp->hpd_isr_status, hpd_isr_status); + ret = IRQ_WAKE_THREAD; + } /* DP controller isr */ dp_ctrl_isr(dp->ctrl); @@ -71,6 +89,54 @@ static irqreturn_t dp_display_irq(int irq, void *dev_id) /* DP aux isr */ dp_aux_isr(dp->aux); + return ret; +} + +static irqreturn_t dp_display_hpd_isr_work(int irq, void *data) +{ + struct dp_display_private *dp; + struct dp_usbpd *hpd; + u32 isr = 0; + + dp = (struct dp_display_private *)data; + if (!dp) + return IRQ_NONE; + + isr = atomic_read(&dp->hpd_isr_status); + + /* reset to default */ + atomic_set(&dp->hpd_isr_status, 0); + + hpd = dp->usbpd; + if (!hpd) + return IRQ_NONE; + + if (isr & DP_DP_HPD_PLUG_INT_MASK && + isr & DP_DP_HPD_STATE_STATUS_CONNECTED) { + hpd->hpd_high = 1; + dp->usbpd_cb.configure(&dp->pdev->dev); + } else if (isr & DP_DP_HPD_UNPLUG_INT_MASK && + (isr & DP_DP_HPD_STATE_STATUS_MASK) == + DP_DP_HPD_STATE_STATUS_DISCONNECTED) { + + /* disable HPD plug interrupt until disconnect is done + */ + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, + false); + + hpd->hpd_high = 0; + + /* We don't need separate work for disconnect as + * connect/attention interrupts are disabled + */ + dp->usbpd_cb.disconnect(&dp->pdev->dev); + + dp_catalog_hpd_config_intr(dp->catalog, + DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, + true); + } + return IRQ_HANDLED; } @@ -212,8 +278,6 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) int rc = 0; struct edid *edid; - dp_aux_init(dp->aux); - if (dp->link->psm_enabled) goto notify; @@ -270,10 +334,6 @@ static void dp_display_host_deinit(struct dp_display_private *dp) return; } - dp_ctrl_host_deinit(dp->ctrl); - dp_aux_deinit(dp->aux); - dp_power_deinit(dp->power); - disable_irq(dp->irq); dp->core_initialized = false; } @@ -630,7 +690,8 @@ int dp_display_request_irq(struct msm_dp *dp_display) return rc; } - rc = devm_request_irq(&dp->pdev->dev, dp->irq, dp_display_irq, + rc = devm_request_threaded_irq(&dp->pdev->dev, dp->irq, + dp_display_irq, dp_display_hpd_isr_work, IRQF_TRIGGER_HIGH, "dp_display_isr", dp); if (rc < 0) { DRM_ERROR("failed to request IRQ%u: %d\n", @@ -829,6 +890,39 @@ void __exit msm_dp_unregister(void) platform_driver_unregister(&dp_display_driver); } +static void dp_display_config_hpd_work(struct work_struct *work) +{ + struct dp_display_private *dp; + struct delayed_work *dw = to_delayed_work(work); + + dp = container_of(dw, struct dp_display_private, config_hpd_work); + + dp_display_host_init(dp); + dp_catalog_ctrl_hpd_config(dp->catalog); + + /* set default to 0 */ + atomic_set(&dp->hpd_isr_status, 0); + + /* Enable interrupt first time + * we are leaving dp clocks on during disconnect + * and never disable interrupt + */ + enable_irq(dp->irq); +} + +void msm_dp_irq_postinstall(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + if (!dp_display) + return; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + INIT_DELAYED_WORK(&dp->config_hpd_work, dp_display_config_hpd_work); + queue_delayed_work(system_wq, &dp->config_hpd_work, HZ * 10); +} + int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 893fc3250c3e4..721c0cc692965 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -54,10 +54,22 @@ #define DP_DP_IRQ_HPD_INT_MASK (0x00000002) #define DP_DP_HPD_REPLUG_INT_MASK (0x00000004) #define DP_DP_HPD_UNPLUG_INT_MASK (0x00000008) +#define DP_DP_HPD_INT_MASK (DP_DP_HPD_PLUG_INT_MASK | \ + DP_DP_IRQ_HPD_INT_MASK | \ + DP_DP_HPD_REPLUG_INT_MASK | \ + DP_DP_HPD_UNPLUG_INT_MASK) +#define DP_DP_HPD_STATE_STATUS_CONNECTED (0x40000000) +#define DP_DP_HPD_STATE_STATUS_PENDING (0x20000000) +#define DP_DP_HPD_STATE_STATUS_DISCONNECTED (0x00000000) +#define DP_DP_HPD_STATE_STATUS_MASK (0xE0000000) #define REG_DP_DP_HPD_REFTIMER (0x00000018) +#define DP_DP_HPD_REFTIMER_ENABLE (1 << 16) + #define REG_DP_DP_HPD_EVENT_TIME_0 (0x0000001C) #define REG_DP_DP_HPD_EVENT_TIME_1 (0x00000020) +#define DP_DP_HPD_EVENT_TIME_0_VAL (0x3E800FA) +#define DP_DP_HPD_EVENT_TIME_1_VAL (0x1F407D0) #define REG_DP_AUX_CTRL (0x00000030) #define DP_AUX_CTRL_ENABLE (0x00000001) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index ff165dafa6c6f..f898a4121ce9b 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -395,6 +395,7 @@ int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder); void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); +void msm_dp_irq_postinstall(struct msm_dp *dp_display); #else static inline int __init msm_dp_register(void) @@ -426,6 +427,11 @@ static inline void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_display_mode *adjusted_mode) { } + +static inline void msm_dp_irq_postinstall(struct msm_dp *dp_display) +{ +} + #endif void __init msm_mdp_register(void); -- GitLab From 8ede2ecc3e5ee327923f6e3cfe52761ce73607d1 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh <khsieh@codeaurora.org> Date: Fri, 11 Sep 2020 20:36:42 +0000 Subject: [PATCH 1122/1494] drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets add event thread to execute events serially from event queue. Also timeout mode is supported which allow an event be deferred to be executed at later time. Both link and phy compliant tests had been done successfully. Changes in v2: -- Fix potential deadlock by removing redundant connect_mutex -- Check and enable link clock during modeset -- Drop unused code and fix function prototypes. -- set sink power to normal operation state (D0) before DPCD read Changes in v3: -- push idle pattern at main link before timing generator off -- add timeout handles for both connect and disconnect Changes in v4: -- add ST_SUSPEND_PENDING to handles suspend/modeset test operations -- clear dp phy aux interrupt status when ERR_DPPHY_AUX error -- send segment addr during edid read -- clear bpp depth before MISC register write Changes in v5: -- add ST_SUSPENDED to fix crash at resume Changes in v6: -- at msm_dp_display_enable() do not return until resume_done to avoid kms commit timeout Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 6 + drivers/gpu/drm/msm/dp/dp_aux.c | 1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 77 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 370 ++++++--- drivers/gpu/drm/msm/dp/dp_ctrl.h | 3 +- drivers/gpu/drm/msm/dp/dp_display.c | 828 ++++++++++++++------ drivers/gpu/drm/msm/dp/dp_display.h | 1 - drivers/gpu/drm/msm/dp/dp_drm.c | 4 - drivers/gpu/drm/msm/dp/dp_hpd.c | 2 +- drivers/gpu/drm/msm/dp/dp_hpd.h | 1 + drivers/gpu/drm/msm/dp/dp_link.c | 22 +- drivers/gpu/drm/msm/dp/dp_panel.c | 78 +- drivers/gpu/drm/msm/dp/dp_panel.h | 9 +- drivers/gpu/drm/msm/dp/dp_parser.c | 42 +- drivers/gpu/drm/msm/dp/dp_parser.h | 2 + drivers/gpu/drm/msm/dp/dp_power.c | 46 +- drivers/gpu/drm/msm/dp/dp_power.h | 13 + drivers/gpu/drm/msm/dp/dp_reg.h | 1 + drivers/gpu/drm/msm/msm_drv.h | 1 + 19 files changed, 1050 insertions(+), 457 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 1d12e7cd11fed..702a290409582 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1225,6 +1225,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { + if (msm_dp_display_pre_disable(priv->dp, drm_enc)) + DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n"); + } + dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP); for (i = 0; i < dpu_enc->num_phys_encs; i++) { @@ -1234,6 +1239,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) phys->ops.disable(phys); } + /* 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); diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index 6bf3a5712968c..d742b4d870b37 100644 --- a/drivers/gpu/drm/msm/dp/dp_aux.c +++ b/drivers/gpu/drm/msm/dp/dp_aux.c @@ -384,6 +384,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, PHY_AUX_CFG1); dp_catalog_aux_reset(aux->catalog); } + usleep_range(400, 500); /* at least 400us to next try */ goto unlock_exit; } diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index c16072630d407..67abb90953e49 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -536,16 +536,21 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, * To make sure link reg writes happens before other operation, * dp_write_link() function uses writel() */ - dp_write_link(catalog, REG_DP_MAINLINK_CTRL, - DP_MAINLINK_FB_BOUNDARY_SEL); - dp_write_link(catalog, REG_DP_MAINLINK_CTRL, - DP_MAINLINK_FB_BOUNDARY_SEL | - DP_MAINLINK_CTRL_RESET); - dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); + + mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET | + DP_MAINLINK_CTRL_ENABLE); + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl |= DP_MAINLINK_CTRL_RESET; + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET; + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); + + mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE | DP_MAINLINK_FB_BOUNDARY_SEL); - dp_write_link(catalog, REG_DP_MAINLINK_CTRL, - DP_MAINLINK_FB_BOUNDARY_SEL | - DP_MAINLINK_CTRL_ENABLE); + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl); } else { mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE; @@ -644,7 +649,7 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, bit = BIT(pattern - 1); DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern); - dp_write_link(catalog, REG_DP_STATE_CTRL, bit); + dp_catalog_ctrl_state_ctrl(dp_catalog, bit); bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT; @@ -769,7 +774,7 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog) /* enable HPD interrupts */ dp_catalog_hpd_config_intr(dp_catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK - | DP_DP_HPD_UNPLUG_INT_MASK, true); + | DP_DP_HPD_UNPLUG_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true); /* Configure REFTIMER and enable it */ reftimer |= DP_DP_HPD_REFTIMER_ENABLE; @@ -881,15 +886,27 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0); switch (pattern) { - case DP_LINK_QUAL_PATTERN_D10_2: + case DP_PHY_TEST_PATTERN_D10_2: dp_write_link(catalog, REG_DP_STATE_CTRL, DP_STATE_CTRL_LINK_TRAINING_PATTERN1); - return; - case DP_LINK_QUAL_PATTERN_PRBS7: + break; + case DP_PHY_TEST_PATTERN_ERROR_COUNT: + value &= ~(1 << 16); + dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + value |= SCRAMBLER_RESET_COUNT_VALUE; + dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, + value); + dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, + DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); + break; + case DP_PHY_TEST_PATTERN_PRBS7: dp_write_link(catalog, REG_DP_STATE_CTRL, DP_STATE_CTRL_LINK_PRBS7); - return; - case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM: + break; + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: dp_write_link(catalog, REG_DP_STATE_CTRL, DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN); /* 00111110000011111000001111100000 */ @@ -901,14 +918,15 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, /* 1111100000111110 */ dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2, 0x0000F83E); - return; - case DP_LINK_QUAL_PATTERN_HBR2_EYE: - case DP_LINK_QUAL_PATTERN_ERROR_RATE: - value &= ~DP_HBR2_ERM_PATTERN; - if (pattern == DP_LINK_QUAL_PATTERN_HBR2_EYE) - value = DP_HBR2_ERM_PATTERN; + break; + case DP_PHY_TEST_PATTERN_CP2520: + value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); + value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER; + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); + + value = DP_HBR2_ERM_PATTERN; dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, - value); + value); value |= SCRAMBLER_RESET_COUNT_VALUE; dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET, value); @@ -916,10 +934,19 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog, DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2); dp_write_link(catalog, REG_DP_STATE_CTRL, DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE); - return; + value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL); + value |= DP_MAINLINK_CTRL_ENABLE; + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value); + break; + case DP_PHY_TEST_PATTERN_SEL_MASK: + dp_write_link(catalog, REG_DP_MAINLINK_CTRL, + DP_MAINLINK_CTRL_ENABLE); + dp_write_link(catalog, REG_DP_STATE_CTRL, + DP_STATE_CTRL_LINK_TRAINING_PATTERN4); + break; default: DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern); - return; + break; } } diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index ae07e43b541b6..70b0e06953f63 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -26,6 +26,13 @@ #define MR_LINK_SYMBOL_ERM 0x80 #define MR_LINK_PRBS7 0x100 #define MR_LINK_CUSTOM80 0x200 +#define MR_LINK_TRAINING4 0x40 + +enum { + DP_TRAINING_NONE, + DP_TRAINING_1, + DP_TRAINING_2, +}; struct dp_tu_calc_input { u64 lclk; /* 162, 270, 540 and 810 */ @@ -58,7 +65,6 @@ struct dp_vc_tu_mapping_table { struct dp_ctrl_private { struct dp_ctrl dp_ctrl; - struct device *dev; struct drm_dp_aux *aux; struct dp_panel *panel; @@ -68,10 +74,16 @@ struct dp_ctrl_private { struct dp_catalog *catalog; struct completion idle_comp; - struct mutex push_idle_mutex; struct completion video_comp; }; +struct dp_cr_status { + u8 lane_0_1; + u8 lane_2_3; +}; + +#define DP_LANE0_1_CR_DONE 0x11 + static int dp_aux_link_configure(struct drm_dp_aux *aux, struct dp_link_info *link) { @@ -97,8 +109,6 @@ void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - mutex_lock(&ctrl->push_idle_mutex); - reinit_completion(&ctrl->idle_comp); dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE); @@ -106,7 +116,6 @@ void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl) IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES)) pr_warn("PUSH_IDLE pattern timedout\n"); - mutex_unlock(&ctrl->push_idle_mutex); pr_debug("mainlink off done\n"); } @@ -979,7 +988,7 @@ static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl) if (!wait_for_completion_timeout(&ctrl->video_comp, WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES)) { - DRM_ERROR("Link Train timedout\n"); + DRM_ERROR("wait4video timedout\n"); ret = -ETIMEDOUT; } return ret; @@ -1000,13 +1009,13 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl) if (ret) return ret; - if (voltage_swing_level > DP_TRAIN_VOLTAGE_SWING_MAX) { + if (voltage_swing_level >= DP_TRAIN_VOLTAGE_SWING_MAX) { DRM_DEBUG_DP("max. voltage swing level reached %d\n", voltage_swing_level); max_level_reached |= DP_TRAIN_MAX_SWING_REACHED; } - if (pre_emphasis_level == DP_TRAIN_PRE_EMPHASIS_MAX) { + if (pre_emphasis_level >= DP_TRAIN_PRE_EMPHASIS_MAX) { DRM_DEBUG_DP("max. pre-emphasis level reached %d\n", pre_emphasis_level); max_level_reached |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; @@ -1038,8 +1047,11 @@ static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl, DRM_DEBUG_DP("sink: pattern=%x\n", pattern); buf = pattern; - ret = drm_dp_dpcd_writeb(ctrl->aux, - DP_TRAINING_PATTERN_SET, buf); + + if (pattern && pattern != DP_TRAINING_PATTERN_4) + buf |= DP_LINK_SCRAMBLING_DISABLE; + + ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf); return ret == 1; } @@ -1065,19 +1077,23 @@ static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl, return -ETIMEDOUT; } -static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) +static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl, + struct dp_cr_status *cr, int *training_step) { int tries, old_v_level, ret = 0; u8 link_status[DP_LINK_STATUS_SIZE]; - int const maximum_retries = 5; + int const maximum_retries = 4; dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + *training_step = DP_TRAINING_1; + ret = dp_catalog_ctrl_set_pattern(ctrl->catalog, DP_TRAINING_PATTERN_1); if (ret) return ret; dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE); + ret = dp_ctrl_update_vx_px(ctrl); if (ret) return ret; @@ -1091,12 +1107,15 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) if (ret) return ret; + cr->lane_0_1 = link_status[0]; + cr->lane_2_3 = link_status[1]; + if (drm_dp_clock_recovery_ok(link_status, ctrl->link->link_params.num_lanes)) { - return ret; + return 0; } - if (ctrl->link->phy_params.v_level > + if (ctrl->link->phy_params.v_level >= DP_TRAIN_VOLTAGE_SWING_MAX) { DRM_ERROR_RATELIMITED("max v_level reached\n"); return -EAGAIN; @@ -1119,8 +1138,10 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl) return -ETIMEDOUT; } -static void dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) +static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) { + int ret = 0; + switch (ctrl->link->link_params.rate) { case 810000: ctrl->link->link_params.rate = 540000; @@ -1129,13 +1150,33 @@ static void dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl) ctrl->link->link_params.rate = 270000; break; case 270000: + ctrl->link->link_params.rate = 162000; + break; case 162000: default: - ctrl->link->link_params.rate = 162000; + ret = -EINVAL; break; }; - DRM_DEBUG_DP("new rate=0x%x\n", ctrl->link->link_params.rate); + if (!ret) + DRM_DEBUG_DP("new rate=0x%x\n", ctrl->link->link_params.rate); + + return ret; +} + +static int dp_ctrl_link_lane_down_shift(struct dp_ctrl_private *ctrl) +{ + + if (ctrl->link->link_params.num_lanes == 1) + return -1; + + ctrl->link->link_params.num_lanes /= 2; + ctrl->link->link_params.rate = ctrl->panel->link_info.rate; + + ctrl->link->phy_params.p_level = 0; + ctrl->link->phy_params.v_level = 0; + + return 0; } static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) @@ -1144,7 +1185,8 @@ static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl) drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd); } -static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) +static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl, + struct dp_cr_status *cr, int *training_step) { int tries = 0, ret = 0; char pattern; @@ -1153,6 +1195,8 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); + *training_step = DP_TRAINING_2; + if (drm_dp_tps3_supported(ctrl->panel->dpcd)) pattern = DP_TRAINING_PATTERN_3; else @@ -1174,10 +1218,13 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) ret = dp_ctrl_read_link_status(ctrl, link_status); if (ret) return ret; + cr->lane_0_1 = link_status[0]; + cr->lane_2_3 = link_status[1]; if (drm_dp_channel_eq_ok(link_status, - ctrl->link->link_params.num_lanes)) - return ret; + ctrl->link->link_params.num_lanes)) { + return 0; + } dp_link_adjust_levels(ctrl->link, link_status); ret = dp_ctrl_update_vx_px(ctrl); @@ -1189,15 +1236,15 @@ static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl) return -ETIMEDOUT; } -static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) +static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl); + +static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl, + struct dp_cr_status *cr, int *training_step) { int ret = 0; u8 encoding = DP_SET_ANSI_8B10B; struct dp_link_info link_info = {0}; - ctrl->link->phy_params.p_level = 0; - ctrl->link->phy_params.v_level = 0; - dp_ctrl_config_ctrl(ctrl); link_info.num_lanes = ctrl->link->link_params.num_lanes; @@ -1208,7 +1255,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET, &encoding, 1); - ret = dp_ctrl_link_train_1(ctrl); + ret = dp_ctrl_link_train_1(ctrl, cr, training_step); if (ret) { DRM_ERROR("link training #1 failed. ret=%d\n", ret); goto end; @@ -1217,7 +1264,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) /* print success info as this is a result of user initiated action */ DRM_DEBUG_DP("link training #1 successful\n"); - ret = dp_ctrl_link_training_2(ctrl); + ret = dp_ctrl_link_train_2(ctrl, cr, training_step); if (ret) { DRM_ERROR("link training #2 failed. ret=%d\n", ret); goto end; @@ -1229,58 +1276,36 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl) end: dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0); - dp_ctrl_clear_training_pattern(ctrl); return ret; } -static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, bool train) +static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, + struct dp_cr_status *cr, int *training_step) { - bool mainlink_ready = false; int ret = 0; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true); - ret = dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, false); - if (ret) - return ret; - if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) return ret; - if (train) { - /* - * As part of previous calls, DP controller state might have - * transitioned to PUSH_IDLE. In order to start transmitting - * a link training pattern, we have to first do soft reset. - */ - dp_catalog_ctrl_reset(ctrl->catalog); - - ret = dp_ctrl_link_train(ctrl); - if (ret) - return ret; - } - /* - * Set up transfer unit values and set controller state to send - * video. + * As part of previous calls, DP controller state might have + * transitioned to PUSH_IDLE. In order to start transmitting + * a link training pattern, we have to first do soft reset. */ - dp_ctrl_setup_tr_unit(ctrl); - dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + dp_catalog_ctrl_reset(ctrl->catalog); - ret = dp_ctrl_wait4video_ready(ctrl); - if (ret) - return ret; + ret = dp_ctrl_link_train(ctrl, cr, training_step); - mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog); - DRM_DEBUG_DP("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); return ret; } static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, - char *name, u32 rate) + enum dp_pm_type module, char *name, u32 rate) { - u32 num = ctrl->parser->mp[DP_CTRL_PM].num_clk; - struct dss_clk *cfg = ctrl->parser->mp[DP_CTRL_PM].clk_config; + u32 num = ctrl->parser->mp[module].num_clk; + struct dss_clk *cfg = ctrl->parser->mp[module].clk_config; while (num && strcmp(cfg->clk_name, name)) { num--; @@ -1302,16 +1327,33 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) dp_power_set_link_clk_parent(ctrl->power); - dp_ctrl_set_clock_rate(ctrl, "ctrl_link", + dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link", ctrl->link->link_params.rate); - dp_ctrl_set_clock_rate(ctrl, "stream_pixel", - ctrl->dp_ctrl.pixel_rate); - ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true); if (ret) DRM_ERROR("Unable to start link clocks. ret=%d\n", ret); + DRM_DEBUG_DP("link rate=%d pixel_clk=%d\n", + ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate); + + return ret; +} + +static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) +{ + int ret = 0; + + dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", + ctrl->dp_ctrl.pixel_rate); + + ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); + if (ret) + DRM_ERROR("Unabled to start pixel clocks. ret=%d\n", ret); + + DRM_DEBUG_DP("link rate=%d pixel_clk=%d\n", + ctrl->link->link_params.rate, ctrl->dp_ctrl.pixel_rate); + return ret; } @@ -1401,37 +1443,30 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) return ret; } - dp_ctrl_configure_source_params(ctrl); - dp_catalog_ctrl_config_msa(ctrl->catalog, - ctrl->link->link_params.rate, - ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl)); - reinit_completion(&ctrl->idle_comp); - return ret; } static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl) { int ret = 0; - int tries; + struct dp_cr_status cr; + int training_step = DP_TRAINING_NONE; dp_ctrl_push_idle(&ctrl->dp_ctrl); dp_catalog_ctrl_reset(ctrl->catalog); ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; - for (tries = 0; tries < 10; tries++) { - ret = dp_ctrl_reinitialize_mainlink(ctrl); - if (ret) { - DRM_ERROR("Failed to reinitialize mainlink. ret=%d\n", - ret); - break; - } + ret = dp_ctrl_setup_main_link(ctrl, &cr, &training_step); + if (ret) + goto end; - ret = dp_ctrl_setup_main_link(ctrl, true); - if (ret == -EAGAIN) /* try with lower link rate */ - dp_ctrl_link_rate_down_shift(ctrl); - } + dp_ctrl_clear_training_pattern(ctrl); + + dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + + ret = dp_ctrl_wait4video_ready(ctrl); +end: return ret; } @@ -1444,22 +1479,22 @@ static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl) return ret; } - dp_ctrl_push_idle(&ctrl->dp_ctrl); /* * The global reset will need DP link related clocks to be * running. Add the global reset just before disabling the * link clocks and core clocks. */ - dp_catalog_ctrl_reset(ctrl->catalog); ret = dp_ctrl_off(&ctrl->dp_ctrl); if (ret) { DRM_ERROR("failed to disable DP controller\n"); return ret; } - ret = dp_ctrl_on(&ctrl->dp_ctrl); - if (ret) - DRM_ERROR("failed to enable DP controller\n"); + ret = dp_ctrl_on_link(&ctrl->dp_ctrl); + if (!ret) + ret = dp_ctrl_on_stream(&ctrl->dp_ctrl); + else + DRM_ERROR("failed to enable DP link controller\n"); return ret; } @@ -1479,27 +1514,33 @@ static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl) return false; } dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested); + dp_ctrl_update_vx_px(ctrl); dp_link_send_test_response(ctrl->link); pattern_sent = dp_catalog_ctrl_read_phy_pattern(ctrl->catalog); switch (pattern_sent) { case MR_LINK_TRAINING1: - success = pattern_requested == - DP_LINK_QUAL_PATTERN_D10_2; + success = (pattern_requested == + DP_PHY_TEST_PATTERN_D10_2); break; case MR_LINK_SYMBOL_ERM: - success = (pattern_requested == - DP_LINK_QUAL_PATTERN_ERROR_RATE) - || (pattern_requested == - DP_LINK_QUAL_PATTERN_HBR2_EYE); + success = ((pattern_requested == + DP_PHY_TEST_PATTERN_ERROR_COUNT) || + (pattern_requested == + DP_PHY_TEST_PATTERN_CP2520)); break; case MR_LINK_PRBS7: - success = pattern_requested == DP_LINK_QUAL_PATTERN_PRBS7; + success = (pattern_requested == + DP_PHY_TEST_PATTERN_PRBS7); break; case MR_LINK_CUSTOM80: - success = pattern_requested == - DP_LINK_QUAL_PATTERN_80BIT_CUSTOM; + success = (pattern_requested == + DP_PHY_TEST_PATTERN_80BIT_CUSTOM); + break; + case MR_LINK_TRAINING4: + success = (pattern_requested == + DP_PHY_TEST_PATTERN_SEL_MASK); break; default: success = false; @@ -1531,12 +1572,12 @@ void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl) } } - if (sink_request & DP_LINK_STATUS_UPDATED) + if (sink_request & DP_LINK_STATUS_UPDATED) { if (dp_ctrl_link_maintenance(ctrl)) { - DRM_ERROR("LM failed: STATUS_UPDATED\n"); + DRM_ERROR("LM failed: TEST_LINK_TRAINING\n"); return; } - + } if (sink_request & DP_TEST_LINK_TRAINING) { dp_link_send_test_response(ctrl->link); @@ -1547,13 +1588,15 @@ void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl) } } -int dp_ctrl_on(struct dp_ctrl *dp_ctrl) +int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) { int rc = 0; struct dp_ctrl_private *ctrl; u32 rate = 0; - u32 link_train_max_retries = 10; + int link_train_max_retries = 5; u32 const phy_cts_pixel_clk_khz = 148500; + struct dp_cr_status cr; + unsigned int training_step; if (!dp_ctrl) return -EINVAL; @@ -1587,6 +1630,9 @@ int dp_ctrl_on(struct dp_ctrl *dp_ctrl) if (rc) return rc; + ctrl->link->phy_params.p_level = 0; + ctrl->link->phy_params.v_level = 0; + while (--link_train_max_retries && !atomic_read(&ctrl->dp_ctrl.aborted)) { rc = dp_ctrl_reinitialize_mainlink(ctrl); @@ -1595,19 +1641,125 @@ int dp_ctrl_on(struct dp_ctrl *dp_ctrl) rc); break; } - rc = dp_ctrl_setup_main_link(ctrl, true); - if (!rc) + + training_step = DP_TRAINING_NONE; + rc = dp_ctrl_setup_main_link(ctrl, &cr, &training_step); + if (rc == 0) { + /* training completed successfully */ break; - /* try with lower link rate */ - dp_ctrl_link_rate_down_shift(ctrl); + } else if (training_step == DP_TRAINING_1) { + /* link train_1 failed */ + rc = dp_ctrl_link_rate_down_shift(ctrl); + if (rc < 0) { /* already in RBR = 1.6G */ + if (cr.lane_0_1 & DP_LANE0_1_CR_DONE) { + /* + * some lanes are ready, + * reduce lane number + */ + rc = dp_ctrl_link_lane_down_shift(ctrl); + if (rc < 0) { /* lane == 1 already */ + /* end with failure */ + break; + } + } else { + /* end with failure */ + break; /* lane == 1 already */ + } + } + } else if (training_step == DP_TRAINING_2) { + /* link train_2 failed, lower lane rate */ + rc = dp_ctrl_link_lane_down_shift(ctrl); + if (rc < 0) { + /* end with failure */ + break; /* lane == 1 already */ + } + } } if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) - dp_ctrl_send_phy_test_pattern(ctrl); + return rc; + + /* stop txing train pattern */ + dp_ctrl_clear_training_pattern(ctrl); + + /* + * keep transmitting idle pattern until video ready + * to avoid main link from loss of sync + */ + if (rc == 0) /* link train successfully */ + dp_ctrl_push_idle(dp_ctrl); return rc; } +int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) +{ + u32 rate = 0; + int ret = 0; + bool mainlink_ready = false; + struct dp_ctrl_private *ctrl; + + if (!dp_ctrl) + return -EINVAL; + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + rate = ctrl->panel->link_info.rate; + + ctrl->link->link_params.rate = rate; + ctrl->link->link_params.num_lanes = ctrl->panel->link_info.num_lanes; + ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock; + + DRM_DEBUG_DP("rate=%d, num_lanes=%d, pixel_rate=%d\n", + ctrl->link->link_params.rate, + ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate); + + if (!dp_power_clk_status(ctrl->power, DP_CTRL_PM)) { /* link clk is off */ + ret = dp_ctrl_enable_mainlink_clocks(ctrl); + if (ret) { + DRM_ERROR("Failed to start link clocks. ret=%d\n", ret); + goto end; + } + } + + ret = dp_ctrl_enable_stream_clocks(ctrl); + if (ret) { + DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret); + goto end; + } + + if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) { + dp_ctrl_send_phy_test_pattern(ctrl); + return 0; + } + + /* + * Set up transfer unit values and set controller state to send + * video. + */ + dp_ctrl_configure_source_params(ctrl); + + dp_catalog_ctrl_config_msa(ctrl->catalog, + ctrl->link->link_params.rate, + ctrl->dp_ctrl.pixel_rate, dp_ctrl_use_fixed_nvid(ctrl)); + + reinit_completion(&ctrl->video_comp); + + dp_ctrl_setup_tr_unit(ctrl); + + dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO); + + ret = dp_ctrl_wait4video_ready(ctrl); + if (ret) + return ret; + + mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog); + DRM_DEBUG_DP("mainlink %s\n", mainlink_ready ? "READY" : "NOT READY"); + +end: + return ret; +} + int dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; @@ -1619,11 +1771,16 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); + dp_catalog_ctrl_reset(ctrl->catalog); + + ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, false); + if (ret) + DRM_ERROR("Failed to disable pixel clocks. ret=%d\n", ret); + ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, false); if (ret) { - DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); - return ret; + DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } DRM_DEBUG_DP("DP off done\n"); @@ -1674,7 +1831,6 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, init_completion(&ctrl->idle_comp); init_completion(&ctrl->video_comp); - mutex_init(&ctrl->push_idle_mutex); /* in parameters */ ctrl->parser = parser; diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 94713a0daff00..f60ba93c8678d 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -21,7 +21,8 @@ struct dp_ctrl { int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip); void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl); -int dp_ctrl_on(struct dp_ctrl *dp_ctrl); +int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); +int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl); int dp_ctrl_off(struct dp_ctrl *dp_ctrl); void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); void dp_ctrl_isr(struct dp_ctrl *dp_ctrl); diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 925c89720a16e..18ca5eac8e203 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -9,6 +9,7 @@ #include <linux/debugfs.h> #include <linux/component.h> #include <linux/of_irq.h> +#include <linux/delay.h> #include "msm_drv.h" #include "msm_kms.h" @@ -28,6 +29,52 @@ static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 +enum { + ISR_DISCONNECTED, + ISR_CONNECT_PENDING, + ISR_CONNECTED, + ISR_HPD_REPLUG_COUNT, + ISR_IRQ_HPD_PULSE_COUNT, + ISR_HPD_LO_GLITH_COUNT, +}; + +/* event thread connection state */ +enum { + ST_DISCONNECTED, + ST_CONNECT_PENDING, + ST_CONNECTED, + ST_DISCONNECT_PENDING, + ST_SUSPEND_PENDING, + ST_SUSPENDED, +}; + +enum { + EV_NO_EVENT, + /* hpd events */ + EV_HPD_INIT_SETUP, + EV_HPD_PLUG_INT, + EV_IRQ_HPD_INT, + EV_HPD_REPLUG_INT, + EV_HPD_UNPLUG_INT, + EV_USER_NOTIFICATION, + EV_CONNECT_PENDING_TIMEOUT, + EV_DISCONNECT_PENDING_TIMEOUT, +}; + +#define EVENT_TIMEOUT (HZ/10) /* 100ms */ +#define DP_EVENT_Q_MAX 8 + +#define DP_TIMEOUT_5_SECOND (5000/EVENT_TIMEOUT) +#define DP_TIMEOUT_NONE 0 + +#define WAIT_FOR_RESUME_TIMEOUT_JIFFIES (HZ / 2) + +struct dp_event { + u32 event_id; + u32 data; + u32 delay; +}; + struct dp_display_private { char *name; int irq; @@ -37,11 +84,9 @@ struct dp_display_private { bool power_on; bool hpd_irq_on; bool audio_supported; - atomic_t hpd_isr_status; struct platform_device *pdev; struct dentry *root; - struct completion notification_comp; struct dp_usbpd *usbpd; struct dp_parser *parser; @@ -52,12 +97,22 @@ struct dp_display_private { struct dp_link *link; struct dp_panel *panel; struct dp_ctrl *ctrl; + struct dp_debug *debug; struct dp_usbpd_cb usbpd_cb; struct dp_display_mode dp_mode; struct msm_dp dp_display; - struct delayed_work config_hpd_work; + /* event related only access by event thread */ + struct mutex event_mutex; + wait_queue_head_t event_q; + atomic_t hpd_state; + u32 event_pndx; + u32 event_gndx; + struct dp_event event_list[DP_EVENT_Q_MAX]; + spinlock_t event_lock; + + struct completion resume_comp; }; static const struct of_device_id dp_dt_match[] = { @@ -65,79 +120,58 @@ static const struct of_device_id dp_dt_match[] = { {} }; -static irqreturn_t dp_display_irq(int irq, void *dev_id) +static int dp_add_event(struct dp_display_private *dp_priv, u32 event, + u32 data, u32 delay) { - struct dp_display_private *dp = dev_id; - irqreturn_t ret = IRQ_HANDLED; - u32 hpd_isr_status; - - if (!dp) { - DRM_ERROR("invalid data\n"); - return IRQ_NONE; - } - - hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog); - - if (hpd_isr_status & DP_DP_HPD_INT_MASK) { - atomic_set(&dp->hpd_isr_status, hpd_isr_status); - ret = IRQ_WAKE_THREAD; + unsigned long flag; + struct dp_event *todo; + int pndx; + + spin_lock_irqsave(&dp_priv->event_lock, flag); + pndx = dp_priv->event_pndx + 1; + pndx %= DP_EVENT_Q_MAX; + if (pndx == dp_priv->event_gndx) { + pr_err("event_q is full: pndx=%d gndx=%d\n", + dp_priv->event_pndx, dp_priv->event_gndx); + spin_unlock_irqrestore(&dp_priv->event_lock, flag); + return -EPERM; } + todo = &dp_priv->event_list[dp_priv->event_pndx++]; + dp_priv->event_pndx %= DP_EVENT_Q_MAX; + todo->event_id = event; + todo->data = data; + todo->delay = delay; + wake_up(&dp_priv->event_q); + spin_unlock_irqrestore(&dp_priv->event_lock, flag); - /* DP controller isr */ - dp_ctrl_isr(dp->ctrl); - - /* DP aux isr */ - dp_aux_isr(dp->aux); - - return ret; + return 0; } -static irqreturn_t dp_display_hpd_isr_work(int irq, void *data) +static int dp_del_event(struct dp_display_private *dp_priv, u32 event) { - struct dp_display_private *dp; - struct dp_usbpd *hpd; - u32 isr = 0; - - dp = (struct dp_display_private *)data; - if (!dp) - return IRQ_NONE; - - isr = atomic_read(&dp->hpd_isr_status); - - /* reset to default */ - atomic_set(&dp->hpd_isr_status, 0); - - hpd = dp->usbpd; - if (!hpd) - return IRQ_NONE; - - if (isr & DP_DP_HPD_PLUG_INT_MASK && - isr & DP_DP_HPD_STATE_STATUS_CONNECTED) { - hpd->hpd_high = 1; - dp->usbpd_cb.configure(&dp->pdev->dev); - } else if (isr & DP_DP_HPD_UNPLUG_INT_MASK && - (isr & DP_DP_HPD_STATE_STATUS_MASK) == - DP_DP_HPD_STATE_STATUS_DISCONNECTED) { - - /* disable HPD plug interrupt until disconnect is done - */ - dp_catalog_hpd_config_intr(dp->catalog, - DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, - false); - - hpd->hpd_high = 0; - - /* We don't need separate work for disconnect as - * connect/attention interrupts are disabled - */ - dp->usbpd_cb.disconnect(&dp->pdev->dev); + unsigned long flag; + struct dp_event *todo; + u32 gndx; + + spin_lock_irqsave(&dp_priv->event_lock, flag); + if (dp_priv->event_pndx == dp_priv->event_gndx) { + spin_unlock_irqrestore(&dp_priv->event_lock, flag); + return -ENOENT; + } - dp_catalog_hpd_config_intr(dp->catalog, - DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, - true); + gndx = dp_priv->event_gndx; + while (dp_priv->event_pndx != gndx) { + todo = &dp_priv->event_list[gndx]; + if (todo->event_id == event) { + todo->event_id = EV_NO_EVENT; /* deleted */ + todo->delay = 0; + } + gndx++; + gndx %= DP_EVENT_Q_MAX; } + spin_unlock_irqrestore(&dp_priv->event_lock, flag); - return IRQ_HANDLED; + return 0; } static int dp_display_bind(struct device *dev, struct device *master, @@ -178,7 +212,6 @@ static int dp_display_bind(struct device *dev, struct device *master, DRM_ERROR("Power client create failed\n"); goto end; } - end: return rc; } @@ -237,11 +270,9 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, struct msm_drm_private *priv = dp->dp_display.drm_dev->dev_private; struct msm_kms *kms = priv->kms; - mutex_lock(&dp->dp_display.connect_mutex); if ((hpd && dp->dp_display.is_connected) || (!hpd && !dp->dp_display.is_connected)) { DRM_DEBUG_DP("HPD already %s\n", (hpd ? "on" : "off")); - mutex_unlock(&dp->dp_display.connect_mutex); return 0; } @@ -250,7 +281,6 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, dp->panel->video_test = false; dp->dp_display.is_connected = hpd; - reinit_completion(&dp->notification_comp); if (dp->dp_display.is_connected && dp->dp_display.encoder && !encoder_mode_set @@ -263,13 +293,6 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, dp_display_send_hpd_event(&dp->dp_display); - if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2)) { - pr_warn("%s timeout\n", hpd ? "connect" : "disconnect"); - mutex_unlock(&dp->dp_display.connect_mutex); - return -EINVAL; - } - - mutex_unlock(&dp->dp_display.connect_mutex); return 0; } @@ -278,23 +301,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) int rc = 0; struct edid *edid; - if (dp->link->psm_enabled) - goto notify; - dp->panel->max_dp_lanes = dp->parser->max_dp_lanes; rc = dp_panel_read_sink_caps(dp->panel, dp->dp_display.connector); if (rc) - goto notify; + goto end; dp_link_process_request(dp->link); - if (dp_display_is_sink_count_zero(dp)) { - DRM_DEBUG_DP("no downstream devices connected\n"); - rc = -EINVAL; - goto end; - } - edid = dp->panel->edid; dp->audio_supported = drm_detect_monitor_audio(edid); @@ -302,8 +316,15 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->dp_display.max_pclk_khz = DP_MAX_PIXEL_CLK_KHZ; dp->dp_display.max_dp_lanes = dp->parser->max_dp_lanes; -notify: - dp_display_send_hpd_notification(dp, true); + + rc = dp_ctrl_on_link(dp->ctrl); + if (rc) { + DRM_ERROR("failed to complete DP link training\n"); + goto end; + } + + dp_add_event(dp, EV_USER_NOTIFICATION, true, 0); + end: return rc; @@ -327,23 +348,6 @@ static void dp_display_host_init(struct dp_display_private *dp) dp->core_initialized = true; } -static void dp_display_host_deinit(struct dp_display_private *dp) -{ - if (!dp->core_initialized) { - DRM_DEBUG_DP("DP core already off\n"); - return; - } - - dp->core_initialized = false; -} - -static void dp_display_process_hpd_low(struct dp_display_private *dp) -{ - dp_display_send_hpd_notification(dp, false); - - dp_aux_deinit(dp->aux); -} - static int dp_display_usbpd_configure_cb(struct device *dev) { int rc = 0; @@ -364,18 +368,16 @@ static int dp_display_usbpd_configure_cb(struct device *dev) dp_display_host_init(dp); - if (dp->usbpd->hpd_high) - dp_display_process_hpd_high(dp); + /* + * set sink to normal operation mode -- D0 + * before dpcd read + */ + dp_link_psm_config(dp->link, &dp->panel->link_info, false); + rc = dp_display_process_hpd_high(dp); end: return rc; } -static void dp_display_clean(struct dp_display_private *dp) -{ - dp_ctrl_push_idle(dp->ctrl); - dp_ctrl_off(dp->ctrl); -} - static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; @@ -383,16 +385,8 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) dp = dev_get_drvdata(dev); - rc = dp_display_send_hpd_notification(dp, false); + dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); - /* if cable is disconnected, reset psm_enabled flag */ - if (!dp->usbpd->alt_mode_cfg_done) - dp->link->psm_enabled = false; - - if ((rc < 0) && dp->power_on) - dp_display_clean(dp); - - dp_display_host_deinit(dp); return rc; } @@ -407,11 +401,14 @@ static void dp_display_handle_video_request(struct dp_display_private *dp) } } -static int dp_display_handle_hpd_irq(struct dp_display_private *dp) +static int dp_display_handle_irq_hpd(struct dp_display_private *dp) { - if (dp->link->sink_request & DS_PORT_STATUS_CHANGED) { - dp_display_send_hpd_notification(dp, false); + u32 sink_request; + + sink_request = dp->link->sink_request; + if (sink_request & DS_PORT_STATUS_CHANGED) { + dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); if (dp_display_is_sink_count_zero(dp)) { DRM_DEBUG_DP("sink count is zero, nothing to do\n"); return 0; @@ -422,7 +419,8 @@ static int dp_display_handle_hpd_irq(struct dp_display_private *dp) dp_ctrl_handle_sink_request(dp->ctrl); - dp_display_handle_video_request(dp); + if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) + dp_display_handle_video_request(dp); return 0; } @@ -443,27 +441,174 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -ENODEV; } - if (dp->usbpd->hpd_irq) { - dp->hpd_irq_on = true; + /* check for any test request issued by sink */ + rc = dp_link_process_request(dp->link); + if (!rc) + dp_display_handle_irq_hpd(dp); - rc = dp_link_process_request(dp->link); - /* check for any test request issued by sink */ - if (!rc) - dp_display_handle_hpd_irq(dp); + return rc; +} - dp->hpd_irq_on = false; - goto end; +static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) +{ + struct dp_usbpd *hpd = dp->usbpd; + u32 state; + u32 tout = DP_TIMEOUT_5_SECOND; + int ret; + + if (!hpd) + return 0; + + mutex_lock(&dp->event_mutex); + + state = atomic_read(&dp->hpd_state); + if (state == ST_SUSPEND_PENDING) { + mutex_unlock(&dp->event_mutex); + return 0; } - if (!dp->usbpd->hpd_high) { - dp_display_process_hpd_low(dp); - goto end; + if (state == ST_CONNECT_PENDING || state == ST_CONNECTED) { + mutex_unlock(&dp->event_mutex); + return 0; } - if (dp->usbpd->alt_mode_cfg_done) - dp_display_process_hpd_high(dp); -end: - return rc; + if (state == ST_DISCONNECT_PENDING) { + /* wait until ST_DISCONNECTED */ + dp_add_event(dp, EV_HPD_PLUG_INT, 0, 1); /* delay = 1 */ + mutex_unlock(&dp->event_mutex); + return 0; + } + + if (state == ST_SUSPENDED) + tout = DP_TIMEOUT_NONE; + + atomic_set(&dp->hpd_state, ST_CONNECT_PENDING); + + hpd->hpd_high = 1; + + ret = dp_display_usbpd_configure_cb(&dp->pdev->dev); + if (ret) { /* failed */ + hpd->hpd_high = 0; + atomic_set(&dp->hpd_state, ST_DISCONNECTED); + } + + /* start sanity checking */ + dp_add_event(dp, EV_CONNECT_PENDING_TIMEOUT, 0, tout); + + mutex_unlock(&dp->event_mutex); + + /* uevent will complete connection part */ + return 0; +}; + +static int dp_display_enable(struct dp_display_private *dp, u32 data); +static int dp_display_disable(struct dp_display_private *dp, u32 data); + +static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data) +{ + u32 state; + + mutex_lock(&dp->event_mutex); + + state = atomic_read(&dp->hpd_state); + if (state == ST_CONNECT_PENDING) { + dp_display_enable(dp, 0); + atomic_set(&dp->hpd_state, ST_CONNECTED); + } + + mutex_unlock(&dp->event_mutex); + + return 0; +} + +static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) +{ + struct dp_usbpd *hpd = dp->usbpd; + u32 state; + + if (!hpd) + return 0; + + mutex_lock(&dp->event_mutex); + + state = atomic_read(&dp->hpd_state); + if (state == ST_SUSPEND_PENDING) { + mutex_unlock(&dp->event_mutex); + return 0; + } + + if (state == ST_DISCONNECT_PENDING || state == ST_DISCONNECTED) { + mutex_unlock(&dp->event_mutex); + return 0; + } + + if (state == ST_CONNECT_PENDING) { + /* wait until CONNECTED */ + dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 1); /* delay = 1 */ + mutex_unlock(&dp->event_mutex); + return 0; + } + + atomic_set(&dp->hpd_state, ST_DISCONNECT_PENDING); + + /* disable HPD plug interrupt until disconnect is done */ + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK + | DP_DP_IRQ_HPD_INT_MASK, false); + + hpd->hpd_high = 0; + + /* + * We don't need separate work for disconnect as + * connect/attention interrupts are disabled + */ + dp_display_usbpd_disconnect_cb(&dp->pdev->dev); + + /* start sanity checking */ + dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND); + + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | + DP_DP_IRQ_HPD_INT_MASK, true); + + /* uevent will complete disconnection part */ + mutex_unlock(&dp->event_mutex); + return 0; +} + +static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data) +{ + u32 state; + + mutex_lock(&dp->event_mutex); + + state = atomic_read(&dp->hpd_state); + if (state == ST_DISCONNECT_PENDING) { + dp_display_disable(dp, 0); + atomic_set(&dp->hpd_state, ST_DISCONNECTED); + } + + mutex_unlock(&dp->event_mutex); + + return 0; +} + +static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) +{ + u32 state; + + mutex_lock(&dp->event_mutex); + + /* irq_hpd can happen at either connected or disconnected state */ + state = atomic_read(&dp->hpd_state); + if (state == ST_SUSPEND_PENDING) { + mutex_unlock(&dp->event_mutex); + return 0; + } + + dp_display_usbpd_attention_cb(&dp->pdev->dev); + + mutex_unlock(&dp->event_mutex); + + return 0; } static void dp_display_deinit_sub_modules(struct dp_display_private *dp) @@ -599,106 +744,39 @@ static int dp_display_prepare(struct msm_dp *dp) return 0; } -static void dp_display_dump(struct msm_dp *dp_display) -{ - struct dp_display_private *dp; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - dp_panel_dump_regs(dp->panel); -} - -static int dp_display_enable(struct msm_dp *dp_display) +static int dp_display_enable(struct dp_display_private *dp, u32 data) { int rc = 0; - struct dp_display_private *dp; - bool dump_dp = false; - - dp = container_of(dp_display, struct dp_display_private, dp_display); if (dp->power_on) { DRM_DEBUG_DP("Link already setup, return\n"); return 0; } - rc = dp_ctrl_on(dp->ctrl); + rc = dp_ctrl_on_stream(dp->ctrl); if (!rc) dp->power_on = true; - if (dump_dp != false) - dp_display_dump(dp_display); - + /* complete resume_comp regardless it is armed or not */ + complete(&dp->resume_comp); return rc; } static int dp_display_post_enable(struct msm_dp *dp_display) { - struct dp_display_private *dp; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - complete_all(&dp->notification_comp); - return 0; -} - -static int dp_display_pre_disable(struct msm_dp *dp_display) -{ - struct dp_display_private *dp; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (dp->usbpd->alt_mode_cfg_done) - dp_link_psm_config(dp->link, &dp->panel->link_info, true); - - dp_ctrl_push_idle(dp->ctrl); return 0; } -static int dp_display_disable(struct msm_dp *dp_display) +static int dp_display_disable(struct dp_display_private *dp, u32 data) { - struct dp_display_private *dp; - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - if (!dp->power_on || !dp->core_initialized) + if (!dp->power_on) return -EINVAL; dp_ctrl_off(dp->ctrl); - dp->power_on = false; - - complete_all(&dp->notification_comp); - return 0; -} - -int dp_display_request_irq(struct msm_dp *dp_display) -{ - int rc = 0; - struct dp_display_private *dp; - - if (!dp_display) { - DRM_ERROR("invalid input\n"); - return -EINVAL; - } - - dp = container_of(dp_display, struct dp_display_private, dp_display); - - dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); - if (dp->irq < 0) { - rc = dp->irq; - DRM_ERROR("failed to get irq: %d\n", rc); - return rc; - } + dp->core_initialized = false; - rc = devm_request_threaded_irq(&dp->pdev->dev, dp->irq, - dp_display_irq, dp_display_hpd_isr_work, - IRQF_TRIGGER_HIGH, "dp_display_isr", dp); - if (rc < 0) { - DRM_ERROR("failed to request IRQ%u: %d\n", - dp->irq, rc); - return rc; - } - disable_irq(dp->irq); + dp->power_on = false; return 0; } @@ -783,6 +861,192 @@ int dp_display_get_test_bpp(struct msm_dp *dp) dp_display->link->test_video.test_bit_depth); } +static void dp_display_config_hpd(struct dp_display_private *dp) +{ + + dp_display_host_init(dp); + dp_catalog_ctrl_hpd_config(dp->catalog); + + /* Enable interrupt first time + * we are leaving dp clocks on during disconnect + * and never disable interrupt + */ + enable_irq(dp->irq); +} + +static int hpd_event_thread(void *data) +{ + struct dp_display_private *dp_priv; + unsigned long flag; + struct dp_event *todo; + int timeout_mode = 0; + + dp_priv = (struct dp_display_private *)data; + + while (1) { + if (timeout_mode) { + wait_event_timeout(dp_priv->event_q, + (dp_priv->event_pndx == dp_priv->event_gndx), + EVENT_TIMEOUT); + } else { + wait_event_timeout(dp_priv->event_q, + (dp_priv->event_pndx != dp_priv->event_gndx), + EVENT_TIMEOUT); + } + spin_lock_irqsave(&dp_priv->event_lock, flag); + todo = &dp_priv->event_list[dp_priv->event_gndx]; + if (todo->delay) { + struct dp_event *todo_next; + + dp_priv->event_gndx++; + dp_priv->event_gndx %= DP_EVENT_Q_MAX; + + /* re enter delay event into q */ + todo_next = &dp_priv->event_list[dp_priv->event_pndx++]; + dp_priv->event_pndx %= DP_EVENT_Q_MAX; + todo_next->event_id = todo->event_id; + todo_next->data = todo->data; + todo_next->delay = todo->delay - 1; + + /* clean up older event */ + todo->event_id = EV_NO_EVENT; + todo->delay = 0; + + /* switch to timeout mode */ + timeout_mode = 1; + spin_unlock_irqrestore(&dp_priv->event_lock, flag); + continue; + } + + /* timeout with no events in q */ + if (dp_priv->event_pndx == dp_priv->event_gndx) { + spin_unlock_irqrestore(&dp_priv->event_lock, flag); + continue; + } + + dp_priv->event_gndx++; + dp_priv->event_gndx %= DP_EVENT_Q_MAX; + timeout_mode = 0; + spin_unlock_irqrestore(&dp_priv->event_lock, flag); + + switch (todo->event_id) { + case EV_HPD_INIT_SETUP: + dp_display_config_hpd(dp_priv); + break; + case EV_HPD_PLUG_INT: + dp_hpd_plug_handle(dp_priv, todo->data); + break; + case EV_HPD_UNPLUG_INT: + dp_hpd_unplug_handle(dp_priv, todo->data); + break; + case EV_IRQ_HPD_INT: + dp_irq_hpd_handle(dp_priv, todo->data); + break; + case EV_HPD_REPLUG_INT: + /* do nothing */ + break; + case EV_USER_NOTIFICATION: + dp_display_send_hpd_notification(dp_priv, + todo->data); + break; + case EV_CONNECT_PENDING_TIMEOUT: + dp_connect_pending_timeout(dp_priv, + todo->data); + break; + case EV_DISCONNECT_PENDING_TIMEOUT: + dp_disconnect_pending_timeout(dp_priv, + todo->data); + break; + default: + break; + } + } + + return 0; +} + +static void dp_hpd_event_setup(struct dp_display_private *dp_priv) +{ + init_waitqueue_head(&dp_priv->event_q); + spin_lock_init(&dp_priv->event_lock); + + kthread_run(hpd_event_thread, dp_priv, "dp_hpd_handler"); +} + +static irqreturn_t dp_display_irq_handler(int irq, void *dev_id) +{ + struct dp_display_private *dp = dev_id; + irqreturn_t ret = IRQ_HANDLED; + u32 hpd_isr_status; + + if (!dp) { + DRM_ERROR("invalid data\n"); + return IRQ_NONE; + } + + hpd_isr_status = dp_catalog_hpd_get_intr_status(dp->catalog); + + if (hpd_isr_status & 0x0F) { + /* hpd related interrupts */ + if (hpd_isr_status & DP_DP_HPD_PLUG_INT_MASK || + hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) { + dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0); + } + + if (hpd_isr_status & DP_DP_IRQ_HPD_INT_MASK) { + /* delete connect pending event first */ + dp_del_event(dp, EV_CONNECT_PENDING_TIMEOUT); + dp_add_event(dp, EV_IRQ_HPD_INT, 0, 0); + } + + if (hpd_isr_status & DP_DP_HPD_REPLUG_INT_MASK) + dp_add_event(dp, EV_HPD_REPLUG_INT, 0, 0); + + if (hpd_isr_status & DP_DP_HPD_UNPLUG_INT_MASK) + dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0); + } + + /* DP controller isr */ + dp_ctrl_isr(dp->ctrl); + + /* DP aux isr */ + dp_aux_isr(dp->aux); + + return ret; +} + +int dp_display_request_irq(struct msm_dp *dp_display) +{ + int rc = 0; + struct dp_display_private *dp; + + if (!dp_display) { + DRM_ERROR("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0); + if (dp->irq < 0) { + rc = dp->irq; + DRM_ERROR("failed to get irq: %d\n", rc); + return rc; + } + + rc = devm_request_irq(&dp->pdev->dev, dp->irq, + dp_display_irq_handler, + IRQF_TRIGGER_HIGH, "dp_display_isr", dp); + if (rc < 0) { + DRM_ERROR("failed to request IRQ%u: %d\n", + dp->irq, rc); + return rc; + } + disable_irq(dp->irq); + + return 0; +} + static int dp_display_probe(struct platform_device *pdev) { int rc = 0; @@ -797,8 +1061,6 @@ static int dp_display_probe(struct platform_device *pdev) if (!dp) return -ENOMEM; - init_completion(&dp->notification_comp); - dp->pdev = pdev; dp->name = "drm_dp"; @@ -810,7 +1072,8 @@ static int dp_display_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dp); - mutex_init(&dp->dp_display.connect_mutex); + mutex_init(&dp->event_mutex); + init_completion(&dp->resume_comp); g_dp_display = &dp->dp_display; rc = component_add(&pdev->dev, &dp_display_comp_ops); @@ -843,6 +1106,16 @@ static int dp_pm_resume(struct device *dev) static int dp_pm_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); + struct dp_display_private *dp = platform_get_drvdata(pdev); + + if (!dp) { + DRM_ERROR("DP driver bind failed. Invalid driver data\n"); + return -EINVAL; + } + + atomic_set(&dp->hpd_state, ST_SUSPENDED); + return 0; } @@ -890,26 +1163,6 @@ void __exit msm_dp_unregister(void) platform_driver_unregister(&dp_display_driver); } -static void dp_display_config_hpd_work(struct work_struct *work) -{ - struct dp_display_private *dp; - struct delayed_work *dw = to_delayed_work(work); - - dp = container_of(dw, struct dp_display_private, config_hpd_work); - - dp_display_host_init(dp); - dp_catalog_ctrl_hpd_config(dp->catalog); - - /* set default to 0 */ - atomic_set(&dp->hpd_isr_status, 0); - - /* Enable interrupt first time - * we are leaving dp clocks on during disconnect - * and never disable interrupt - */ - enable_irq(dp->irq); -} - void msm_dp_irq_postinstall(struct msm_dp *dp_display) { struct dp_display_private *dp; @@ -919,8 +1172,9 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp = container_of(dp_display, struct dp_display_private, dp_display); - INIT_DELAYED_WORK(&dp->config_hpd_work, dp_display_config_hpd_work); - queue_delayed_work(system_wq, &dp->config_hpd_work, HZ * 10); + dp_hpd_event_setup(dp); + + dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); } int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, @@ -956,10 +1210,24 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, return 0; } +static int dp_display_wait4resume_done(struct dp_display_private *dp) +{ + int ret = 0; + + reinit_completion(&dp->resume_comp); + if (!wait_for_completion_timeout(&dp->resume_comp, + WAIT_FOR_RESUME_TIMEOUT_JIFFIES)) { + DRM_ERROR("wait4resume_done timedout\n"); + ret = -ETIMEDOUT; + } + return ret; +} + int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder) { int rc = 0; struct dp_display_private *dp_display; + u32 state; dp_display = container_of(dp, struct dp_display_private, dp_display); if (!dp_display->dp_mode.drm_mode.clock) { @@ -967,54 +1235,96 @@ int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder) return -EINVAL; } + mutex_lock(&dp_display->event_mutex); + rc = dp_display_set_mode(dp, &dp_display->dp_mode); if (rc) { DRM_ERROR("Failed to perform a mode set, rc=%d\n", rc); + mutex_unlock(&dp_display->event_mutex); return rc; } rc = dp_display_prepare(dp); if (rc) { DRM_ERROR("DP display prepare failed, rc=%d\n", rc); + mutex_unlock(&dp_display->event_mutex); return rc; } - rc = dp_display_enable(dp); - if (rc) { - DRM_ERROR("DP display enable failed, rc=%d\n", rc); - dp_display_unprepare(dp); - return rc; + state = atomic_read(&dp_display->hpd_state); + if (state == ST_SUSPENDED) { + /* start link training */ + dp_add_event(dp_display, EV_HPD_PLUG_INT, 0, 0); + mutex_unlock(&dp_display->event_mutex); + + /* wait until dp interface is up */ + goto resume_done; } + dp_display_enable(dp_display, 0); + rc = dp_display_post_enable(dp); if (rc) { DRM_ERROR("DP display post enable failed, rc=%d\n", rc); - dp_display_disable(dp); + dp_display_disable(dp_display, 0); dp_display_unprepare(dp); } + + dp_del_event(dp_display, EV_CONNECT_PENDING_TIMEOUT); + + if (state == ST_SUSPEND_PENDING) + dp_add_event(dp_display, EV_IRQ_HPD_INT, 0, 0); + + /* completed connection */ + atomic_set(&dp_display->hpd_state, ST_CONNECTED); + + mutex_unlock(&dp_display->event_mutex); + return rc; + +resume_done: + dp_display_wait4resume_done(dp_display); + return rc; +} + +int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder *encoder) +{ + struct dp_display_private *dp_display; + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + dp_ctrl_push_idle(dp_display->ctrl); + + return 0; } int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder) { int rc = 0; + u32 state; + struct dp_display_private *dp_display; - rc = dp_display_pre_disable(dp); - if (rc) { - DRM_ERROR("DP display pre disable failed, rc=%d\n", rc); - return rc; - } + dp_display = container_of(dp, struct dp_display_private, dp_display); - rc = dp_display_disable(dp); - if (rc) { - DRM_ERROR("DP display disable failed, rc=%d\n", rc); - return rc; - } + mutex_lock(&dp_display->event_mutex); + + dp_display_disable(dp_display, 0); rc = dp_display_unprepare(dp); if (rc) DRM_ERROR("DP display unprepare failed, rc=%d\n", rc); + dp_del_event(dp_display, EV_DISCONNECT_PENDING_TIMEOUT); + + state = atomic_read(&dp_display->hpd_state); + if (state == ST_DISCONNECT_PENDING) { + /* completed disconnection */ + atomic_set(&dp_display->hpd_state, ST_DISCONNECTED); + } else { + atomic_set(&dp_display->hpd_state, ST_SUSPEND_PENDING); + } + + mutex_unlock(&dp_display->event_mutex); return rc; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 4c53ed55d1cca..2f2d1279dfc65 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -13,7 +13,6 @@ struct msm_dp { struct drm_connector *connector; struct drm_encoder *encoder; bool is_connected; - struct mutex connect_mutex; u32 max_pclk_khz; u32 max_dp_lanes; }; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index e58906f4ae1e2..764f4b81017ed 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -58,7 +58,6 @@ static int dp_connector_get_modes(struct drm_connector *connector) if (!dp_mode) return 0; - mutex_lock(&dp->connect_mutex); /* pluggable case assumes EDID is read when HPD */ if (dp->is_connected) { /* @@ -71,7 +70,6 @@ static int dp_connector_get_modes(struct drm_connector *connector) if (rc <= 0) { DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc); kfree(dp_mode); - mutex_unlock(&dp->connect_mutex); return rc; } if (dp_mode->drm_mode.clock) { /* valid DP mode */ @@ -83,7 +81,6 @@ static int dp_connector_get_modes(struct drm_connector *connector) drm_mode.hdisplay, drm_mode.vdisplay); kfree(dp_mode); - mutex_unlock(&dp->connect_mutex); return 0; } drm_mode_probed_add(connector, m); @@ -91,7 +88,6 @@ static int dp_connector_get_modes(struct drm_connector *connector) } else { DRM_DEBUG_DP("No sink connected\n"); } - mutex_unlock(&dp->connect_mutex); kfree(dp_mode); return rc; } diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.c b/drivers/gpu/drm/msm/dp/dp_hpd.c index 5b08ce580702b..5b8fe32022b5f 100644 --- a/drivers/gpu/drm/msm/dp/dp_hpd.c +++ b/drivers/gpu/drm/msm/dp/dp_hpd.c @@ -24,7 +24,7 @@ struct dp_hpd_private { struct dp_usbpd dp_usbpd; }; -static int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd) +int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd) { int rc = 0; struct dp_hpd_private *hpd_priv; diff --git a/drivers/gpu/drm/msm/dp/dp_hpd.h b/drivers/gpu/drm/msm/dp/dp_hpd.h index c0178524bec71..5bc5bb64680fb 100644 --- a/drivers/gpu/drm/msm/dp/dp_hpd.h +++ b/drivers/gpu/drm/msm/dp/dp_hpd.h @@ -75,5 +75,6 @@ struct dp_usbpd *dp_hpd_get(struct device *dev, struct dp_usbpd_cb *cb); int dp_hpd_register(struct dp_usbpd *dp_usbpd); void dp_hpd_unregister(struct dp_usbpd *dp_usbpd); +int dp_hpd_connect(struct dp_usbpd *dp_usbpd, bool hpd); #endif /* _DP_HPD_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 9156a7f3dbf88..3cbae92deff0b 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -38,7 +38,6 @@ struct dp_link_private { struct dp_link dp_link; struct dp_link_request request; - struct mutex test_response_mutex; struct mutex psm_mutex; u8 link_status[DP_LINK_STATUS_SIZE]; }; @@ -580,17 +579,18 @@ static int dp_link_parse_phy_test_params(struct dp_link_private *link) return rlen; } - link->dp_link.phy_params.phy_test_pattern_sel = data; + link->dp_link.phy_params.phy_test_pattern_sel = data & 0x07; DRM_DEBUG_DP("phy_test_pattern_sel = 0x%x\n", data); switch (data) { - case DP_LINK_QUAL_PATTERN_DISABLE: - case DP_LINK_QUAL_PATTERN_D10_2: - case DP_LINK_QUAL_PATTERN_ERROR_RATE: - case DP_LINK_QUAL_PATTERN_PRBS7: - case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM: - case DP_LINK_QUAL_PATTERN_HBR2_EYE: + case DP_PHY_TEST_PATTERN_SEL_MASK: + case DP_PHY_TEST_PATTERN_NONE: + case DP_PHY_TEST_PATTERN_D10_2: + case DP_PHY_TEST_PATTERN_ERROR_COUNT: + case DP_PHY_TEST_PATTERN_PRBS7: + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: + case DP_PHY_TEST_PATTERN_CP2520: return 0; default: return -EINVAL; @@ -661,7 +661,6 @@ static int dp_link_parse_request(struct dp_link_private *link) DRM_DEBUG_DP("Test:(0x%x) requested\n", data); link->request.test_requested = data; - if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) { ret = dp_link_parse_phy_test_params(link); if (ret) @@ -789,10 +788,8 @@ bool dp_link_send_test_response(struct dp_link *dp_link) link = container_of(dp_link, struct dp_link_private, dp_link); - mutex_lock(&link->test_response_mutex); ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_RESPONSE, dp_link->test_response); - mutex_unlock(&link->test_response_mutex); return ret == 1; } @@ -1028,11 +1025,9 @@ int dp_link_process_request(struct dp_link *dp_link) link = container_of(dp_link, struct dp_link_private, dp_link); - mutex_lock(&link->test_response_mutex); dp_link_reset_data(link); dp_link_parse_sink_status_field(link); - mutex_unlock(&link->test_response_mutex); if (link->request.test_requested == DP_TEST_LINK_EDID_READ) { dp_link->sink_request |= DP_TEST_LINK_EDID_READ; @@ -1206,7 +1201,6 @@ struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux) link->dev = dev; link->aux = aux; - mutex_init(&link->test_response_mutex); mutex_init(&link->psm_mutex); dp_link = &link->dp_link; diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 5ac4b017da8fd..7cdf37c525d85 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -8,8 +8,6 @@ #include <drm/drm_connector.h> #include <drm/drm_edid.h> -#define DP_MAX_DS_PORT_COUNT 1 - struct dp_panel_private { struct device *dev; struct dp_panel dp_panel; @@ -23,26 +21,32 @@ struct dp_panel_private { static int dp_panel_read_dpcd(struct dp_panel *dp_panel) { int rc = 0; - size_t rlen; + size_t len; + ssize_t rlen; struct dp_panel_private *panel; struct dp_link_info *link_info; u8 *dpcd, major = 0, minor = 0, temp; - u32 dfp_count = 0, offset = DP_DPCD_REV; + u32 offset = DP_DPCD_REV; dpcd = dp_panel->dpcd; panel = container_of(dp_panel, struct dp_panel_private, dp_panel); link_info = &dp_panel->link_info; - rlen = drm_dp_dpcd_read(panel->aux, - DP_TRAINING_AUX_RD_INTERVAL, &temp, 1); - if (rlen < 0) { - DRM_ERROR("err reading DP_TRAINING_AUX_RD_INTERVAL,rlen=%zd\n", - rlen); - rc = -EINVAL; + rlen = drm_dp_dpcd_read(panel->aux, offset, + dpcd, (DP_RECEIVER_CAP_SIZE + 1)); + if (rlen < (DP_RECEIVER_CAP_SIZE + 1)) { + DRM_ERROR("dpcd read failed, rlen=%zd\n", rlen); + if (rlen == -ETIMEDOUT) + rc = rlen; + else + rc = -EINVAL; + goto end; } + temp = dpcd[DP_TRAINING_AUX_RD_INTERVAL]; + /* check for EXTENDED_RECEIVER_CAPABILITY_FIELD_PRESENT */ if (temp & BIT(7)) { DRM_DEBUG_DP("using EXTENDED_RECEIVER_CAPABILITY_FIELD\n"); @@ -61,9 +65,6 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel) goto end; } - print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ", - DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false); - link_info->revision = dpcd[DP_DPCD_REV]; major = (link_info->revision >> 4) & 0x0f; minor = link_info->revision & 0x0f; @@ -85,14 +86,23 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel) if (drm_dp_enhanced_frame_cap(dpcd)) link_info->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; - dfp_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & - DP_DOWN_STREAM_PORT_COUNT; + dp_panel->dfp_present = dpcd[DP_DOWNSTREAMPORT_PRESENT]; + dp_panel->dfp_present &= DP_DWN_STRM_PORT_PRESENT; - if (dfp_count > DP_MAX_DS_PORT_COUNT) { - DRM_ERROR("DS port count %d greater that max (%d) supported\n", - dfp_count, DP_MAX_DS_PORT_COUNT); - return -EINVAL; + if (dp_panel->dfp_present && (dpcd[DP_DPCD_REV] > 0x10)) { + dp_panel->ds_port_cnt = dpcd[DP_DOWN_STREAM_PORT_COUNT]; + dp_panel->ds_port_cnt &= DP_PORT_COUNT_MASK; + len = DP_DOWNSTREAM_PORTS * DP_DOWNSTREAM_CAP_SIZE; + + rlen = drm_dp_dpcd_read(panel->aux, + DP_DOWNSTREAM_PORT_0, dp_panel->ds_cap_info, len); + if (rlen < len) { + DRM_ERROR("ds port status failed, rlen=%zd\n", rlen); + rc = -EINVAL; + goto end; + } } + end: return rc; } @@ -185,6 +195,7 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, struct drm_connector *connector) { int rc = 0, bw_code; + int rlen, count; struct dp_panel_private *panel; if (!dp_panel || !connector) { @@ -202,11 +213,19 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, DRM_ERROR("read dpcd failed %d\n", rc); return rc; } - rc = drm_dp_read_desc(panel->aux, &dp_panel->desc, - drm_dp_is_branch(dp_panel->dpcd)); - if (rc) { - DRM_ERROR("read sink/branch descriptor failed %d\n", rc); - return rc; + + if (dp_panel->dfp_present) { + rlen = drm_dp_dpcd_read(panel->aux, DP_SINK_COUNT, + &count, 1); + if (rlen == 1) { + count = DP_GET_SINK_COUNT(count); + if (!count) { + DRM_ERROR("no downstream ports connected\n"); + panel->link->sink_count = 0; + rc = -ENOTCONN; + goto end; + } + } } kfree(dp_panel->edid); @@ -216,7 +235,12 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, &panel->aux->ddc); if (!dp_panel->edid) { DRM_ERROR("panel edid read failed\n"); - return -EINVAL; + + /* fail safe edid */ + mutex_lock(&connector->dev->mode_config.mutex); + if (drm_add_modes_noedid(connector, 640, 480)) + drm_set_preferred_mode(connector, 640, 480); + mutex_unlock(&connector->dev->mode_config.mutex); } if (panel->aux_cfg_update_done) { @@ -231,8 +255,8 @@ int dp_panel_read_sink_caps(struct dp_panel *dp_panel, } panel->aux_cfg_update_done = false; } - - return 0; +end: + return rc; } u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h index f6f417eef2e9c..9023e5bb4b8b2 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.h +++ b/drivers/gpu/drm/msm/dp/dp_panel.h @@ -14,8 +14,10 @@ struct edid; -#define DP_MAX_DOWNSTREAM_PORTS 0x10 -#define DPRX_EXTENDED_DPCD_FIELD 0x2200 +#define DPRX_EXTENDED_DPCD_FIELD 0x2200 + +#define DP_DOWNSTREAM_PORTS 4 +#define DP_DOWNSTREAM_CAP_SIZE 4 struct dp_display_mode { struct drm_display_mode drm_mode; @@ -35,6 +37,9 @@ struct dp_panel_in { struct dp_panel { /* dpcd raw data */ u8 dpcd[DP_RECEIVER_CAP_SIZE + 1]; + u8 ds_cap_info[DP_DOWNSTREAM_PORTS * DP_DOWNSTREAM_CAP_SIZE]; + u32 ds_port_cnt; + u32 dfp_present; struct dp_link_info link_info; struct drm_dp_desc desc; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 1e480d01ddbb3..255a800535d57 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -103,11 +103,12 @@ static inline bool dp_parser_check_prefix(const char *clk_prefix, static int dp_parser_init_clk_data(struct dp_parser *parser) { int num_clk, i, rc; - int core_clk_count = 0, ctrl_clk_count = 0; + int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; const char *clk_name; struct device *dev = &parser->pdev->dev; struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; + struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; num_clk = of_property_count_strings(dev->of_node, "clock-names"); if (num_clk <= 0) { @@ -128,7 +129,7 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) ctrl_clk_count++; if (dp_parser_check_prefix("stream", clk_name)) - ctrl_clk_count++; + stream_clk_count++; } /* Initialize the CORE power module */ @@ -159,6 +160,21 @@ static int dp_parser_init_clk_data(struct dp_parser *parser) return -EINVAL; } + /* Initialize the STREAM power module */ + if (stream_clk_count == 0) { + DRM_ERROR("no stream (pixel) clocks are defined\n"); + return -EINVAL; + } + + stream_power->num_clk = stream_clk_count; + stream_power->clk_config = devm_kzalloc(dev, + sizeof(struct dss_clk) * stream_power->num_clk, + GFP_KERNEL); + if (!stream_power->clk_config) { + stream_power->num_clk = 0; + return -EINVAL; + } + return 0; } @@ -166,15 +182,13 @@ static int dp_parser_clock(struct dp_parser *parser) { int rc = 0, i = 0; int num_clk = 0; - int core_clk_index = 0, ctrl_clk_index = 0; - int core_clk_count = 0, ctrl_clk_count = 0; + int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0; + int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; const char *clk_name; struct device *dev = &parser->pdev->dev; struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; - - core_power = &parser->mp[DP_CORE_PM]; - ctrl_power = &parser->mp[DP_CTRL_PM]; + struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; rc = dp_parser_init_clk_data(parser); if (rc) { @@ -184,8 +198,9 @@ static int dp_parser_clock(struct dp_parser *parser) core_clk_count = core_power->num_clk; ctrl_clk_count = ctrl_power->num_clk; + stream_clk_count = stream_power->num_clk; - num_clk = core_clk_count + ctrl_clk_count; + num_clk = core_clk_count + ctrl_clk_count + stream_clk_count; for (i = 0; i < num_clk; i++) { rc = of_property_read_string_index(dev->of_node, "clock-names", @@ -201,14 +216,19 @@ static int dp_parser_clock(struct dp_parser *parser) strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); clk->type = DSS_CLK_AHB; core_clk_index++; - } else if ((dp_parser_check_prefix("ctrl", clk_name) || - dp_parser_check_prefix("stream", clk_name)) && + } else if (dp_parser_check_prefix("stream", clk_name) && + stream_clk_index < stream_clk_count) { + struct dss_clk *clk = + &stream_power->clk_config[stream_clk_index]; + strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); + clk->type = DSS_CLK_PCLK; + stream_clk_index++; + } else if (dp_parser_check_prefix("ctrl", clk_name) && ctrl_clk_index < ctrl_clk_count) { struct dss_clk *clk = &ctrl_power->clk_config[ctrl_clk_index]; strlcpy(clk->clk_name, clk_name, sizeof(clk->clk_name)); ctrl_clk_index++; - if (dp_parser_check_prefix("ctrl_link", clk_name) || dp_parser_check_prefix("stream_pixel", clk_name)) clk->type = DSS_CLK_PCLK; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index aa0380b6a2806..841e776124c4e 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -19,6 +19,7 @@ enum dp_pm_type { DP_CORE_PM, DP_CTRL_PM, + DP_STREAM_PM, DP_PHY_PM, DP_MAX_PM }; @@ -33,6 +34,7 @@ static inline const char *dp_parser_pm_name(enum dp_pm_type module) switch (module) { case DP_CORE_PM: return "DP_CORE_PM"; case DP_CTRL_PM: return "DP_CTRL_PM"; + case DP_STREAM_PM: return "DP_STREAM_PM"; case DP_PHY_PM: return "DP_PHY_PM"; default: return "???"; } diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 8b0a276d34a46..34fdb2e5d644b 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -95,11 +95,12 @@ static int dp_power_regulator_init(struct dp_power_private *power) static int dp_power_clk_init(struct dp_power_private *power) { int rc = 0; - struct dss_module_power *core, *ctrl; + struct dss_module_power *core, *ctrl, *stream; struct device *dev = &power->pdev->dev; core = &power->parser->mp[DP_CORE_PM]; ctrl = &power->parser->mp[DP_CTRL_PM]; + stream = &power->parser->mp[DP_STREAM_PM]; if (power->parser->pll && power->parser->pll->get_provider) { rc = power->parser->pll->get_provider(power->parser->pll, @@ -126,21 +127,33 @@ static int dp_power_clk_init(struct dp_power_private *power) return -ENODEV; } + rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk); + if (rc) { + DRM_ERROR("failed to get %s clk. err=%d\n", + dp_parser_pm_name(DP_CTRL_PM), rc); + msm_dss_put_clk(core->clk_config, core->num_clk); + return -ENODEV; + } + return 0; } static int dp_power_clk_deinit(struct dp_power_private *power) { - struct dss_module_power *core, *ctrl; + struct dss_module_power *core, *ctrl, *stream; core = &power->parser->mp[DP_CORE_PM]; ctrl = &power->parser->mp[DP_CTRL_PM]; + stream = &power->parser->mp[DP_STREAM_PM]; - if (!core || !ctrl) + if (!core || !ctrl || !stream) { + DRM_ERROR("invalid power_data\n"); return -EINVAL; + } msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk); msm_dss_put_clk(core->clk_config, core->num_clk); + msm_dss_put_clk(stream->clk_config, stream->num_clk); return 0; } @@ -167,6 +180,20 @@ static int dp_power_clk_set_rate(struct dp_power_private *power, return 0; } +int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) +{ + if (pm_type == DP_CORE_PM) + return dp_power->core_clks_on; + + if (pm_type == DP_CTRL_PM) + return dp_power->link_clks_on; + + if (pm_type == DP_STREAM_PM) + return dp_power->stream_clks_on; + + return 0; +} + int dp_power_clk_enable(struct dp_power *dp_power, enum dp_pm_type pm_type, bool enable) { @@ -175,7 +202,8 @@ int dp_power_clk_enable(struct dp_power *dp_power, power = container_of(dp_power, struct dp_power_private, dp_power); - if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM) { + if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM && + pm_type != DP_STREAM_PM) { DRM_ERROR("unsupported power module: %s\n", dp_parser_pm_name(pm_type)); return -EINVAL; @@ -192,6 +220,11 @@ int dp_power_clk_enable(struct dp_power *dp_power, return 0; } + if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) { + DRM_DEBUG_DP("pixel clks already enabled\n"); + return 0; + } + if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) { DRM_DEBUG_DP("Enable core clks before link clks\n"); @@ -215,13 +248,16 @@ int dp_power_clk_enable(struct dp_power *dp_power, if (pm_type == DP_CORE_PM) dp_power->core_clks_on = enable; + else if (pm_type == DP_STREAM_PM) + dp_power->stream_clks_on = enable; else dp_power->link_clks_on = enable; DRM_DEBUG_DP("%s clocks for %s\n", enable ? "enable" : "disable", dp_parser_pm_name(pm_type)); - DRM_DEBUG_DP("link_clks:%s core_clks:%s\n", + DRM_DEBUG_DP("strem_clks:%s link_clks:%s core_clks:%s\n", + dp_power->stream_clks_on ? "on" : "off", dp_power->link_clks_on ? "on" : "off", dp_power->core_clks_on ? "on" : "off"); diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h index 756341e290ed0..5333a97d5c356 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ b/drivers/gpu/drm/msm/dp/dp_power.h @@ -19,6 +19,7 @@ struct dp_power { bool core_clks_on; bool link_clks_on; + bool stream_clks_on; }; /** @@ -43,6 +44,18 @@ int dp_power_init(struct dp_power *power, bool flip); */ int dp_power_deinit(struct dp_power *power); +/** + * dp_power_clk_status() - display controller clocks status + * + * @power: instance of power module + * @pm_type: type of pm, core/ctrl/phy + * return: status of power clocks + * + * This API return status of DP clocks + */ + +int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type); + /** * dp_power_clk_enable() - enable display controller clocks * diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index 721c0cc692965..de32f6204a505 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -101,6 +101,7 @@ #define REG_DP_MAINLINK_CTRL (0x00000000) #define DP_MAINLINK_CTRL_ENABLE (0x00000001) #define DP_MAINLINK_CTRL_RESET (0x00000002) +#define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER (0x00000010) #define DP_MAINLINK_FB_BOUNDARY_SEL (0x02000000) #define REG_DP_STATE_CTRL (0x00000004) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index f898a4121ce9b..4dbdf5b0f5f71 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -392,6 +392,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder); int msm_dp_display_enable(struct msm_dp *dp, struct drm_encoder *encoder); int msm_dp_display_disable(struct msm_dp *dp, struct drm_encoder *encoder); +int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder *encoder); void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -- GitLab From 061eb621fc2780aa252b7dad332ac241feb1e7c7 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 13:49:28 -0700 Subject: [PATCH 1123/1494] drm/msm/dp: store dp_display in the driver data Store the dp_display in the platform driver data instead of the dp_display_private. This is required to allow other sub-modules to reuse the platform driver data. Changes in v3: none Changes in v4: none Changes in v5: none Changes in v6: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_display.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 18ca5eac8e203..509fc76dbe716 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -181,11 +181,11 @@ static int dp_display_bind(struct device *dev, struct device *master, struct dp_display_private *dp; struct drm_device *drm; struct msm_drm_private *priv; - struct platform_device *pdev = to_platform_device(dev); drm = dev_get_drvdata(master); - dp = platform_get_drvdata(pdev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); if (!dp) { DRM_ERROR("DP driver bind failed. Invalid driver data\n"); return -EINVAL; @@ -220,11 +220,11 @@ static void dp_display_unbind(struct device *dev, struct device *master, void *data) { struct dp_display_private *dp; - struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm = dev_get_drvdata(master); struct msm_drm_private *priv = drm->dev_private; - dp = platform_get_drvdata(pdev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); if (!dp) { DRM_ERROR("Invalid DP driver data\n"); return; @@ -359,7 +359,8 @@ static int dp_display_usbpd_configure_cb(struct device *dev) goto end; } - dp = dev_get_drvdata(dev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); if (!dp) { DRM_ERROR("no driver data found\n"); rc = -ENODEV; @@ -383,7 +384,8 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) int rc = 0; struct dp_display_private *dp; - dp = dev_get_drvdata(dev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); @@ -435,7 +437,8 @@ static int dp_display_usbpd_attention_cb(struct device *dev) return -EINVAL; } - dp = dev_get_drvdata(dev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); if (!dp) { DRM_ERROR("no driver data found\n"); return -ENODEV; @@ -1070,12 +1073,14 @@ static int dp_display_probe(struct platform_device *pdev) return -EPROBE_DEFER; } - platform_set_drvdata(pdev, dp); - mutex_init(&dp->event_mutex); + init_completion(&dp->resume_comp); + g_dp_display = &dp->dp_display; + platform_set_drvdata(pdev, g_dp_display); + rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { DRM_ERROR("component add failed, rc=%d\n", rc); @@ -1089,7 +1094,8 @@ static int dp_display_remove(struct platform_device *pdev) { struct dp_display_private *dp; - dp = platform_get_drvdata(pdev); + dp = container_of(g_dp_display, + struct dp_display_private, dp_display); dp_display_deinit_sub_modules(dp); -- GitLab From d13e36d7d2227e6fe91bc063d473f97d43f9442f Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 13:49:29 -0700 Subject: [PATCH 1124/1494] drm/msm/dp: add audio support for Display Port on MSM Introduce audio support for Display Port on MSM chipsets. This change integrates DP audio sub-module with the main Display Port platform driver. In addition, this change leverages hdmi_codec_ops to expose the operations to the audio driver. Changes in v2: fix up a compilation issue on drm-next branch Changes in v3: none Changes in v4: none Changes in v5: none Changes in v6: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 + drivers/gpu/drm/msm/dp/dp_audio.c | 583 ++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_audio.h | 72 +++ drivers/gpu/drm/msm/dp/dp_catalog.c | 192 +++++++ drivers/gpu/drm/msm/dp/dp_catalog.h | 29 + drivers/gpu/drm/msm/dp/dp_display.c | 48 ++ drivers/gpu/drm/msm/dp/dp_display.h | 2 + 8 files changed, 935 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_audio.c create mode 100644 drivers/gpu/drm/msm/dp/dp_audio.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 6db6423cca935..5c9a8a353145a 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -111,7 +111,8 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_parser.o \ dp/dp_power.o \ dp/dp_pll.o \ - dp/dp_pll_10nm.o + dp/dp_pll_10nm.o \ + dp/dp_audio.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 702a290409582..761a007e71692 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1112,6 +1112,13 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc) return; } + + if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort && + dpu_enc->cur_master->hw_mdptop && + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select) + dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select( + dpu_enc->cur_master->hw_mdptop); + _dpu_encoder_update_vsync_source(dpu_enc, &dpu_enc->disp_info); if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI && diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c new file mode 100644 index 0000000000000..75556eea10592 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + */ + + +#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ + +#include <linux/of_platform.h> + +#include <drm/drm_dp_helper.h> +#include <drm/drm_edid.h> +#include <sound/hdmi-codec.h> + +#include "dp_catalog.h" +#include "dp_audio.h" +#include "dp_panel.h" +#include "dp_display.h" + +#define HEADER_BYTE_2_BIT 0 +#define PARITY_BYTE_2_BIT 8 +#define HEADER_BYTE_1_BIT 16 +#define PARITY_BYTE_1_BIT 24 +#define HEADER_BYTE_3_BIT 16 +#define PARITY_BYTE_3_BIT 24 + +struct dp_audio_private { + struct platform_device *audio_pdev; + struct platform_device *pdev; + struct dp_catalog *catalog; + struct dp_panel *panel; + + bool engine_on; + u32 channels; + + struct dp_audio dp_audio; +}; + +static u8 dp_audio_get_g0_value(u8 data) +{ + u8 c[4]; + u8 g[4]; + u8 ret_data = 0; + u8 i; + + for (i = 0; i < 4; i++) + c[i] = (data >> i) & 0x01; + + g[0] = c[3]; + g[1] = c[0] ^ c[3]; + g[2] = c[1]; + g[3] = c[2]; + + for (i = 0; i < 4; i++) + ret_data = ((g[i] & 0x01) << i) | ret_data; + + return ret_data; +} + +static u8 dp_audio_get_g1_value(u8 data) +{ + u8 c[4]; + u8 g[4]; + u8 ret_data = 0; + u8 i; + + for (i = 0; i < 4; i++) + c[i] = (data >> i) & 0x01; + + g[0] = c[0] ^ c[3]; + g[1] = c[0] ^ c[1] ^ c[3]; + g[2] = c[1] ^ c[2]; + g[3] = c[2] ^ c[3]; + + for (i = 0; i < 4; i++) + ret_data = ((g[i] & 0x01) << i) | ret_data; + + return ret_data; +} + +static u8 dp_audio_calculate_parity(u32 data) +{ + u8 x0 = 0; + u8 x1 = 0; + u8 ci = 0; + u8 iData = 0; + u8 i = 0; + u8 parity_byte; + u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2; + + for (i = 0; i < num_byte; i++) { + iData = (data >> i*4) & 0xF; + + ci = iData ^ x1; + x1 = x0 ^ dp_audio_get_g1_value(ci); + x0 = dp_audio_get_g0_value(ci); + } + + parity_byte = x1 | (x0 << 4); + + return parity_byte; +} + +static u32 dp_audio_get_header(struct dp_catalog *catalog, + enum dp_catalog_audio_sdp_type sdp, + enum dp_catalog_audio_header_type header) +{ + catalog->sdp_type = sdp; + catalog->sdp_header = header; + dp_catalog_audio_get_header(catalog); + + return catalog->audio_data; +} + +static void dp_audio_set_header(struct dp_catalog *catalog, + u32 data, + enum dp_catalog_audio_sdp_type sdp, + enum dp_catalog_audio_header_type header) +{ + catalog->sdp_type = sdp; + catalog->sdp_header = header; + catalog->audio_data = data; + dp_catalog_audio_set_header(catalog); +} + +static void dp_audio_stream_sdp(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 value, new_value; + u8 parity_byte; + + /* Config header and parity byte 1 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); + + new_value = 0x02; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_1_BIT) + | (parity_byte << PARITY_BYTE_1_BIT)); + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1); + + /* Config header and parity byte 2 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); + new_value = value; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_2_BIT) + | (parity_byte << PARITY_BYTE_2_BIT)); + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2); + + /* Config header and parity byte 3 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); + + new_value = audio->channels - 1; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_3_BIT) + | (parity_byte << PARITY_BYTE_3_BIT)); + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3); +} + +static void dp_audio_timestamp_sdp(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 value, new_value; + u8 parity_byte; + + /* Config header and parity byte 1 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); + + new_value = 0x1; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_1_BIT) + | (parity_byte << PARITY_BYTE_1_BIT)); + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1); + + /* Config header and parity byte 2 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); + + new_value = 0x17; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_2_BIT) + | (parity_byte << PARITY_BYTE_2_BIT)); + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2); + + /* Config header and parity byte 3 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); + + new_value = (0x0 | (0x11 << 2)); + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_3_BIT) + | (parity_byte << PARITY_BYTE_3_BIT)); + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3); +} + +static void dp_audio_infoframe_sdp(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 value, new_value; + u8 parity_byte; + + /* Config header and parity byte 1 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); + + new_value = 0x84; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_1_BIT) + | (parity_byte << PARITY_BYTE_1_BIT)); + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1); + + /* Config header and parity byte 2 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); + + new_value = 0x1b; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_2_BIT) + | (parity_byte << PARITY_BYTE_2_BIT)); + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2); + + /* Config header and parity byte 3 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); + + new_value = (0x0 | (0x11 << 2)); + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_3_BIT) + | (parity_byte << PARITY_BYTE_3_BIT)); + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", + new_value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3); +} + +static void dp_audio_copy_management_sdp(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 value, new_value; + u8 parity_byte; + + /* Config header and parity byte 1 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); + + new_value = 0x05; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_1_BIT) + | (parity_byte << PARITY_BYTE_1_BIT)); + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1); + + /* Config header and parity byte 2 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); + + new_value = 0x0F; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_2_BIT) + | (parity_byte << PARITY_BYTE_2_BIT)); + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2); + + /* Config header and parity byte 3 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); + + new_value = 0x0; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_3_BIT) + | (parity_byte << PARITY_BYTE_3_BIT)); + DRM_DEBUG_DP("Header Byte 3: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3); +} + +static void dp_audio_isrc_sdp(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 value, new_value; + u8 parity_byte; + + /* Config header and parity byte 1 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); + + new_value = 0x06; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_1_BIT) + | (parity_byte << PARITY_BYTE_1_BIT)); + DRM_DEBUG_DP("Header Byte 1: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1); + + /* Config header and parity byte 2 */ + value = dp_audio_get_header(catalog, + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); + + new_value = 0x0F; + parity_byte = dp_audio_calculate_parity(new_value); + value |= ((new_value << HEADER_BYTE_2_BIT) + | (parity_byte << PARITY_BYTE_2_BIT)); + DRM_DEBUG_DP("Header Byte 2: value = 0x%x, parity_byte = 0x%x\n", + value, parity_byte); + dp_audio_set_header(catalog, value, + DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2); +} + +static void dp_audio_setup_sdp(struct dp_audio_private *audio) +{ + dp_catalog_audio_config_sdp(audio->catalog); + + dp_audio_stream_sdp(audio); + dp_audio_timestamp_sdp(audio); + dp_audio_infoframe_sdp(audio); + dp_audio_copy_management_sdp(audio); + dp_audio_isrc_sdp(audio); +} + +static void dp_audio_setup_acr(struct dp_audio_private *audio) +{ + u32 select = 0; + struct dp_catalog *catalog = audio->catalog; + + switch (audio->dp_audio.bw_code) { + case DP_LINK_BW_1_62: + select = 0; + break; + case DP_LINK_BW_2_7: + select = 1; + break; + case DP_LINK_BW_5_4: + select = 2; + break; + case DP_LINK_BW_8_1: + select = 3; + break; + default: + DRM_DEBUG_DP("Unknown link rate\n"); + select = 0; + break; + } + + catalog->audio_data = select; + dp_catalog_audio_config_acr(catalog); +} + +static void dp_audio_safe_to_exit_level(struct dp_audio_private *audio) +{ + struct dp_catalog *catalog = audio->catalog; + u32 safe_to_exit_level = 0; + + switch (audio->dp_audio.lane_count) { + case 1: + safe_to_exit_level = 14; + break; + case 2: + safe_to_exit_level = 8; + break; + case 4: + safe_to_exit_level = 5; + break; + default: + DRM_DEBUG_DP("setting the default safe_to_exit_level = %u\n", + safe_to_exit_level); + safe_to_exit_level = 14; + break; + } + + catalog->audio_data = safe_to_exit_level; + dp_catalog_audio_sfe_level(catalog); +} + +static void dp_audio_enable(struct dp_audio_private *audio, bool enable) +{ + struct dp_catalog *catalog = audio->catalog; + + catalog->audio_data = enable; + dp_catalog_audio_enable(catalog); + + audio->engine_on = enable; +} + +static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev) +{ + struct dp_audio *dp_audio; + struct msm_dp *dp_display; + + if (!pdev) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-ENODEV); + } + + dp_display = platform_get_drvdata(pdev); + if (!dp_display) { + DRM_ERROR("invalid input\n"); + return ERR_PTR(-ENODEV); + } + + dp_audio = dp_display->dp_audio; + + if (!dp_audio) { + DRM_ERROR("invalid dp_audio data\n"); + return ERR_PTR(-EINVAL); + } + + return container_of(dp_audio, struct dp_audio_private, dp_audio); +} + +static int dp_audio_get_eld(struct device *dev, + void *data, uint8_t *buf, size_t len) +{ + struct platform_device *pdev; + struct msm_dp *dp_display; + + pdev = to_platform_device(dev); + + if (!pdev) { + DRM_ERROR("invalid input\n"); + return -ENODEV; + } + + dp_display = platform_get_drvdata(pdev); + if (!dp_display) { + DRM_ERROR("invalid input\n"); + return -ENODEV; + } + + memcpy(buf, dp_display->connector->eld, + min(sizeof(dp_display->connector->eld), len)); + + return 0; +} + +int dp_audio_hw_params(struct device *dev, + void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + int rc = 0; + struct dp_audio_private *audio; + struct platform_device *pdev; + + pdev = to_platform_device(dev); + + audio = dp_audio_get_data(pdev); + if (IS_ERR(audio)) { + rc = PTR_ERR(audio); + goto end; + } + + audio->channels = params->channels; + + dp_audio_setup_sdp(audio); + dp_audio_setup_acr(audio); + dp_audio_safe_to_exit_level(audio); + dp_audio_enable(audio, true); +end: + return rc; +} + +static void dp_audio_shutdown(struct device *dev, void *data) +{ + struct dp_audio_private *audio; + struct platform_device *pdev; + + pdev = to_platform_device(dev); + audio = dp_audio_get_data(pdev); + if (IS_ERR(audio)) { + DRM_ERROR("failed to get audio data\n"); + return; + } + + dp_audio_enable(audio, false); +} + +static const struct hdmi_codec_ops dp_audio_codec_ops = { + .hw_params = dp_audio_hw_params, + .audio_shutdown = dp_audio_shutdown, + .get_eld = dp_audio_get_eld, +}; + +static struct hdmi_codec_pdata codec_data = { + .ops = &dp_audio_codec_ops, + .max_i2s_channels = 8, + .i2s = 1, +}; + +int dp_register_audio_driver(struct device *dev, + struct dp_audio *dp_audio) +{ + struct dp_audio_private *audio_priv; + + audio_priv = container_of(dp_audio, + struct dp_audio_private, 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 dp_audio *dp_audio_get(struct platform_device *pdev, + struct dp_panel *panel, + struct dp_catalog *catalog) +{ + int rc = 0; + struct dp_audio_private *audio; + struct dp_audio *dp_audio; + + if (!pdev || !panel || !catalog) { + DRM_ERROR("invalid input\n"); + rc = -EINVAL; + goto error; + } + + audio = devm_kzalloc(&pdev->dev, sizeof(*audio), GFP_KERNEL); + if (!audio) { + rc = -ENOMEM; + goto error; + } + + audio->pdev = pdev; + audio->panel = panel; + audio->catalog = catalog; + + dp_audio = &audio->dp_audio; + + dp_catalog_audio_init(catalog); + + return dp_audio; +error: + return ERR_PTR(rc); +} + +void dp_audio_put(struct dp_audio *dp_audio) +{ + struct dp_audio_private *audio; + + if (!dp_audio) + return; + + audio = container_of(dp_audio, struct dp_audio_private, dp_audio); + + devm_kfree(&audio->pdev->dev, audio); +} diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h new file mode 100644 index 0000000000000..84e5f4a5d26ba --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_audio.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_AUDIO_H_ +#define _DP_AUDIO_H_ + +#include <linux/platform_device.h> + +#include "dp_panel.h" +#include "dp_catalog.h" +#include <sound/hdmi-codec.h> + +/** + * struct dp_audio + * @lane_count: number of lanes configured in current session + * @bw_code: link rate's bandwidth code for current session + */ +struct dp_audio { + u32 lane_count; + u32 bw_code; +}; + +/** + * dp_audio_get() + * + * Creates and instance of dp audio. + * + * @pdev: caller's platform device instance. + * @panel: an instance of dp_panel module. + * @catalog: an instance of dp_catalog module. + * + * Returns the error code in case of failure, otherwize + * an instance of newly created dp_module. + */ +struct dp_audio *dp_audio_get(struct platform_device *pdev, + struct dp_panel *panel, + struct dp_catalog *catalog); + +/** + * dp_register_audio_driver() + * + * Registers DP device with hdmi_codec interface. + * + * @dev: DP device instance. + * @dp_audio: an instance of dp_audio module. + * + * + * Returns the error code in case of failure, otherwise + * zero on success. + */ +int dp_register_audio_driver(struct device *dev, + struct dp_audio *dp_audio); + +/** + * dp_audio_put() + * + * Cleans the dp_audio instance. + * + * @dp_audio: an instance of dp_audio. + */ +void dp_audio_put(struct dp_audio *dp_audio); + +int dp_audio_hw_params(struct device *dev, + void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params); + +#endif /* _DP_AUDIO_H_ */ + + diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 67abb90953e49..393e3d4431399 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -90,6 +90,7 @@ aux_lut_value[PHY_AUX_CFG_MAX][DP_AUX_CFG_MAX_VALUE_CNT] = { struct dp_catalog_private { struct device *dev; struct dp_io *io; + u32 (*audio_map)[DP_AUDIO_SDP_HEADER_MAX]; struct dp_catalog dp_catalog; u8 aux_lut_cfg_index[PHY_AUX_CFG_MAX]; }; @@ -1070,3 +1071,194 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io) return &catalog->dp_catalog; } + +void dp_catalog_audio_get_header(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; + enum dp_catalog_audio_sdp_type sdp; + enum dp_catalog_audio_header_type header; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + sdp_map = catalog->audio_map; + sdp = dp_catalog->sdp_type; + header = dp_catalog->sdp_header; + + dp_catalog->audio_data = dp_read_link(catalog, + sdp_map[sdp][header]); +} + +void dp_catalog_audio_set_header(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + u32 (*sdp_map)[DP_AUDIO_SDP_HEADER_MAX]; + enum dp_catalog_audio_sdp_type sdp; + enum dp_catalog_audio_header_type header; + u32 data; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + sdp_map = catalog->audio_map; + sdp = dp_catalog->sdp_type; + header = dp_catalog->sdp_header; + data = dp_catalog->audio_data; + + dp_write_link(catalog, sdp_map[sdp][header], data); +} + +void dp_catalog_audio_config_acr(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + u32 acr_ctrl, select; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + select = dp_catalog->audio_data; + acr_ctrl = select << 4 | BIT(31) | BIT(8) | BIT(14); + + DRM_DEBUG_DP("select = 0x%x, acr_ctrl = 0x%x\n", select, acr_ctrl); + + dp_write_link(catalog, MMSS_DP_AUDIO_ACR_CTRL, acr_ctrl); +} + +void dp_catalog_audio_enable(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + bool enable; + u32 audio_ctrl; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + enable = !!dp_catalog->audio_data; + audio_ctrl = dp_read_link(catalog, MMSS_DP_AUDIO_CFG); + + if (enable) + audio_ctrl |= BIT(0); + else + audio_ctrl &= ~BIT(0); + + DRM_DEBUG_DP("dp_audio_cfg = 0x%x\n", audio_ctrl); + + dp_write_link(catalog, MMSS_DP_AUDIO_CFG, audio_ctrl); + /* make sure audio engine is disabled */ + wmb(); +} + +void dp_catalog_audio_config_sdp(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + u32 sdp_cfg = 0; + u32 sdp_cfg2 = 0; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + sdp_cfg = 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_DEBUG_DP("sdp_cfg = 0x%x\n", sdp_cfg); + + dp_write_link(catalog, MMSS_DP_SDP_CFG, sdp_cfg); + + sdp_cfg2 = 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_DEBUG_DP("sdp_cfg2 = 0x%x\n", sdp_cfg2); + + dp_write_link(catalog, MMSS_DP_SDP_CFG2, sdp_cfg2); +} + +void dp_catalog_audio_init(struct dp_catalog *dp_catalog) +{ + struct 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 (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + catalog->audio_map = sdp_map; +} + +void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) +{ + struct dp_catalog_private *catalog; + u32 mainlink_levels, safe_to_exit_level; + + if (!dp_catalog) + return; + + catalog = container_of(dp_catalog, + struct dp_catalog_private, dp_catalog); + + safe_to_exit_level = dp_catalog->audio_data; + mainlink_levels = dp_read_link(catalog, REG_DP_MAINLINK_LEVELS); + mainlink_levels &= 0xFE0; + mainlink_levels |= safe_to_exit_level; + + DRM_DEBUG_DP("mainlink_level = 0x%x, safe_to_exit_level = 0x%x\n", + mainlink_levels, safe_to_exit_level); + + 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 index 35c90b248b5d1..edb68a65b0fa1 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -42,12 +42,31 @@ enum dp_phy_aux_config_type { PHY_AUX_CFG_MAX, }; +enum 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 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 dp_catalog { u32 aux_data; u32 total; u32 sync_start; u32 width_blanking; u32 dp_active; + enum dp_catalog_audio_sdp_type sdp_type; + enum dp_catalog_audio_header_type sdp_header; + u32 audio_data; }; /* AUX APIs */ @@ -102,4 +121,14 @@ void dp_catalog_panel_tpg_disable(struct dp_catalog *dp_catalog); struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_io *io); +/* DP Audio APIs */ +void dp_catalog_audio_get_header(struct dp_catalog *catalog); +void dp_catalog_audio_set_header(struct dp_catalog *catalog); +void dp_catalog_audio_config_acr(struct dp_catalog *catalog); +void dp_catalog_audio_enable(struct dp_catalog *catalog); +void dp_catalog_audio_enable(struct dp_catalog *catalog); +void dp_catalog_audio_config_sdp(struct dp_catalog *catalog); +void dp_catalog_audio_init(struct dp_catalog *catalog); +void dp_catalog_audio_sfe_level(struct dp_catalog *catalog); + #endif /* _DP_CATALOG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 509fc76dbe716..dd2d9433f4d75 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -25,6 +25,7 @@ #include "dp_display.h" #include "dp_drm.h" #include "dp_pll.h" +#include "dp_audio.h" static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 @@ -113,6 +114,8 @@ struct dp_display_private { spinlock_t event_lock; struct completion resume_comp; + + struct dp_audio *audio; }; static const struct of_device_id dp_dt_match[] = { @@ -212,6 +215,13 @@ static int dp_display_bind(struct device *dev, struct device *master, DRM_ERROR("Power client create failed\n"); goto end; } + + rc = dp_register_audio_driver(dev, dp->audio); + if (rc) { + DRM_ERROR("Audio registration Dp failed\n"); + goto end; + } + end: return rc; } @@ -384,8 +394,19 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) int rc = 0; struct dp_display_private *dp; + if (!dev) { + DRM_ERROR("invalid dev\n"); + rc = -EINVAL; + return rc; + } + dp = container_of(g_dp_display, struct dp_display_private, dp_display); + if (!dp) { + DRM_ERROR("no driver data found\n"); + rc = -ENODEV; + return rc; + } dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); @@ -620,6 +641,7 @@ static void dp_display_deinit_sub_modules(struct dp_display_private *dp) dp_panel_put(dp->panel); dp_aux_put(dp->aux); dp_pll_put(dp->pll); + dp_audio_put(dp->audio); } static int dp_init_sub_modules(struct dp_display_private *dp) @@ -719,7 +741,18 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_ctrl; } + dp->audio = dp_audio_get(dp->pdev, dp->panel, dp->catalog); + if (IS_ERR(dp->audio)) { + rc = PTR_ERR(dp->audio); + pr_err("failed to initialize audio, rc = %d\n", rc); + dp->audio = NULL; + goto error_audio; + } + return rc; + +error_audio: + dp_ctrl_put(dp->ctrl); error_ctrl: dp_panel_put(dp->panel); error_link: @@ -767,6 +800,18 @@ static int dp_display_enable(struct dp_display_private *dp, u32 data) static int dp_display_post_enable(struct msm_dp *dp_display) { + struct dp_display_private *dp; + u32 rate; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + rate = dp->link->link_params.rate; + + if (dp->audio_supported) { + dp->audio->bw_code = drm_dp_link_rate_to_bw_code(rate); + dp->audio->lane_count = dp->link->link_params.num_lanes; + } + return 0; } @@ -1079,6 +1124,9 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display = &dp->dp_display; + /* Store DP audio handle inside DP display */ + g_dp_display->dp_audio = dp->audio; + platform_set_drvdata(pdev, g_dp_display); rc = component_add(&pdev->dev, &dp_display_comp_ops); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 2f2d1279dfc65..1e0d2b9d9a2ae 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -14,7 +14,9 @@ struct msm_dp { struct drm_encoder *encoder; bool is_connected; u32 max_pclk_khz; + u32 max_dp_lanes; + struct dp_audio *dp_audio; }; int dp_display_validate_mode(struct msm_dp *dp_display, u32 mode_pclk_khz); -- GitLab From a1f5bda99b7bee46b01f6a9f256671c8efef0ec9 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 13:49:30 -0700 Subject: [PATCH 1125/1494] drm/msm/dp: add hook_plugged_cb hdmi-codec op for MSM DP driver Add the hook_plugged_cb op for the MSM DP driver to signal connect and disconnect events to the hdmi-codec driver which in-turn shall notify the audio subsystem to start a new or teardown an existing session. Changes in v2: none Changes in v3: none Changes in v4: rebase on top of latest patchset of dependency Changes in v5: rebase on top of latest patchset of dependency Changes in v6: none Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_audio.c | 25 ++++++++++++++++++++++++- drivers/gpu/drm/msm/dp/dp_display.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.h | 7 +++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 75556eea10592..11fa5ad7a8016 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -10,7 +10,6 @@ #include <drm/drm_dp_helper.h> #include <drm/drm_edid.h> -#include <sound/hdmi-codec.h> #include "dp_catalog.h" #include "dp_audio.h" @@ -442,6 +441,29 @@ static struct dp_audio_private *dp_audio_get_data(struct platform_device *pdev) return container_of(dp_audio, struct dp_audio_private, dp_audio); } +static int 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 *dp_display; + + pdev = to_platform_device(dev); + if (!pdev) { + pr_err("invalid input\n"); + return -ENODEV; + } + + dp_display = platform_get_drvdata(pdev); + if (!dp_display) { + pr_err("invalid input\n"); + return -ENODEV; + } + + return dp_display_set_plugged_cb(dp_display, fn, codec_dev); +} + static int dp_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size_t len) { @@ -513,6 +535,7 @@ static const struct hdmi_codec_ops dp_audio_codec_ops = { .hw_params = dp_audio_hw_params, .audio_shutdown = dp_audio_shutdown, .get_eld = dp_audio_get_eld, + .hook_plugged_cb = dp_audio_hook_plugged_cb, }; static struct hdmi_codec_pdata codec_data = { diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index dd2d9433f4d75..c30ffe778ffea 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -780,6 +780,13 @@ static int dp_display_prepare(struct msm_dp *dp) return 0; } +static void dp_display_handle_plugged_change(struct msm_dp *dp_display, + bool plugged) +{ + if (dp_display->plugged_cb && dp_display->codec_dev) + dp_display->plugged_cb(dp_display->codec_dev, plugged); +} + static int dp_display_enable(struct dp_display_private *dp, u32 data) { int rc = 0; @@ -812,6 +819,8 @@ static int dp_display_post_enable(struct msm_dp *dp_display) dp->audio->lane_count = dp->link->link_params.num_lanes; } + /* signal the connect event late to synchronize video and display */ + dp_display_handle_plugged_change(dp_display, true); return 0; } @@ -834,6 +843,19 @@ static int dp_display_unprepare(struct msm_dp *dp) return 0; } +int dp_display_set_plugged_cb(struct msm_dp *dp_display, + hdmi_codec_plugged_cb fn, struct device *codec_dev) +{ + bool plugged; + + dp_display->plugged_cb = fn; + dp_display->codec_dev = codec_dev; + plugged = dp_display->is_connected; + dp_display_handle_plugged_change(dp_display, plugged); + + return 0; +} + int dp_display_validate_mode(struct msm_dp *dp, u32 mode_pclk_khz) { const u32 num_components = 3, default_bpp = 24; @@ -1349,6 +1371,8 @@ int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder *encoder) dp_ctrl_push_idle(dp_display->ctrl); + dp_display_handle_plugged_change(dp, false); + return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 1e0d2b9d9a2ae..5020faf360db7 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -7,18 +7,25 @@ #define _DP_DISPLAY_H_ #include "dp_panel.h" +#include <sound/hdmi-codec.h> struct msm_dp { struct drm_device *drm_dev; + struct device *codec_dev; struct drm_connector *connector; struct drm_encoder *encoder; bool is_connected; + + hdmi_codec_plugged_cb plugged_cb; + u32 max_pclk_khz; u32 max_dp_lanes; struct dp_audio *dp_audio; }; +int dp_display_set_plugged_cb(struct msm_dp *dp_display, + hdmi_codec_plugged_cb fn, struct device *codec_dev); int dp_display_validate_mode(struct msm_dp *dp_display, u32 mode_pclk_khz); int dp_display_get_modes(struct msm_dp *dp_display, struct dp_display_mode *dp_mode); -- GitLab From bf4a1b3127d34b0b6ee0565b31ff699b3dc9c48e Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 13:49:31 -0700 Subject: [PATCH 1126/1494] drm/msm/dp: signal the hotplug disconnect in the event handler Signal the hotplug disconnect event to the audio side in the event handler so that they are notified earlier and have more time to process the disconnect event. Changes in v2: none Changes in v3: none Changes in v4: rebase on top of latest patchset of dependency Changes in v5: rebase on top of latest patchset of dependency Changes in v6: none Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_display.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c30ffe778ffea..32d2236b20b2e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -545,6 +545,13 @@ static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data) return 0; } +static void dp_display_handle_plugged_change(struct msm_dp *dp_display, + bool plugged) +{ + if (dp_display->plugged_cb && dp_display->codec_dev) + dp_display->plugged_cb(dp_display->codec_dev, plugged); +} + static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) { struct dp_usbpd *hpd = dp->usbpd; @@ -590,6 +597,9 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) /* start sanity checking */ dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND); + /* signal the disconnect event early to ensure proper teardown */ + dp_display_handle_plugged_change(g_dp_display, false); + dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, true); @@ -780,13 +790,6 @@ static int dp_display_prepare(struct msm_dp *dp) return 0; } -static void dp_display_handle_plugged_change(struct msm_dp *dp_display, - bool plugged) -{ - if (dp_display->plugged_cb && dp_display->codec_dev) - dp_display->plugged_cb(dp_display->codec_dev, plugged); -} - static int dp_display_enable(struct dp_display_private *dp, u32 data) { int rc = 0; @@ -1371,8 +1374,6 @@ int msm_dp_display_pre_disable(struct msm_dp *dp, struct drm_encoder *encoder) dp_ctrl_push_idle(dp_display->ctrl); - dp_display_handle_plugged_change(dp, false); - return 0; } -- GitLab From 158b9aa74479c9979b7b4806cefdbf0c9a72ba49 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 13:49:32 -0700 Subject: [PATCH 1127/1494] drm/msm/dp: wait for audio notification before disabling clocks In the current implementation, there is a very small window for the audio side to safely signal the hdmi_code_shutdown() before the clocks are disabled. Add some synchronization between the DP display and DP audio module to safely disable the clocks to avoid unclocked access from audio side. In addition, audio side can open the sound card even if DP monitor is not connected. Avoid programming hardware registers in this case and bail out early. Changes in v4: - removed some leftover prints Changes in v5: - fix crash when user tries to play audio in suspended state Changes in v6: - rebased on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_audio.c | 32 +++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_display.c | 40 +++++++++++++++++++++++++---- drivers/gpu/drm/msm/dp/dp_display.h | 3 +++ 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 11fa5ad7a8016..82a8673ab8daf 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -497,8 +497,23 @@ int dp_audio_hw_params(struct device *dev, int rc = 0; struct dp_audio_private *audio; struct platform_device *pdev; + struct msm_dp *dp_display; pdev = to_platform_device(dev); + dp_display = platform_get_drvdata(pdev); + + /* + * there could be cases where sound card can be opened even + * before OR even when DP is not connected . This can cause + * unclocked access as the audio subsystem relies on the DP + * driver to maintain the correct state of clocks. To protect + * such cases check for connection status and bail out if not + * connected. + */ + if (!dp_display->power_on) { + rc = -EINVAL; + goto end; + } audio = dp_audio_get_data(pdev); if (IS_ERR(audio)) { @@ -512,6 +527,8 @@ int dp_audio_hw_params(struct device *dev, dp_audio_setup_acr(audio); dp_audio_safe_to_exit_level(audio); dp_audio_enable(audio, true); + dp_display->audio_enabled = true; + end: return rc; } @@ -520,15 +537,30 @@ static void dp_audio_shutdown(struct device *dev, void *data) { struct dp_audio_private *audio; struct platform_device *pdev; + struct msm_dp *dp_display; pdev = to_platform_device(dev); + dp_display = platform_get_drvdata(pdev); audio = dp_audio_get_data(pdev); if (IS_ERR(audio)) { DRM_ERROR("failed to get audio data\n"); return; } + /* + * if audio was not enabled there is no need + * to execute the shutdown and we can bail out early. + * This also makes sure that we dont cause an unclocked + * access when audio subsystem calls this without DP being + * connected. is_connected cannot be used here as its set + * to false earlier than this call + */ + if (!dp_display->audio_enabled) + return; + dp_audio_enable(audio, false); + /* signal the dp display to safely shutdown clocks */ + dp_display_signal_audio_complete(dp_display); } static const struct hdmi_codec_ops dp_audio_codec_ops = { diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 32d2236b20b2e..6f7795dc9bc38 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -82,7 +82,6 @@ struct dp_display_private { /* state variables */ bool core_initialized; - bool power_on; bool hpd_irq_on; bool audio_supported; @@ -104,6 +103,9 @@ struct dp_display_private { struct dp_display_mode dp_mode; struct msm_dp dp_display; + /* wait for audio signaling */ + struct completion audio_comp; + /* event related only access by event thread */ struct mutex event_mutex; wait_queue_head_t event_q; @@ -177,6 +179,15 @@ static int dp_del_event(struct dp_display_private *dp_priv, u32 event) return 0; } +void dp_display_signal_audio_complete(struct msm_dp *dp_display) +{ + struct dp_display_private *dp; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + complete_all(&dp->audio_comp); +} + static int dp_display_bind(struct device *dev, struct device *master, void *data) { @@ -599,6 +610,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) /* signal the disconnect event early to ensure proper teardown */ dp_display_handle_plugged_change(g_dp_display, false); + reinit_completion(&dp->audio_comp); dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK, true); @@ -793,15 +805,18 @@ static int dp_display_prepare(struct msm_dp *dp) static int dp_display_enable(struct dp_display_private *dp, u32 data) { int rc = 0; + struct msm_dp *dp_display; - if (dp->power_on) { + dp_display = g_dp_display; + + if (dp_display->power_on) { DRM_DEBUG_DP("Link already setup, return\n"); return 0; } rc = dp_ctrl_on_stream(dp->ctrl); if (!rc) - dp->power_on = true; + dp_display->power_on = true; /* complete resume_comp regardless it is armed or not */ complete(&dp->resume_comp); @@ -829,14 +844,27 @@ static int dp_display_post_enable(struct msm_dp *dp_display) static int dp_display_disable(struct dp_display_private *dp, u32 data) { - if (!dp->power_on) + struct msm_dp *dp_display; + + dp_display = g_dp_display; + + if (!dp_display->power_on) return -EINVAL; + /* wait only if audio was enabled */ + if (dp_display->audio_enabled) { + if (!wait_for_completion_timeout(&dp->audio_comp, + HZ * 5)) + DRM_ERROR("audio comp timeout\n"); + } + + dp_display->audio_enabled = false; + dp_ctrl_off(dp->ctrl); dp->core_initialized = false; - dp->power_on = false; + dp_display->power_on = false; return 0; } @@ -1152,6 +1180,8 @@ static int dp_display_probe(struct platform_device *pdev) /* Store DP audio handle inside DP display */ g_dp_display->dp_audio = dp->audio; + init_completion(&dp->audio_comp); + platform_set_drvdata(pdev, g_dp_display); rc = component_add(&pdev->dev, &dp_display_comp_ops); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 5020faf360db7..8b78b40bbd6c6 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -15,6 +15,8 @@ struct msm_dp { struct drm_connector *connector; struct drm_encoder *encoder; bool is_connected; + bool audio_enabled; + bool power_on; hdmi_codec_plugged_cb plugged_cb; @@ -32,6 +34,7 @@ int dp_display_get_modes(struct msm_dp *dp_display, int dp_display_request_irq(struct msm_dp *dp_display); bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); +void dp_display_signal_audio_complete(struct msm_dp *dp_display); void __init msm_dp_pll_driver_register(void); void __exit msm_dp_pll_driver_unregister(void); -- GitLab From d11a93690df7e9a7e07c0784ecad019a627b1449 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 14:08:12 -0700 Subject: [PATCH 1128/1494] drm/msm/dp: add debugfs support to DP driver To prepare the MSM DP driver for running video pattern compliance tests introduce debugfs module for it. Changes in v2: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/dp/dp_debug.c | 310 ++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_debug.h | 71 +++++++ drivers/gpu/drm/msm/dp/dp_display.c | 13 ++ 4 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.c create mode 100644 drivers/gpu/drm/msm/dp/dp_debug.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 5c9a8a353145a..99658a6bf6984 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -96,7 +96,8 @@ msm-y := \ msm_gpu_tracepoints.o \ msm_gpummu.o -msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o +msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ + dp/dp_debug.o msm-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c new file mode 100644 index 0000000000000..7430d60481839 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -0,0 +1,310 @@ +// 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/debugfs.h> +#include <drm/drm_connector.h> + +#include "dp_parser.h" +#include "dp_catalog.h" +#include "dp_aux.h" +#include "dp_ctrl.h" +#include "dp_debug.h" +#include "dp_display.h" + +#define DEBUG_NAME "drm_dp" + +struct dp_debug_private { + struct dentry *root; + + struct dp_usbpd *usbpd; + struct dp_link *link; + struct dp_panel *panel; + struct drm_connector **connector; + struct device *dev; + + struct dp_debug dp_debug; +}; + +static int dp_debug_check_buffer_overflow(int rc, int *max_size, int *len) +{ + if (rc >= *max_size) { + DRM_ERROR("buffer overflow\n"); + return -EINVAL; + } + *len += rc; + *max_size = SZ_4K - *len; + + return 0; +} + +static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, + size_t count, loff_t *ppos) +{ + struct dp_debug_private *debug = file->private_data; + char *buf; + u32 len = 0, rc = 0; + u64 lclk = 0; + u32 max_size = SZ_4K; + u32 link_params_rate; + struct drm_display_mode *drm_mode; + + if (!debug) + return -ENODEV; + + if (*ppos) + return 0; + + buf = kzalloc(SZ_4K, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + drm_mode = &debug->panel->dp_mode.drm_mode; + + rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\tdp_panel\n\t\tmax_pclk_khz = %d\n", + debug->panel->max_pclk_khz); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\tdrm_dp_link\n\t\trate = %u\n", + debug->panel->link_info.rate); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tnum_lanes = %u\n", + debug->panel->link_info.num_lanes); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tcapabilities = %lu\n", + debug->panel->link_info.capabilities); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\tdp_panel_info:\n\t\tactive = %dx%d\n", + drm_mode->hdisplay, + drm_mode->vdisplay); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tback_porch = %dx%d\n", + drm_mode->htotal - drm_mode->hsync_end, + drm_mode->vtotal - drm_mode->vsync_end); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tfront_porch = %dx%d\n", + drm_mode->hsync_start - drm_mode->hdisplay, + drm_mode->vsync_start - drm_mode->vdisplay); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tsync_width = %dx%d\n", + drm_mode->hsync_end - drm_mode->hsync_start, + drm_mode->vsync_end - drm_mode->vsync_start); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tactive_low = %dx%d\n", + debug->panel->dp_mode.h_active_low, + debug->panel->dp_mode.v_active_low); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\th_skew = %d\n", + drm_mode->hskew); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\trefresh rate = %d\n", + drm_mode_vrefresh(drm_mode)); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tpixel clock khz = %d\n", + drm_mode->clock); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tbpp = %d\n", + debug->panel->dp_mode.bpp); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + /* Link Information */ + rc = snprintf(buf + len, max_size, + "\tdp_link:\n\t\ttest_requested = %d\n", + debug->link->sink_request); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tnum_lanes = %d\n", + debug->link->link_params.num_lanes); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + link_params_rate = debug->link->link_params.rate; + rc = snprintf(buf + len, max_size, + "\t\tbw_code = %d\n", + drm_dp_link_rate_to_bw_code(link_params_rate)); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + lclk = debug->link->link_params.rate * 1000; + rc = snprintf(buf + len, max_size, + "\t\tlclk = %lld\n", lclk); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tv_level = %d\n", + debug->link->phy_params.v_level); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + rc = snprintf(buf + len, max_size, + "\t\tp_level = %d\n", + debug->link->phy_params.p_level); + if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) + goto error; + + if (copy_to_user(user_buff, buf, len)) + goto error; + + *ppos += len; + + kfree(buf); + return len; + error: + kfree(buf); + return -EINVAL; +} + +static const struct file_operations dp_debug_fops = { + .open = simple_open, + .read = dp_debug_read_info, +}; + +static int dp_debug_init(struct dp_debug *dp_debug) +{ + int rc = 0; + struct dp_debug_private *debug = container_of(dp_debug, + struct dp_debug_private, dp_debug); + struct dentry *dir, *file; + + dir = debugfs_create_dir(DEBUG_NAME, NULL); + if (IS_ERR_OR_NULL(dir)) { + rc = PTR_ERR(dir); + DRM_ERROR("[%s] debugfs create dir failed, rc = %d\n", + DEBUG_NAME, rc); + goto error; + } + + file = debugfs_create_file("dp_debug", 0444, dir, + debug, &dp_debug_fops); + if (IS_ERR_OR_NULL(file)) { + rc = PTR_ERR(file); + DRM_ERROR("[%s] debugfs create file failed, rc=%d\n", + DEBUG_NAME, rc); + goto error_remove_dir; + } + + debug->root = dir; + return rc; + error_remove_dir: + debugfs_remove(dir); + error: + return rc; +} + +struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, + struct dp_usbpd *usbpd, struct dp_link *link, + struct drm_connector **connector) +{ + int rc = 0; + struct dp_debug_private *debug; + struct dp_debug *dp_debug; + + if (!dev || !panel || !usbpd || !link) { + DRM_ERROR("invalid input\n"); + rc = -EINVAL; + goto error; + } + + debug = devm_kzalloc(dev, sizeof(*debug), GFP_KERNEL); + if (!debug) { + rc = -ENOMEM; + goto error; + } + + debug->dp_debug.debug_en = false; + debug->usbpd = usbpd; + debug->link = link; + debug->panel = panel; + debug->dev = dev; + debug->connector = connector; + + dp_debug = &debug->dp_debug; + dp_debug->vdisplay = 0; + dp_debug->hdisplay = 0; + dp_debug->vrefresh = 0; + + rc = dp_debug_init(dp_debug); + if (rc) { + devm_kfree(dev, debug); + goto error; + } + + return dp_debug; + error: + return ERR_PTR(rc); +} + +static int dp_debug_deinit(struct dp_debug *dp_debug) +{ + struct dp_debug_private *debug; + + if (!dp_debug) + return -EINVAL; + + debug = container_of(dp_debug, struct dp_debug_private, dp_debug); + + debugfs_remove_recursive(debug->root); + + return 0; +} + +void dp_debug_put(struct dp_debug *dp_debug) +{ + struct dp_debug_private *debug; + + if (!dp_debug) + return; + + debug = container_of(dp_debug, struct dp_debug_private, dp_debug); + + dp_debug_deinit(dp_debug); + + devm_kfree(debug->dev, debug); +} diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h new file mode 100644 index 0000000000000..fddf827ac0897 --- /dev/null +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DP_DEBUG_H_ +#define _DP_DEBUG_H_ + +#include "dp_panel.h" +#include "dp_link.h" + +/** + * struct dp_debug + * @debug_en: specifies whether debug mode enabled + * @vdisplay: used to filter out vdisplay value + * @hdisplay: used to filter out hdisplay value + * @vrefresh: used to filter out vrefresh value + * @tpg_state: specifies whether tpg feature is enabled + */ +struct dp_debug { + bool debug_en; + int aspect_ratio; + int vdisplay; + int hdisplay; + int vrefresh; +}; + +#if defined(CONFIG_DEBUG_FS) + +/** + * dp_debug_get() - configure and get the DisplayPlot debug module data + * + * @dev: device instance of the caller + * @panel: instance of panel module + * @usbpd: instance of usbpd module + * @link: instance of link module + * @connector: double pointer to display connector + * return: pointer to allocated debug module data + * + * This function sets up the debug module and provides a way + * for debugfs input to be communicated with existing modules + */ +struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, + struct dp_usbpd *usbpd, struct dp_link *link, + struct drm_connector **connector); +/** + * dp_debug_put() + * + * Cleans up dp_debug instance + * + * @dp_debug: instance of dp_debug + */ +void dp_debug_put(struct dp_debug *dp_debug); + +#else + +static inline +struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, + struct dp_usbpd *usbpd, struct dp_link *link, + struct drm_connector **connector) +{ + return ERR_PTR(-EINVAL); +} + +static inline void dp_debug_put(struct dp_debug *dp_debug) +{ +} + +#endif /* defined(CONFIG_DEBUG_FS) */ + +#endif /* _DP_DEBUG_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 6f7795dc9bc38..e34b1f49c64f6 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -26,6 +26,7 @@ #include "dp_drm.h" #include "dp_pll.h" #include "dp_audio.h" +#include "dp_debug.h" static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 @@ -659,6 +660,7 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) static void dp_display_deinit_sub_modules(struct dp_display_private *dp) { + dp_debug_put(dp->debug); dp_ctrl_put(dp->ctrl); dp_panel_put(dp->panel); dp_aux_put(dp->aux); @@ -771,8 +773,19 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_audio; } + dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, + dp->link, &dp->dp_display.connector); + if (IS_ERR(dp->debug)) { + rc = PTR_ERR(dp->debug); + DRM_ERROR("failed to initialize debug, rc = %d\n", rc); + dp->debug = NULL; + goto error_debug; + } + return rc; +error_debug: + dp_audio_put(dp->audio); error_audio: dp_ctrl_put(dp->ctrl); error_ctrl: -- GitLab From f913454aae8edaa84264d717e20f175bf616755f Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 14:08:13 -0700 Subject: [PATCH 1129/1494] drm/msm/dp: move debugfs node to /sys/kernel/debug/dri/*/ Move the MSM DP debugfs node from /sys/kernel/debug/drm_dp to /sys/kernel/debug/dri/*/ as required for video pattern compliance test suite. Changes in v2: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 +++++ drivers/gpu/drm/msm/dp/dp_debug.c | 31 ++++++++-------------- drivers/gpu/drm/msm/dp/dp_debug.h | 5 +++- drivers/gpu/drm/msm/dp/dp_display.c | 34 +++++++++++++++---------- drivers/gpu/drm/msm/msm_drv.h | 2 ++ 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index bcb5ee50568c7..db9e2761085bf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -195,10 +195,15 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dpu_kms *dpu_kms = to_dpu_kms(kms); void *p = dpu_hw_util_get_log_mask_ptr(); struct dentry *entry; + struct drm_device *dev; + struct msm_drm_private *priv; if (!p) return -EINVAL; + dev = dpu_kms->dev; + priv = dev->dev_private; + entry = debugfs_create_dir("debug", minor->debugfs_root); debugfs_create_x32(DPU_DEBUGFS_HWMASKNAME, 0600, entry, p); @@ -207,6 +212,8 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); + msm_dp_debugfs_init(priv->dp, minor); + return dpu_core_perf_debugfs_init(dpu_kms, entry); } #endif diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 7430d60481839..450f65060202b 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -7,6 +7,7 @@ #include <linux/debugfs.h> #include <drm/drm_connector.h> +#include <drm/drm_file.h> #include "dp_parser.h" #include "dp_catalog.h" @@ -15,7 +16,7 @@ #include "dp_debug.h" #include "dp_display.h" -#define DEBUG_NAME "drm_dp" +#define DEBUG_NAME "msm_dp" struct dp_debug_private { struct dentry *root; @@ -25,6 +26,7 @@ struct dp_debug_private { struct dp_panel *panel; struct drm_connector **connector; struct device *dev; + struct drm_device *drm_dev; struct dp_debug dp_debug; }; @@ -206,41 +208,29 @@ static const struct file_operations dp_debug_fops = { .read = dp_debug_read_info, }; -static int dp_debug_init(struct dp_debug *dp_debug) +static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); - struct dentry *dir, *file; + struct dentry *file; - dir = debugfs_create_dir(DEBUG_NAME, NULL); - if (IS_ERR_OR_NULL(dir)) { - rc = PTR_ERR(dir); - DRM_ERROR("[%s] debugfs create dir failed, rc = %d\n", - DEBUG_NAME, rc); - goto error; - } - - file = debugfs_create_file("dp_debug", 0444, dir, + file = debugfs_create_file("dp_debug", 0444, minor->debugfs_root, debug, &dp_debug_fops); if (IS_ERR_OR_NULL(file)) { rc = PTR_ERR(file); DRM_ERROR("[%s] debugfs create file failed, rc=%d\n", DEBUG_NAME, rc); - goto error_remove_dir; } - debug->root = dir; - return rc; - error_remove_dir: - debugfs_remove(dir); - error: + debug->root = minor->debugfs_root; + return rc; } struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, - struct drm_connector **connector) + struct drm_connector **connector, struct drm_minor *minor) { int rc = 0; struct dp_debug_private *debug; @@ -263,6 +253,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, debug->link = link; debug->panel = panel; debug->dev = dev; + debug->drm_dev = minor->dev; debug->connector = connector; dp_debug = &debug->dp_debug; @@ -270,7 +261,7 @@ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, dp_debug->hdisplay = 0; dp_debug->vrefresh = 0; - rc = dp_debug_init(dp_debug); + rc = dp_debug_init(dp_debug, minor); if (rc) { devm_kfree(dev, debug); goto error; diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h index fddf827ac0897..377e166fd0ead 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -35,6 +35,7 @@ struct dp_debug { * @usbpd: instance of usbpd module * @link: instance of link module * @connector: double pointer to display connector + * @minor: pointer to drm minor number after device registration * return: pointer to allocated debug module data * * This function sets up the debug module and provides a way @@ -42,7 +43,9 @@ struct dp_debug { */ struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, - struct drm_connector **connector); + struct drm_connector **connector, + struct drm_minor *minor); + /** * dp_debug_put() * diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index e34b1f49c64f6..aa7661f2a441e 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -229,10 +229,8 @@ static int dp_display_bind(struct device *dev, struct device *master, } rc = dp_register_audio_driver(dev, dp->audio); - if (rc) { + if (rc) DRM_ERROR("Audio registration Dp failed\n"); - goto end; - } end: return rc; @@ -773,19 +771,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error_audio; } - dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, - dp->link, &dp->dp_display.connector); - if (IS_ERR(dp->debug)) { - rc = PTR_ERR(dp->debug); - DRM_ERROR("failed to initialize debug, rc = %d\n", rc); - dp->debug = NULL; - goto error_debug; - } - return rc; -error_debug: - dp_audio_put(dp->audio); error_audio: dp_ctrl_put(dp->ctrl); error_ctrl: @@ -1299,6 +1286,25 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display) dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100); } +void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor) +{ + struct dp_display_private *dp; + struct device *dev; + int rc; + + dp = container_of(dp_display, struct dp_display_private, dp_display); + dev = &dp->pdev->dev; + + dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd, + dp->link, &dp->dp_display.connector, + minor); + if (IS_ERR(dp->debug)) { + rc = PTR_ERR(dp->debug); + DRM_ERROR("failed to initialize debug, rc = %d\n", rc); + dp->debug = NULL; + } +} + int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev, struct drm_encoder *encoder) { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 4dbdf5b0f5f71..319327462b29e 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -398,6 +398,8 @@ void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode); void msm_dp_irq_postinstall(struct msm_dp *dp_display); +void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor); + #else static inline int __init msm_dp_register(void) { -- GitLab From de3ee25473ba49f2e785e43b5db5e05cb35aad24 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 14:08:14 -0700 Subject: [PATCH 1130/1494] drm/msm/dp: add debugfs nodes for video pattern tests Add the debugfs nodes needed for the video pattern compliance tests to MSM DP driver. Changes in v2: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_debug.c | 184 ++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/dp/dp_link.h | 23 ++++ 2 files changed, 207 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 450f65060202b..84670bcdcfea1 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -203,17 +203,174 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, return -EINVAL; } +static int dp_test_data_show(struct seq_file *m, void *data) +{ + struct drm_device *dev; + struct dp_debug_private *debug; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + u32 bpc; + + debug = m->private; + dev = debug->drm_dev; + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + bpc = debug->link->test_video.test_bit_depth; + seq_printf(m, "hdisplay: %d\n", + debug->link->test_video.test_h_width); + seq_printf(m, "vdisplay: %d\n", + debug->link->test_video.test_v_height); + seq_printf(m, "bpc: %u\n", + dp_link_bit_depth_to_bpc(bpc)); + } else + seq_puts(m, "0"); + } + + drm_connector_list_iter_end(&conn_iter); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dp_test_data); + +static int dp_test_type_show(struct seq_file *m, void *data) +{ + struct dp_debug_private *debug = m->private; + struct drm_device *dev = debug->drm_dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) + seq_printf(m, "%02x", DP_TEST_LINK_VIDEO_PATTERN); + else + seq_puts(m, "0"); + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(dp_test_type); + +static ssize_t dp_test_active_write(struct file *file, + const char __user *ubuf, + size_t len, loff_t *offp) +{ + char *input_buffer; + int status = 0; + struct dp_debug_private *debug; + struct drm_device *dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + int val = 0; + + debug = ((struct seq_file *)file->private_data)->private; + dev = debug->drm_dev; + + if (len == 0) + return 0; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_ERR(input_buffer); + + DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len); + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + status = kstrtoint(input_buffer, 10, &val); + if (status < 0) + break; + DRM_DEBUG_DRIVER("Got %d for test active\n", val); + /* To prevent erroneous activation of the compliance + * testing code, only accept an actual value of 1 here + */ + if (val == 1) + debug->panel->video_test = true; + else + debug->panel->video_test = false; + } + } + drm_connector_list_iter_end(&conn_iter); + kfree(input_buffer); + if (status < 0) + return status; + + *offp += len; + return len; +} + +static int dp_test_active_show(struct seq_file *m, void *data) +{ + struct dp_debug_private *debug = m->private; + struct drm_device *dev = debug->drm_dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->connector_type != + DRM_MODE_CONNECTOR_DisplayPort) + continue; + + if (connector->status == connector_status_connected) { + if (debug->panel->video_test) + seq_puts(m, "1"); + else + seq_puts(m, "0"); + } else + seq_puts(m, "0"); + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} + +static int dp_test_active_open(struct inode *inode, + struct file *file) +{ + return single_open(file, dp_test_active_show, + inode->i_private); +} + static const struct file_operations dp_debug_fops = { .open = simple_open, .read = dp_debug_read_info, }; +static const struct file_operations test_active_fops = { + .owner = THIS_MODULE, + .open = dp_test_active_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = dp_test_active_write +}; + static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) { int rc = 0; struct dp_debug_private *debug = container_of(dp_debug, struct dp_debug_private, dp_debug); struct dentry *file; + struct dentry *test_active; + struct dentry *test_data, *test_type; file = debugfs_create_file("dp_debug", 0444, minor->debugfs_root, debug, &dp_debug_fops); @@ -223,6 +380,33 @@ static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor) DEBUG_NAME, rc); } + test_active = debugfs_create_file("msm_dp_test_active", 0444, + minor->debugfs_root, + debug, &test_active_fops); + if (IS_ERR_OR_NULL(test_active)) { + rc = PTR_ERR(test_active); + DRM_ERROR("[%s] debugfs test_active failed, rc=%d\n", + DEBUG_NAME, rc); + } + + test_data = debugfs_create_file("msm_dp_test_data", 0444, + minor->debugfs_root, + debug, &dp_test_data_fops); + if (IS_ERR_OR_NULL(test_data)) { + rc = PTR_ERR(test_data); + DRM_ERROR("[%s] debugfs test_data failed, rc=%d\n", + DEBUG_NAME, rc); + } + + test_type = debugfs_create_file("msm_dp_test_type", 0444, + minor->debugfs_root, + debug, &dp_test_type_fops); + if (IS_ERR_OR_NULL(test_type)) { + rc = PTR_ERR(test_type); + DRM_ERROR("[%s] debugfs test_type failed, rc=%d\n", + DEBUG_NAME, rc); + } + debug->root = minor->debugfs_root; return rc; diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index e9d54db8fb612..49811b6221e53 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -112,6 +112,29 @@ static inline u32 dp_link_bit_depth_to_bpp(u32 tbd) } } +/** + * dp_test_bit_depth_to_bpc() - convert test bit depth to bpc + * @tbd: test bit depth + * + * Returns the bits per comp (bpc) to be used corresponding to the + * bit depth value. This function assumes that bit depth has + * already been validated. + */ +static inline u32 dp_link_bit_depth_to_bpc(u32 tbd) +{ + switch (tbd) { + case DP_TEST_BIT_DEPTH_6: + return 6; + case DP_TEST_BIT_DEPTH_8: + return 8; + case DP_TEST_BIT_DEPTH_10: + return 10; + case DP_TEST_BIT_DEPTH_UNKNOWN: + default: + return 0; + } +} + u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp); int dp_link_process_request(struct dp_link *dp_link); int dp_link_get_colorimetry_config(struct dp_link *dp_link); -- GitLab From ab205927592be25ddef5db10344925b389fd4344 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Sat, 12 Sep 2020 14:08:15 -0700 Subject: [PATCH 1131/1494] drm/msm/dp: remove mode hard-coding in case of DP CTS No need to fix the number of resolutions to one during the video pattern CTS test. The userspace test client will handle both the hotplug as well as picking the right resolution for the test. Changes in v2: rebase on top of latest patchset of dependency Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_display.c | 3 -- drivers/gpu/drm/msm/dp/dp_link.c | 2 +- drivers/gpu/drm/msm/dp/dp_panel.c | 50 +---------------------------- 3 files changed, 2 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index aa7661f2a441e..94b05e4a25747 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -426,10 +426,7 @@ static int dp_display_usbpd_disconnect_cb(struct device *dev) static void dp_display_handle_video_request(struct dp_display_private *dp) { if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) { - /* force disconnect followed by connect */ - dp->usbpd->connect(dp->usbpd, false); dp->panel->video_test = true; - dp->usbpd->connect(dp->usbpd, true); dp_link_send_test_response(dp->link); } } diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 3cbae92deff0b..ac0e1daea9134 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -1059,8 +1059,8 @@ int dp_link_process_request(struct dp_link *dp_link) } if (dp_link_is_video_pattern_requested(link)) { + ret = 0; dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN; - return -EINVAL; } if (dp_link_is_audio_pattern_requested(link)) { diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 7cdf37c525d85..4e5af59db6ba4 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -128,46 +128,6 @@ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel, return bpp; } -static void dp_panel_set_test_mode(struct dp_panel_private *panel, - struct dp_display_mode *mode) -{ - struct drm_display_mode *drm_mode = NULL; - struct dp_link_test_video *test_info = NULL; - - drm_mode = &mode->drm_mode; - test_info = &panel->link->test_video; - - drm_mode->hdisplay = test_info->test_h_width; - drm_mode->hsync_start = drm_mode->hdisplay + test_info->test_h_total - - (test_info->test_h_start + test_info->test_h_width); - drm_mode->hsync_end = drm_mode->hsync_start + - test_info->test_hsync_width; - drm_mode->htotal = drm_mode->hsync_end + test_info->test_h_start - - test_info->test_hsync_width; - - drm_mode->vdisplay = test_info->test_v_height; - drm_mode->vsync_start = drm_mode->vdisplay + test_info->test_v_total - - (test_info->test_v_start + test_info->test_v_height); - drm_mode->vsync_end = drm_mode->vsync_start + - test_info->test_vsync_width; - drm_mode->vtotal = drm_mode->vsync_end + test_info->test_v_start - - test_info->test_vsync_width; - - drm_mode->clock = test_info->test_h_total * - test_info->test_v_total * test_info->test_rr_n; - - drm_mode->type = 0x48; - drm_mode_set_name(drm_mode); - - if (test_info->test_rr_d == 0) - drm_mode->clock /= 1000; - else - drm_mode->clock /= 1001; - - if (test_info->test_h_width == 640) - drm_mode->clock = 25170; -} - static int dp_panel_update_modes(struct drm_connector *connector, struct edid *edid) { @@ -285,21 +245,13 @@ u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, int dp_panel_get_modes(struct dp_panel *dp_panel, struct drm_connector *connector, struct dp_display_mode *mode) { - struct dp_panel_private *panel; - if (!dp_panel) { DRM_ERROR("invalid input\n"); return -EINVAL; } - panel = container_of(dp_panel, struct dp_panel_private, dp_panel); - - if (dp_panel->video_test) { - dp_panel_set_test_mode(panel, mode); - return 1; - } else if (dp_panel->edid) { + if (dp_panel->edid) return dp_panel_update_modes(connector, dp_panel->edid); - } return 0; } -- GitLab From 937f941ca06f2f3ab64baebf31be2c16d57ae7b8 Mon Sep 17 00:00:00 2001 From: Stephen Boyd <swboyd@chromium.org> Date: Wed, 9 Sep 2020 17:49:02 -0700 Subject: [PATCH 1132/1494] drm/msm/dp: Use qmp phy for DP PLL and PHY Make the necessary changes to the DP driver to use the qmp phy from the common phy framework instead of rolling our own in the drm subsystem. This also removes the PLL code and adds proper includes so things build. Cc: Jeykumar Sankaran <jsanka@codeaurora.org> Cc: Chandan Uddaraju <chandanu@codeaurora.org> Cc: Vara Reddy <varar@codeaurora.org> Cc: Tanmay Shah <tanmay@codeaurora.org> Cc: Bjorn Andersson <bjorn.andersson@linaro.org> Cc: Manu Gautam <mgautam@codeaurora.org> Cc: Sandeep Maheswaram <sanm@codeaurora.org> Cc: Douglas Anderson <dianders@chromium.org> Cc: Sean Paul <seanpaul@chromium.org> Cc: Jonathan Marek <jonathan@marek.ca> Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Cc: Rob Clark <robdclark@chromium.org> Signed-off-by: Stephen Boyd <swboyd@chromium.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Makefile | 2 - drivers/gpu/drm/msm/dp/dp_aux.c | 7 +- drivers/gpu/drm/msm/dp/dp_catalog.c | 287 +------- drivers/gpu/drm/msm/dp/dp_catalog.h | 9 +- drivers/gpu/drm/msm/dp/dp_ctrl.c | 48 +- drivers/gpu/drm/msm/dp/dp_display.c | 17 - drivers/gpu/drm/msm/dp/dp_display.h | 3 - drivers/gpu/drm/msm/dp/dp_link.c | 2 + drivers/gpu/drm/msm/dp/dp_panel.c | 1 + drivers/gpu/drm/msm/dp/dp_parser.c | 12 +- drivers/gpu/drm/msm/dp/dp_parser.h | 12 +- drivers/gpu/drm/msm/dp/dp_pll.c | 99 --- drivers/gpu/drm/msm/dp/dp_pll.h | 61 -- drivers/gpu/drm/msm/dp/dp_pll_10nm.c | 930 ------------------------ drivers/gpu/drm/msm/dp/dp_pll_private.h | 89 --- drivers/gpu/drm/msm/dp/dp_power.c | 39 +- drivers/gpu/drm/msm/dp/dp_power.h | 9 - drivers/gpu/drm/msm/dp/dp_reg.h | 213 ------ 18 files changed, 78 insertions(+), 1762 deletions(-) delete mode 100644 drivers/gpu/drm/msm/dp/dp_pll.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_pll.h delete mode 100644 drivers/gpu/drm/msm/dp/dp_pll_10nm.c delete mode 100644 drivers/gpu/drm/msm/dp/dp_pll_private.h diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 99658a6bf6984..340682cd0f320 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -111,8 +111,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_panel.o \ dp/dp_parser.o \ dp/dp_power.o \ - dp/dp_pll.o \ - dp/dp_pll_10nm.o \ dp/dp_audio.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c index d742b4d870b37..19b35ae3e9272 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 <drm/drm_print.h> #include "dp_reg.h" #include "dp_aux.h" @@ -380,8 +381,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, if (aux->native) { aux->retry_cnt++; if (!(aux->retry_cnt % retry_count)) - dp_catalog_aux_update_cfg(aux->catalog, - PHY_AUX_CFG1); + dp_catalog_aux_update_cfg(aux->catalog); dp_catalog_aux_reset(aux->catalog); } usleep_range(400, 500); /* at least 400us to next try */ @@ -438,7 +438,7 @@ void dp_aux_reconfig(struct drm_dp_aux *dp_aux) aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - dp_catalog_aux_update_cfg(aux->catalog, PHY_AUX_CFG1); + dp_catalog_aux_update_cfg(aux->catalog); dp_catalog_aux_reset(aux->catalog); } @@ -453,7 +453,6 @@ void dp_aux_init(struct drm_dp_aux *dp_aux) aux = container_of(dp_aux, struct dp_aux_private, dp_aux); - dp_catalog_aux_setup(aux->catalog); dp_catalog_aux_enable(aux->catalog, true); aux->retry_cnt = 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 393e3d4431399..b15b4ce4ba35a 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -8,8 +8,11 @@ #include <linux/rational.h> #include <linux/delay.h> #include <linux/iopoll.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-dp.h> #include <linux/rational.h> #include <drm/drm_dp_helper.h> +#include <drm/drm_print.h> #include "dp_catalog.h" #include "dp_reg.h" @@ -52,41 +55,6 @@ #define DP_INTERRUPT_STATUS2_MASK \ (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) -static u8 const vm_pre_emphasis_hbr_rbr[4][4] = { - {0x00, 0x0C, 0x14, 0x19}, - {0x00, 0x0B, 0x12, 0xFF}, - {0x00, 0x0B, 0xFF, 0xFF}, - {0x04, 0xFF, 0xFF, 0xFF} -}; - -static u8 const vm_voltage_swing_hbr_rbr[4][4] = { - {0x08, 0x0F, 0x16, 0x1F}, - {0x11, 0x1E, 0x1F, 0xFF}, - {0x19, 0x1F, 0xFF, 0xFF}, - {0x1F, 0xFF, 0xFF, 0xFF} -}; - -/* AUX look-up-table configurations - * Pair of offset and config values for each LUT - */ -static u8 const aux_lut_offset[] = { - 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, 0x40, 0x44 -}; - -static u8 const -aux_lut_value[PHY_AUX_CFG_MAX][DP_AUX_CFG_MAX_VALUE_CNT] = { - { 0x00, 0x00, 0x00, }, - { 0x13, 0x23, 0x1d, }, - { 0x24, 0x00, 0x00, }, - { 0x00, 0x00, 0x00, }, - { 0x0A, 0x00, 0x00, }, - { 0x26, 0x00, 0x00, }, - { 0x0A, 0x00, 0x00, }, - { 0x03, 0x00, 0x00, }, - { 0xBB, 0x00, 0x00, }, - { 0x03, 0x00, 0x00, } -}; - struct dp_catalog_private { struct device *dev; struct dp_io *io; @@ -129,83 +97,6 @@ static inline void dp_write_ahb(struct dp_catalog_private *catalog, writel(data, catalog->io->dp_controller.base + offset); } -static inline void dp_write_phy(struct dp_catalog_private *catalog, - u32 offset, u32 data) -{ - offset += DP_PHY_REG_OFFSET; - /* - * To make sure phy reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io->phy_reg.base + offset); -} - -static inline u32 dp_read_phy(struct dp_catalog_private *catalog, - u32 offset) -{ - offset += DP_PHY_REG_OFFSET; - /* - * To make sure phy reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - return readl_relaxed(catalog->io->phy_reg.base + offset); -} - -static inline void dp_write_pll(struct dp_catalog_private *catalog, - u32 offset, u32 data) -{ - offset += DP_PHY_PLL_OFFSET; - writel_relaxed(data, catalog->io->phy_reg.base + offset); -} - -static inline void dp_write_ln_tx0(struct dp_catalog_private *catalog, - u32 offset, u32 data) -{ - offset += DP_PHY_LN_TX0_OFFSET; - writel_relaxed(data, catalog->io->phy_reg.base + offset); -} - -static inline void dp_write_ln_tx1(struct dp_catalog_private *catalog, - u32 offset, u32 data) -{ - offset += DP_PHY_LN_TX1_OFFSET; - writel_relaxed(data, catalog->io->phy_reg.base + offset); -} - -static inline u32 dp_read_ln_tx0(struct dp_catalog_private *catalog, - u32 offset) -{ - offset += DP_PHY_LN_TX0_OFFSET; - return readl_relaxed(catalog->io->phy_reg.base + offset); -} - -static inline u32 dp_read_ln_tx1(struct dp_catalog_private *catalog, - u32 offset) -{ - offset += DP_PHY_LN_TX1_OFFSET; - return readl_relaxed(catalog->io->phy_reg.base + offset); -} - -static inline void dp_write_usb_cm(struct dp_catalog_private *catalog, - u32 offset, u32 data) -{ - /* - * To make sure usb reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - writel(data, catalog->io->usb3_dp_com.base + offset); -} - -static inline u32 dp_read_usb_cm(struct dp_catalog_private *catalog, - u32 offset) -{ - /* - * To make sure usb reg writes happens before any other operation, - * this function uses writel() instread of writel_relaxed() - */ - return readl_relaxed(catalog->io->usb3_dp_com.base + offset); -} - static inline void dp_write_p0(struct dp_catalog_private *catalog, u32 offset, u32 data) { @@ -335,27 +226,14 @@ void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable) dp_write_aux(catalog, REG_DP_AUX_CTRL, aux_ctrl); } -void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog, - enum dp_phy_aux_config_type type) +void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - u32 new_index = 0, current_index = 0; + struct dp_io *dp_io = catalog->io; + struct phy *phy = dp_io->phy; - if (type >= PHY_AUX_CFG_MAX) { - DRM_ERROR("invalid input\n"); - return; - } - - current_index = catalog->aux_lut_cfg_index[type]; - new_index = (current_index + 1) % DP_AUX_CFG_MAX_VALUE_CNT; - DRM_DEBUG_DP("Updating PHY_AUX_CFG%d from 0x%08x to 0x%08x\n", - type, aux_lut_value[type][current_index], - aux_lut_value[type][new_index]); - - dp_write_phy(catalog, aux_lut_offset[type], - aux_lut_value[type][new_index]); - catalog->aux_lut_cfg_index[type] = new_index; + phy_calibrate(phy); } static void dump_regs(void __iomem *base, int len) @@ -401,64 +279,6 @@ void dp_catalog_dump_regs(struct dp_catalog *dp_catalog) offset = MSM_DP_CONTROLLER_P0_OFFSET; len = MSM_DP_CONTROLLER_P0_SIZE; dump_regs(catalog->io->dp_controller.base + offset, len); - - pr_info("USB3 DP COM regs\n"); - dump_regs(catalog->io->usb3_dp_com.base, catalog->io->usb3_dp_com.len); - - pr_info("LN TX0 regs\n"); - dump_regs(catalog->io->phy_reg.base + DP_PHY_LN_TX0_OFFSET, - DP_PHY_LN_TX0_SIZE); - - pr_info("LN TX1 regs\n"); - dump_regs(catalog->io->phy_reg.base + DP_PHY_LN_TX1_OFFSET, - DP_PHY_LN_TX1_SIZE); - - pr_info("DP PHY regs\n"); - dump_regs(catalog->io->phy_reg.base + DP_PHY_REG_OFFSET, - DP_PHY_REG_SIZE); -} - -void dp_catalog_aux_setup(struct dp_catalog *dp_catalog) -{ - struct dp_catalog_private *catalog = container_of(dp_catalog, - struct dp_catalog_private, dp_catalog); - int i = 0; - - dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PWRDN | - DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | - DP_PHY_PD_CTL_DP_CLAMP_EN); - - /* Turn on BIAS current for PHY/PLL */ - dp_write_pll(catalog, - QSERDES_COM_BIAS_EN_CLKBUFLR_EN, QSERDES_COM_BIAS_EN | - QSERDES_COM_BIAS_EN_MUX | QSERDES_COM_CLKBUF_L_EN | - QSERDES_COM_EN_SYSCLK_TX_SEL); - - dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PSR_PWRDN); - - dp_write_phy(catalog, REG_DP_PHY_PD_CTL, DP_PHY_PD_CTL_PWRDN | - DP_PHY_PD_CTL_AUX_PWRDN | DP_PHY_PD_CTL_LANE_0_1_PWRDN - | DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN - | DP_PHY_PD_CTL_DP_CLAMP_EN); - - dp_write_pll(catalog, - QSERDES_COM_BIAS_EN_CLKBUFLR_EN, QSERDES_COM_BIAS_EN | - QSERDES_COM_BIAS_EN_MUX | QSERDES_COM_CLKBUF_R_EN | - QSERDES_COM_CLKBUF_L_EN | QSERDES_COM_EN_SYSCLK_TX_SEL | - QSERDES_COM_CLKBUF_RX_DRIVE_L); - - /* DP AUX CFG register programming */ - for (i = 0; i < PHY_AUX_CFG_MAX; i++) { - DRM_DEBUG_DP("PHY_AUX_CFG%ds: offset=0x%08x, value=0x%08x\n", - i, aux_lut_offset[i], aux_lut_value[i][0]); - dp_write_phy(catalog, aux_lut_offset[i], - aux_lut_value[i][0]); - } - - dp_write_phy(catalog, REG_DP_PHY_AUX_INTERRUPT_MASK, - PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | - PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | - PHY_AUX_REQ_ERR_MASK); } int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog) @@ -585,7 +405,7 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, bool fixed_nvid) { u32 pixel_m, pixel_n; - u32 mvid, nvid, div, pixel_div = 0, dispcc_input_rate; + 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; @@ -594,14 +414,11 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - div = dp_read_phy(catalog, REG_DP_PHY_VCO_DIV); - div &= 0x03; - - if (div == 0) + if (rate == link_rate_hbr3) pixel_div = 6; - else if (div == 1) + else if (rate == 1620000 || rate == 270000) pixel_div = 2; - else if (div == 2) + else if (rate == link_rate_hbr2) pixel_div = 4; else DRM_ERROR("Invalid pixel mux divider\n"); @@ -667,36 +484,6 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, return 0; } -void dp_catalog_ctrl_usb_reset(struct dp_catalog *dp_catalog, bool flip) -{ - struct dp_catalog_private *catalog = container_of(dp_catalog, - struct dp_catalog_private, dp_catalog); - u32 typec_ctrl; - - dp_write_usb_cm(catalog, REG_USB3_DP_COM_RESET_OVRD_CTRL, - USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX | - USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX); - dp_write_usb_cm(catalog, REG_USB3_DP_COM_PHY_MODE_CTRL, - USB3_DP_COM_PHY_MODE_DP); - dp_write_usb_cm(catalog, REG_USB3_DP_COM_SW_RESET, - USB3_DP_COM_SW_RESET_SET); - - /* Default configuration i.e CC1 */ - typec_ctrl = USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX; - if (flip) - typec_ctrl |= USB3_DP_COM_TYPEC_CTRL_PORTSEL; - - dp_write_usb_cm(catalog, REG_USB3_DP_COM_TYPEC_CTRL, typec_ctrl); - - dp_write_usb_cm(catalog, REG_USB3_DP_COM_SWI_CTRL, 0x00); - dp_write_usb_cm(catalog, REG_USB3_DP_COM_SW_RESET, 0x00); - - dp_write_usb_cm(catalog, REG_USB3_DP_COM_POWER_DOWN_CTRL, - USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN); - dp_write_usb_cm(catalog, REG_USB3_DP_COM_RESET_OVRD_CTRL, 0x00); - -} - void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog) { u32 sw_reset; @@ -820,58 +607,26 @@ void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog) struct dp_catalog_private, dp_catalog); dp_write_ahb(catalog, REG_DP_PHY_CTRL, - DP_PHY_CTRL_SW_RESET_PLL | DP_PHY_CTRL_SW_RESET); + DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL); usleep_range(1000, 1100); /* h/w recommended delay */ dp_write_ahb(catalog, REG_DP_PHY_CTRL, 0x0); } -void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog *dp_catalog, - bool flipped, u8 ln_cnt) -{ - u32 info; - struct dp_catalog_private *catalog = container_of(dp_catalog, - struct dp_catalog_private, dp_catalog); - u8 orientation = BIT(!!flipped); - - info = ln_cnt & DP_PHY_SPARE0_MASK; - info |= (orientation & DP_PHY_SPARE0_MASK) - << DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT; - DRM_DEBUG_DP("Shared Info = 0x%x\n", info); - - dp_write_phy(catalog, REG_DP_PHY_SPARE0, info); -} - int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, u8 v_level, u8 p_level) { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); - u8 voltage_swing_cfg, pre_emphasis_cfg; - - DRM_DEBUG_DP("hw: v=%d p=%d\n", v_level, p_level); - - voltage_swing_cfg = vm_voltage_swing_hbr_rbr[v_level][p_level]; - pre_emphasis_cfg = vm_pre_emphasis_hbr_rbr[v_level][p_level]; - - if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) { - DRM_ERROR("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n", - v_level, voltage_swing_cfg, p_level, pre_emphasis_cfg); - return -EINVAL; - } + struct dp_io *dp_io = catalog->io; + struct phy *phy = dp_io->phy; + struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; - /* Enable MUX to use Cursor values from these registers */ - voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; - pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; - - /* Configure host and panel only if both values are allowed */ - dp_write_ln_tx0(catalog, REG_DP_PHY_TXn_TX_DRV_LVL, voltage_swing_cfg); - dp_write_ln_tx1(catalog, REG_DP_PHY_TXn_TX_DRV_LVL, voltage_swing_cfg); - dp_write_ln_tx0(catalog, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, - pre_emphasis_cfg); - dp_write_ln_tx1(catalog, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, - pre_emphasis_cfg); - DRM_DEBUG_DP("hw: vx_value=0x%x px_value=0x%x\n", - voltage_swing_cfg, pre_emphasis_cfg); + /* TODO: Update for all lanes instead of just first one */ + opts_dp->voltage[0] = v_level; + opts_dp->pre[0] = p_level; + opts_dp->set_voltages = 1; + phy_configure(phy, &dp_io->phy_opts); + opts_dp->set_voltages = 0; return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h index edb68a65b0fa1..4b7666f1fe6fe 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.h +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h @@ -6,6 +6,8 @@ #ifndef _DP_CATALOG_H_ #define _DP_CATALOG_H_ +#include <drm/drm_modes.h> + #include "dp_parser.h" /* interrupts */ @@ -77,9 +79,7 @@ int dp_catalog_aux_clear_trans(struct dp_catalog *dp_catalog, bool read); int dp_catalog_aux_clear_hw_interrupts(struct dp_catalog *dp_catalog); void dp_catalog_aux_reset(struct dp_catalog *dp_catalog); void dp_catalog_aux_enable(struct dp_catalog *dp_catalog, bool enable); -void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog, - enum dp_phy_aux_config_type type); -void dp_catalog_aux_setup(struct dp_catalog *dp_catalog); +void dp_catalog_aux_update_cfg(struct dp_catalog *dp_catalog); int dp_catalog_aux_get_irq(struct dp_catalog *dp_catalog); /* DP Controller APIs */ @@ -92,7 +92,6 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate, u32 stream_rate_khz, bool fixed_nvid); int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog, u32 pattern); void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog); -void dp_catalog_ctrl_usb_reset(struct dp_catalog *dp_catalog, bool flip); bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable); void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, @@ -100,8 +99,6 @@ void dp_catalog_hpd_config_intr(struct dp_catalog *dp_catalog, void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog); u32 dp_catalog_hpd_get_intr_status(struct dp_catalog *dp_catalog); void dp_catalog_ctrl_phy_reset(struct dp_catalog *dp_catalog); -void dp_catalog_ctrl_phy_lane_cfg(struct dp_catalog *dp_catalog, bool flipped, - u8 lane_cnt); int dp_catalog_ctrl_update_vx_px(struct dp_catalog *dp_catalog, u8 v_level, u8 p_level); int dp_catalog_ctrl_get_interrupt(struct dp_catalog *dp_catalog); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 70b0e06953f63..2e3e1917351f0 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -8,8 +8,11 @@ #include <linux/types.h> #include <linux/completion.h> #include <linux/delay.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-dp.h> #include <drm/drm_fixed.h> #include <drm/drm_dp_helper.h> +#include <drm/drm_print.h> #include "dp_reg.h" #include "dp_ctrl.h" @@ -1302,7 +1305,7 @@ static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl, } static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, - enum dp_pm_type module, char *name, u32 rate) + enum dp_pm_type module, char *name, unsigned long rate) { u32 num = ctrl->parser->mp[module].num_clk; struct dss_clk *cfg = ctrl->parser->mp[module].clk_config; @@ -1312,23 +1315,29 @@ static void dp_ctrl_set_clock_rate(struct dp_ctrl_private *ctrl, cfg++; } - DRM_DEBUG_DP("setting rate=%d on clk=%s\n", rate, name); + DRM_DEBUG_DP("setting rate=%lu on clk=%s\n", rate, name); if (num) cfg->rate = rate; else - DRM_ERROR("%s clock doesn't exit to set rate %d\n", + DRM_ERROR("%s clock doesn't exit to set rate %lu\n", name, rate); } static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) { int ret = 0; + struct dp_io *dp_io = &ctrl->parser->io; + struct phy *phy = dp_io->phy; + struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; - dp_power_set_link_clk_parent(ctrl->power); - + opts_dp->lanes = ctrl->link->link_params.num_lanes; + opts_dp->link_rate = ctrl->link->link_params.rate / 100; dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link", - ctrl->link->link_params.rate); + ctrl->link->link_params.rate * 1000); + + phy_configure(phy, &dp_io->phy_opts); + phy_power_on(phy); ret = dp_power_clk_enable(ctrl->power, DP_CTRL_PM, true); if (ret) @@ -1345,7 +1354,7 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) int ret = 0; dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", - ctrl->dp_ctrl.pixel_rate); + ctrl->dp_ctrl.pixel_rate * 1000); ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); if (ret) @@ -1360,6 +1369,8 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip) { struct dp_ctrl_private *ctrl; + struct dp_io *dp_io; + struct phy *phy; if (!dp_ctrl) { DRM_ERROR("Invalid input data\n"); @@ -1367,11 +1378,13 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip) } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + dp_io = &ctrl->parser->io; + phy = dp_io->phy; ctrl->dp_ctrl.orientation = flip; - dp_catalog_ctrl_usb_reset(ctrl->catalog, flip); dp_catalog_ctrl_phy_reset(ctrl->catalog); + phy_init(phy); dp_catalog_ctrl_enable_irq(ctrl->catalog, true); return 0; @@ -1420,10 +1433,13 @@ static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl) static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) { int ret = 0; + struct dp_io *dp_io = &ctrl->parser->io; + struct phy *phy = dp_io->phy; + struct phy_configure_opts_dp *opts_dp = &dp_io->phy_opts.dp; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); - dp_catalog_ctrl_phy_lane_cfg(ctrl->catalog, - ctrl->dp_ctrl.orientation, ctrl->link->link_params.num_lanes); + opts_dp->lanes = ctrl->link->link_params.num_lanes; + phy_configure(phy, &dp_io->phy_opts); /* * Disable and re-enable the mainlink clock since the * link clock might have been adjusted as part of the @@ -1434,6 +1450,7 @@ static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl) DRM_ERROR("Failed to disable clocks. ret=%d\n", ret); return ret; } + phy_power_off(phy); /* hw recommended delay before re-enabling clocks */ msleep(20); @@ -1622,10 +1639,6 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes, ctrl->dp_ctrl.pixel_rate); - dp_catalog_ctrl_phy_lane_cfg(ctrl->catalog, - ctrl->dp_ctrl.orientation, - ctrl->link->link_params.num_lanes); - rc = dp_ctrl_enable_mainlink_clocks(ctrl); if (rc) return rc; @@ -1763,12 +1776,16 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl) int dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; + struct dp_io *dp_io; + struct phy *phy; int ret = 0; if (!dp_ctrl) return -EINVAL; ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + dp_io = &ctrl->parser->io; + phy = dp_io->phy; dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false); @@ -1783,6 +1800,9 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl) DRM_ERROR("Failed to disable link clocks. ret=%d\n", ret); } + phy_power_off(phy); + phy_exit(phy); + DRM_DEBUG_DP("DP off done\n"); return ret; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 94b05e4a25747..05a97e097edf3 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -24,7 +24,6 @@ #include "dp_ctrl.h" #include "dp_display.h" #include "dp_drm.h" -#include "dp_pll.h" #include "dp_audio.h" #include "dp_debug.h" @@ -91,7 +90,6 @@ struct dp_display_private { struct dp_usbpd *usbpd; struct dp_parser *parser; - struct msm_dp_pll *pll; struct dp_power *power; struct dp_catalog *catalog; struct drm_dp_aux *aux; @@ -659,7 +657,6 @@ static void dp_display_deinit_sub_modules(struct dp_display_private *dp) dp_ctrl_put(dp->ctrl); dp_panel_put(dp->panel); dp_aux_put(dp->aux); - dp_pll_put(dp->pll); dp_audio_put(dp->audio); } @@ -671,9 +668,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp) struct dp_panel_in panel_in = { .dev = dev, }; - struct dp_pll_in pll_in = { - .pdev = dp->pdev, - }; /* Callback APIs used for cable status change event */ cb->configure = dp_display_usbpd_configure_cb; @@ -704,17 +698,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp) goto error; } - pll_in.parser = dp->parser; - dp->pll = dp_pll_get(&pll_in); - if (IS_ERR_OR_NULL(dp->pll)) { - rc = -EINVAL; - DRM_ERROR("failed to initialize pll, rc = %d\n", rc); - dp->pll = NULL; - goto error; - } - - dp->parser->pll = dp->pll; - dp->power = dp_power_get(dp->parser); if (IS_ERR(dp->power)) { rc = PTR_ERR(dp->power); diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index 8b78b40bbd6c6..6092ba1ed85ed 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -36,7 +36,4 @@ bool dp_display_check_video_test(struct msm_dp *dp_display); int dp_display_get_test_bpp(struct msm_dp *dp_display); void dp_display_signal_audio_complete(struct msm_dp *dp_display); -void __init msm_dp_pll_driver_register(void); -void __exit msm_dp_pll_driver_unregister(void); - #endif /* _DP_DISPLAY_H_ */ diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index ac0e1daea9134..c811da515fb3b 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -5,6 +5,8 @@ #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ +#include <drm/drm_print.h> + #include "dp_link.h" #include "dp_panel.h" diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 4e5af59db6ba4..18cec4fc5e0ba 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -7,6 +7,7 @@ #include <drm/drm_connector.h> #include <drm/drm_edid.h> +#include <drm/drm_print.h> struct dp_panel_private { struct device *dev; diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 255a800535d57..0519dd3ac3c3b 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -4,6 +4,9 @@ */ #include <linux/of_gpio.h> +#include <linux/phy/phy.h> + +#include <drm/drm_print.h> #include "dp_parser.h" #include "dp_reg.h" @@ -53,8 +56,6 @@ static void dp_parser_unmap_io_resources(struct dp_parser *parser) struct dp_io *io = &parser->io; msm_dss_iounmap(&io->dp_controller); - msm_dss_iounmap(&io->phy_reg); - msm_dss_iounmap(&io->usb3_dp_com); } static int dp_parser_ctrl_res(struct dp_parser *parser) @@ -69,6 +70,12 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) goto err; } + io->phy = devm_phy_get(&pdev->dev, "dp"); + if (IS_ERR(io->phy)) { + rc = PTR_ERR(io->phy); + goto err; + } + return 0; err: dp_parser_unmap_io_resources(parser); @@ -90,7 +97,6 @@ static int dp_parser_misc(struct dp_parser *parser) } parser->max_dp_lanes = len; - return 0; } diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 841e776124c4e..34b49628bbaf4 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -7,10 +7,11 @@ #define _DP_PARSER_H_ #include <linux/platform_device.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-dp.h> #include "dpu_io_util.h" #include "msm_drv.h" -#include "dp_pll.h" #define DP_LABEL "MDSS DP DISPLAY" #define DP_MAX_PIXEL_CLK_KHZ 675000 @@ -62,15 +63,11 @@ struct dp_display_data { * * @dp_controller: Display Port controller mapped memory address * @phy_io: phy's mapped memory address - * @ln_tx0_io: USB-DP lane TX0's mapped memory address - * @ln_tx1_io: USB-DP lane TX1's mapped memory address - * @dp_pll_io: DP PLL mapped memory address - * @usb3_dp_com: USB3 DP PHY combo mapped memory address */ struct dp_io { struct dss_io_data dp_controller; - struct dss_io_data phy_reg; - struct dss_io_data usb3_dp_com; + struct phy *phy; + union phy_configure_opts phy_opts; }; /** @@ -117,7 +114,6 @@ struct dp_parser { struct dp_pinctrl pinctrl; struct dp_io io; struct dp_display_data disp_data; - struct msm_dp_pll *pll; const struct dp_regulator_cfg *regulator_cfg; u32 max_dp_lanes; diff --git a/drivers/gpu/drm/msm/dp/dp_pll.c b/drivers/gpu/drm/msm/dp/dp_pll.c deleted file mode 100644 index 53f82cd970277..0000000000000 --- a/drivers/gpu/drm/msm/dp/dp_pll.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - */ - -#include <linux/device.h> - -#include "dp_parser.h" -#include "dp_pll.h" -#include "dp_pll_private.h" - -static int dp_pll_get_phy_io(struct dp_parser *parser) -{ - struct dp_io *io = &parser->io; - - io->usb3_dp_com.base = ioremap(REG_USB3_DP_COM_REGION_BASE, - REG_USB3_DP_COM_REGION_SIZE); - if (!io->usb3_dp_com.base) { - DRM_ERROR("unable to map USB3 DP COM IO\n"); - return -EIO; - } - - /* ToDo(user): DP PLL and DP PHY will not be part of - * DP driver eventually so for now Hardcode Base and offsets - * of PHY registers so we can remove them from dts and bindings - */ - io->phy_reg.base = ioremap(REG_DP_PHY_REGION_BASE, - REG_DP_PHY_REGION_SIZE); - if (!io->phy_reg.base) { - DRM_ERROR("DP PHY io region mapping failed\n"); - return -EIO; - } - io->phy_reg.len = REG_DP_PHY_REGION_SIZE; - - return 0; -} - -static int msm_dp_pll_init(struct msm_dp_pll *pll, - enum msm_dp_pll_type type, int id) -{ - struct device *dev = &pll->pdev->dev; - int ret = 0; - - switch (type) { - case MSM_DP_PLL_10NM: - ret = msm_dp_pll_10nm_init(pll, id); - break; - default: - DRM_DEV_ERROR(dev, "%s: Wrong PLL type %d\n", __func__, type); - return -ENXIO; - } - - if (ret) { - DRM_DEV_ERROR(dev, "%s: failed to init DP PLL\n", __func__); - return ret; - } - - pll->type = type; - - DRM_DEBUG_DP("DP:%d PLL registered", id); - - return ret; -} - -struct msm_dp_pll *dp_pll_get(struct dp_pll_in *pll_in) -{ - struct msm_dp_pll *dp_pll; - struct dp_parser *parser = pll_in->parser; - struct dp_io_pll *pll_io; - int ret; - - dp_pll = devm_kzalloc(&pll_in->pdev->dev, sizeof(*dp_pll), GFP_KERNEL); - if (!dp_pll) - return ERR_PTR(-ENOMEM); - - pll_io = &dp_pll->pll_io; - dp_pll->pdev = pll_in->pdev; - - dp_pll_get_phy_io(parser); - - pll_io->pll_base = parser->io.phy_reg.base + DP_PHY_PLL_OFFSET; - pll_io->phy_base = parser->io.phy_reg.base + DP_PHY_REG_OFFSET; - pll_io->ln_tx0_base = parser->io.phy_reg.base + DP_PHY_LN_TX0_OFFSET; - pll_io->ln_tx1_base = parser->io.phy_reg.base + DP_PHY_LN_TX1_OFFSET; - - ret = msm_dp_pll_init(dp_pll, MSM_DP_PLL_10NM, 0); - if (ret) { - kfree(dp_pll); - return ERR_PTR(ret); - } - - return dp_pll; -} - -void dp_pll_put(struct msm_dp_pll *dp_pll) -{ - if (dp_pll->type == MSM_DP_PLL_10NM) - msm_dp_pll_10nm_deinit(dp_pll); -} diff --git a/drivers/gpu/drm/msm/dp/dp_pll.h b/drivers/gpu/drm/msm/dp/dp_pll.h deleted file mode 100644 index 5a10c8f3cfeae..0000000000000 --- a/drivers/gpu/drm/msm/dp/dp_pll.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - */ - -#ifndef __DP_PLL_H -#define __DP_PLL_H - -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/platform_device.h> - -#include "dpu_io_util.h" -#include "msm_drv.h" -#include "dp_parser.h" - -#define PLL_REG_W(base, offset, data) \ - writel((data), (base) + (offset)) -#define PLL_REG_R(base, offset) readl((base) + (offset)) - -enum msm_dp_pll_type { - MSM_DP_PLL_10NM, - MSM_DP_PLL_MAX -}; - -struct dp_pll_in { - struct platform_device *pdev; - struct dp_parser *parser; -}; - -struct dp_io_pll { - void __iomem *pll_base; - void __iomem *phy_base; - void __iomem *ln_tx0_base; - void __iomem *ln_tx1_base; -}; - -struct msm_dp_pll { - enum msm_dp_pll_type type; - bool pll_on; - - struct dp_io_pll pll_io; - - /* clock-provider: */ - struct clk_hw_onecell_data *hw_data; - - struct platform_device *pdev; - void *priv; - - /* Pll specific resources like GPIO, power supply, clocks, etc*/ - struct dss_module_power mp; - int (*get_provider)(struct msm_dp_pll *pll, - struct clk **link_clk_provider, - struct clk **pixel_clk_provider); -}; - -struct msm_dp_pll *dp_pll_get(struct dp_pll_in *pll_in); - -void dp_pll_put(struct msm_dp_pll *dp_pll); - -#endif /* __DP_PLL_H */ diff --git a/drivers/gpu/drm/msm/dp/dp_pll_10nm.c b/drivers/gpu/drm/msm/dp/dp_pll_10nm.c deleted file mode 100644 index a2bf2fc24d6af..0000000000000 --- a/drivers/gpu/drm/msm/dp/dp_pll_10nm.c +++ /dev/null @@ -1,930 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - */ - -/* - * Display Port PLL driver block diagram for branch clocks - * - * +------------------------------+ - * | DP_VCO_CLK | - * | | - * | +-------------------+ | - * | | (DP PLL/VCO) | | - * | +---------+---------+ | - * | v | - * | +----------+-----------+ | - * | | hsclk_divsel_clk_src | | - * | +----------+-----------+ | - * +------------------------------+ - * | - * +---------<---------v------------>----------+ - * | | - * +--------v---------+ | - * | dp_phy_pll | | - * | link_clk | | - * +--------+---------+ | - * | | - * | | - * v v - * Input to DISPCC block | - * for link clk, crypto clk | - * and interface clock | - * | - * | - * +--------<------------+-----------------+---<---+ - * | | | - * +----v---------+ +--------v-----+ +--------v------+ - * | vco_divided | | vco_divided | | vco_divided | - * | _clk_src | | _clk_src | | _clk_src | - * | | | | | | - * |divsel_six | | divsel_two | | divsel_four | - * +-------+------+ +-----+--------+ +--------+------+ - * | | | - * v---->----------v-------------<------v - * | - * +----------+---------+ - * | dp_phy_pll_vco | - * | div_clk | - * +---------+----------+ - * | - * v - * Input to DISPCC block - * for DP pixel clock - * - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/regmap.h> -#include <linux/iopoll.h> - -#include "dp_hpd.h" -#include "dp_pll.h" -#include "dp_pll_private.h" - -#define NUM_PROVIDED_CLKS 2 - -#define DP_LINK_CLK_SRC 0 -#define DP_PIXEL_CLK_SRC 1 - - -static int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate); - -static unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, - unsigned long parent_rate); - -static long dp_vco_round_rate_10nm(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate); - -static int dp_vco_prepare_10nm(struct clk_hw *hw); -static void dp_vco_unprepare_10nm(struct clk_hw *hw); - -static struct dp_pll_db *dp_pdb; - -static const struct clk_ops dp_10nm_vco_clk_ops = { - .recalc_rate = dp_vco_recalc_rate_10nm, - .set_rate = dp_vco_set_rate_10nm, - .round_rate = dp_vco_round_rate_10nm, - .prepare = dp_vco_prepare_10nm, - .unprepare = dp_vco_unprepare_10nm, -}; - -struct dp_pll_10nm_pclksel { - struct clk_hw hw; - - /* divider params */ - u8 shift; - u8 width; - u8 flags; /* same flags as used by clk_divider struct */ - - struct dp_pll_db *pll; -}; - -#define to_pll_10nm_pclksel(_hw) \ - container_of(_hw, struct dp_pll_10nm_pclksel, hw) - -static const struct clk_parent_data disp_cc_parent_data_0[] = { - { .fw_name = "bi_tcxo" }, - { .fw_name = "dp_phy_pll_link_clk", .name = "dp_phy_pll_link_clk" }, - { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, -}; - -static struct dp_pll_vco_clk dp_vco_clk = { - .min_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000, - .max_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000, -}; - -static int dp_pll_mux_set_parent_10nm(struct clk_hw *hw, u8 val) -{ - struct dp_pll_10nm_pclksel *pclksel = to_pll_10nm_pclksel(hw); - struct dp_pll_db *dp_res = pclksel->pll; - struct dp_io_pll *pll_io = &dp_res->base->pll_io; - u32 auxclk_div; - - auxclk_div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_VCO_DIV); - auxclk_div &= ~0x03; - - if (val == 0) - auxclk_div |= 1; - else if (val == 1) - auxclk_div |= 2; - else if (val == 2) - auxclk_div |= 0; - - PLL_REG_W(pll_io->phy_base, - REG_DP_PHY_VCO_DIV, auxclk_div); - DRM_DEBUG_DP("%s: mux=%d auxclk_div=%x\n", __func__, val, auxclk_div); - - return 0; -} - -static u8 dp_pll_mux_get_parent_10nm(struct clk_hw *hw) -{ - u32 auxclk_div = 0; - struct dp_pll_10nm_pclksel *pclksel = to_pll_10nm_pclksel(hw); - struct dp_pll_db *dp_res = pclksel->pll; - struct dp_io_pll *pll_io = &dp_res->base->pll_io; - u8 val = 0; - - auxclk_div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_VCO_DIV); - auxclk_div &= 0x03; - - if (auxclk_div == 1) /* Default divider */ - val = 0; - else if (auxclk_div == 2) - val = 1; - else if (auxclk_div == 0) - val = 2; - - DRM_DEBUG_DP("%s: auxclk_div=%d, val=%d\n", __func__, auxclk_div, val); - - return val; -} - -static int dp_pll_clk_mux_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - unsigned long rate = 0; - - rate = clk_get_rate(hw->clk); - - if (rate <= 0) { - DRM_ERROR("Rate is not set properly\n"); - return -EINVAL; - } - - req->rate = rate; - - DRM_DEBUG_DP("%s: rate=%ld\n", __func__, req->rate); - return 0; -} - -static unsigned long dp_pll_mux_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_hw *div_clk_hw = NULL, *vco_clk_hw = NULL; - struct dp_pll_vco_clk *vco; - - div_clk_hw = clk_hw_get_parent(hw); - if (!div_clk_hw) - return 0; - - vco_clk_hw = clk_hw_get_parent(div_clk_hw); - if (!vco_clk_hw) - return 0; - - vco = to_dp_vco_hw(vco_clk_hw); - if (!vco) - return 0; - - if (vco->rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) - return (vco->rate / 6); - else if (vco->rate == DP_VCO_HSCLK_RATE_5400MHZDIV1000) - return (vco->rate / 4); - else - return (vco->rate / 2); -} - -static int dp_pll_10nm_get_provider(struct msm_dp_pll *pll, - struct clk **link_clk_provider, - struct clk **pixel_clk_provider) -{ - struct clk_hw_onecell_data *hw_data = pll->hw_data; - - if (link_clk_provider) - *link_clk_provider = hw_data->hws[DP_LINK_CLK_SRC]->clk; - if (pixel_clk_provider) - *pixel_clk_provider = hw_data->hws[DP_PIXEL_CLK_SRC]->clk; - - return 0; -} - -static const struct clk_ops dp_10nm_pclksel_clk_ops = { - .get_parent = dp_pll_mux_get_parent_10nm, - .set_parent = dp_pll_mux_set_parent_10nm, - .recalc_rate = dp_pll_mux_recalc_rate, - .determine_rate = dp_pll_clk_mux_determine_rate, -}; - -static struct clk_hw *dp_pll_10nm_pixel_clk_sel(struct dp_pll_db *pll_10nm) -{ - struct device *dev = &pll_10nm->pdev->dev; - struct dp_pll_10nm_pclksel *pll_pclksel; - struct clk_init_data pclksel_init = { - .parent_data = disp_cc_parent_data_0, - .num_parents = 3, - .name = "dp_phy_pll_vco_div_clk", - .ops = &dp_10nm_pclksel_clk_ops, - }; - int ret; - - pll_pclksel = devm_kzalloc(dev, sizeof(*pll_pclksel), GFP_KERNEL); - if (!pll_pclksel) - return ERR_PTR(-ENOMEM); - - pll_pclksel->pll = pll_10nm; - pll_pclksel->shift = 0; - pll_pclksel->width = 4; - pll_pclksel->hw.init = &pclksel_init; - - ret = clk_hw_register(dev, &pll_pclksel->hw); - if (ret) - return ERR_PTR(ret); - - return &pll_pclksel->hw; -} - -static void dp_pll_10nm_unregister(struct dp_pll_db *pll_10nm) -{ - int i = 0; - struct clk_hw **hws; - - hws = pll_10nm->hws; - - for (i = 0; i < pll_10nm->num_hws; i++) { - if (pll_10nm->fixed_factor_clk[i] == true) - clk_hw_unregister_fixed_factor(hws[i]); - else - clk_hw_unregister(hws[i]); - } -} - -static int dp_pll_10nm_register(struct dp_pll_db *pll_10nm) -{ - struct clk_hw_onecell_data *hw_data; - int ret = 0; - struct clk_hw *hw; - - struct msm_dp_pll *pll = pll_10nm->base; - struct device *dev = &pll_10nm->pdev->dev; - struct clk_hw **hws = pll_10nm->hws; - int num = 0; - - struct clk_init_data vco_init = { - .parent_data = &(const struct clk_parent_data){ - .fw_name = "bi_tcxo", - }, - .num_parents = 1, - .name = "dp_vco_clk", - .ops = &dp_10nm_vco_clk_ops, - }; - - if (!dev) { - DRM_ERROR("DP dev node not available\n"); - return 0; - } - - DRM_DEBUG_DP("DP->id = %d", pll_10nm->id); - - hw_data = devm_kzalloc(dev, sizeof(*hw_data) + - NUM_PROVIDED_CLKS * sizeof(struct clk_hw *), - GFP_KERNEL); - if (!hw_data) - return -ENOMEM; - - dp_vco_clk.hw.init = &vco_init; - ret = clk_hw_register(dev, &dp_vco_clk.hw); - if (ret) - return ret; - hws[num++] = &dp_vco_clk.hw; - - hw = clk_hw_register_fixed_factor(dev, "dp_phy_pll_link_clk", - "dp_vco_clk", CLK_SET_RATE_PARENT, 1, 10); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - pll_10nm->fixed_factor_clk[num] = true; - hws[num++] = hw; - hw_data->hws[DP_LINK_CLK_SRC] = hw; - - hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_two_clk_src", - "dp_vco_clk", 0, 1, 2); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - pll_10nm->fixed_factor_clk[num] = true; - hws[num++] = hw; - - hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_four_clk_src", - "dp_vco_clk", 0, 1, 4); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - pll_10nm->fixed_factor_clk[num] = true; - hws[num++] = hw; - - hw = clk_hw_register_fixed_factor(dev, "dp_vco_divsel_six_clk_src", - "dp_vco_clk", 0, 1, 6); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - pll_10nm->fixed_factor_clk[num] = true; - hws[num++] = hw; - - hw = dp_pll_10nm_pixel_clk_sel(pll_10nm); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - hws[num++] = hw; - hw_data->hws[DP_PIXEL_CLK_SRC] = hw; - - pll_10nm->num_hws = num; - - hw_data->num = NUM_PROVIDED_CLKS; - pll->hw_data = hw_data; - - ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, - pll->hw_data); - if (ret) { - DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", - ret); - return ret; - } - - return ret; -} - -void msm_dp_pll_10nm_deinit(struct msm_dp_pll *pll) -{ - dp_pll_10nm_unregister(pll->priv); -} - -int msm_dp_pll_10nm_init(struct msm_dp_pll *pll, int id) -{ - struct dp_pll_db *dp_10nm_pll; - struct platform_device *pdev = pll->pdev; - int ret; - - dp_10nm_pll = devm_kzalloc(&pdev->dev, - sizeof(*dp_10nm_pll), GFP_KERNEL); - if (!dp_10nm_pll) - return -ENOMEM; - - DRM_DEBUG_DP("DP PLL%d", id); - - dp_10nm_pll->base = pll; - dp_10nm_pll->pdev = pll->pdev; - dp_10nm_pll->id = id; - dp_pdb = dp_10nm_pll; - pll->priv = (void *)dp_10nm_pll; - dp_vco_clk.priv = pll; - dp_10nm_pll->index = 0; - - ret = dp_pll_10nm_register(dp_10nm_pll); - if (ret) { - DRM_DEV_ERROR(&pdev->dev, "failed to register PLL: %d\n", ret); - return ret; - } - - pll->get_provider = dp_pll_10nm_get_provider; - - return ret; -} - -static int dp_vco_pll_init_db_10nm(struct msm_dp_pll *pll, - unsigned long rate) -{ - u32 spare_value = 0; - struct dp_io_pll *pll_io; - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - pll_io = &pll->pll_io; - spare_value = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_SPARE0); - dp_res->lane_cnt = spare_value & 0x0F; - dp_res->orientation = (spare_value & 0xF0) >> 4; - - DRM_DEBUG_DP("%s: spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", - __func__, spare_value, dp_res->lane_cnt, - dp_res->orientation); - - switch (rate) { - case DP_VCO_HSCLK_RATE_1620MHZDIV1000: - DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_9720MHZDIV1000); - dp_res->hsclk_sel = 0x0c; - dp_res->dec_start_mode0 = 0x69; - dp_res->div_frac_start1_mode0 = 0x00; - dp_res->div_frac_start2_mode0 = 0x80; - dp_res->div_frac_start3_mode0 = 0x07; - dp_res->integloop_gain0_mode0 = 0x3f; - dp_res->integloop_gain1_mode0 = 0x00; - dp_res->vco_tune_map = 0x00; - dp_res->lock_cmp1_mode0 = 0x6f; - dp_res->lock_cmp2_mode0 = 0x08; - dp_res->lock_cmp3_mode0 = 0x00; - dp_res->phy_vco_div = 0x1; - dp_res->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_2700MHZDIV1000: - DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_10800MHZDIV1000); - dp_res->hsclk_sel = 0x04; - dp_res->dec_start_mode0 = 0x69; - dp_res->div_frac_start1_mode0 = 0x00; - dp_res->div_frac_start2_mode0 = 0x80; - dp_res->div_frac_start3_mode0 = 0x07; - dp_res->integloop_gain0_mode0 = 0x3f; - dp_res->integloop_gain1_mode0 = 0x00; - dp_res->vco_tune_map = 0x00; - dp_res->lock_cmp1_mode0 = 0x0f; - dp_res->lock_cmp2_mode0 = 0x0e; - dp_res->lock_cmp3_mode0 = 0x00; - dp_res->phy_vco_div = 0x1; - dp_res->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_5400MHZDIV1000: - DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_10800MHZDIV1000); - dp_res->hsclk_sel = 0x00; - dp_res->dec_start_mode0 = 0x8c; - dp_res->div_frac_start1_mode0 = 0x00; - dp_res->div_frac_start2_mode0 = 0x00; - dp_res->div_frac_start3_mode0 = 0x0a; - dp_res->integloop_gain0_mode0 = 0x3f; - dp_res->integloop_gain1_mode0 = 0x00; - dp_res->vco_tune_map = 0x00; - dp_res->lock_cmp1_mode0 = 0x1f; - dp_res->lock_cmp2_mode0 = 0x1c; - dp_res->lock_cmp3_mode0 = 0x00; - dp_res->phy_vco_div = 0x2; - dp_res->lock_cmp_en = 0x00; - break; - case DP_VCO_HSCLK_RATE_8100MHZDIV1000: - DRM_DEBUG_DP("%s: VCO rate: %ld\n", __func__, - DP_VCO_RATE_8100MHZDIV1000); - dp_res->hsclk_sel = 0x03; - dp_res->dec_start_mode0 = 0x69; - dp_res->div_frac_start1_mode0 = 0x00; - dp_res->div_frac_start2_mode0 = 0x80; - dp_res->div_frac_start3_mode0 = 0x07; - dp_res->integloop_gain0_mode0 = 0x3f; - dp_res->integloop_gain1_mode0 = 0x00; - dp_res->vco_tune_map = 0x00; - dp_res->lock_cmp1_mode0 = 0x2f; - dp_res->lock_cmp2_mode0 = 0x2a; - dp_res->lock_cmp3_mode0 = 0x00; - dp_res->phy_vco_div = 0x0; - dp_res->lock_cmp_en = 0x08; - break; - default: - return -EINVAL; - } - return 0; -} - -static int dp_config_vco_rate_10nm(struct dp_pll_vco_clk *vco, - unsigned long rate) -{ - u32 res = 0; - struct msm_dp_pll *pll = vco->priv; - struct dp_io_pll *pll_io = &pll->pll_io; - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - res = dp_vco_pll_init_db_10nm(pll, rate); - if (res) { - DRM_ERROR("VCO Init DB failed\n"); - return res; - } - - if (dp_res->lane_cnt != 4) { - if (dp_res->orientation == ORIENTATION_CC2) - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x6d); - else - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x75); - } else { - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_PD_CTL, 0x7d); - } - - PLL_REG_W(pll_io->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x06); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CLK_SEL, 0x30); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); - - /* Different for each clock rates */ - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_HSCLK_SEL, dp_res->hsclk_sel); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_DEC_START_MODE0, dp_res->dec_start_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_DIV_FRAC_START1_MODE0, - dp_res->div_frac_start1_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_DIV_FRAC_START2_MODE0, - dp_res->div_frac_start2_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_DIV_FRAC_START3_MODE0, - dp_res->div_frac_start3_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_INTEGLOOP_GAIN0_MODE0, - dp_res->integloop_gain0_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_INTEGLOOP_GAIN1_MODE0, - dp_res->integloop_gain1_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_VCO_TUNE_MAP, dp_res->vco_tune_map); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_LOCK_CMP1_MODE0, dp_res->lock_cmp1_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_LOCK_CMP2_MODE0, dp_res->lock_cmp2_mode0); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_LOCK_CMP3_MODE0, dp_res->lock_cmp3_mode0); - - PLL_REG_W(pll_io->pll_base, QSERDES_COM_BG_TIMER, 0x0a); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CORECLK_DIV_MODE0, 0x0a); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x3f); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CORE_CLK_EN, 0x1f); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_IVCO, 0x07); - PLL_REG_W(pll_io->pll_base, - QSERDES_COM_LOCK_CMP_EN, dp_res->lock_cmp_en); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); - PLL_REG_W(pll_io->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x06); - - if (dp_res->orientation == ORIENTATION_CC2) - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_MODE, 0x4c); - else - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_MODE, 0x5c); - - /* TX Lane configuration */ - PLL_REG_W(pll_io->phy_base, - REG_DP_PHY_TX0_TX1_LANE_CTL, 0x05); - PLL_REG_W(pll_io->phy_base, - REG_DP_PHY_TX2_TX3_LANE_CTL, 0x05); - - /* TX-0 register configuration */ - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, 0x1a); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_VMODE_CTRL1, 0x40); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_INTERFACE_SELECT, 0x3d); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_CLKBUF_ENABLE, 0x0f); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_RESET_TSYNC_EN, 0x03); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN, 0x03); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_TX_INTERFACE_MODE, 0x00); - PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_BAND, 0x4); - - /* TX-1 register configuration */ - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, 0x1a); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_VMODE_CTRL1, 0x40); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN, 0x30); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_INTERFACE_SELECT, 0x3d); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_CLKBUF_ENABLE, 0x0f); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_RESET_TSYNC_EN, 0x03); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN, 0x03); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TX_INTERFACE_MODE, 0x00); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TX_BAND, 0x4); - - /* dependent on the vco frequency */ - PLL_REG_W(pll_io->phy_base, - REG_DP_PHY_VCO_DIV, dp_res->phy_vco_div); - - return res; -} - -static bool dp_10nm_pll_lock_status(struct dp_pll_db *dp_res) -{ - u32 status; - bool pll_locked; - struct dp_io_pll *pll_io = &dp_res->base->pll_io; - - /* poll for PLL lock status */ - if (readl_poll_timeout_atomic((pll_io->pll_base + - QSERDES_COM_C_READY_STATUS), - status, - ((status & BIT(0)) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - DRM_ERROR("%s: C_READY status is not high. Status=%x\n", - __func__, status); - pll_locked = false; - } else { - pll_locked = true; - } - - return pll_locked; -} - -static bool dp_10nm_phy_rdy_status(struct dp_pll_db *dp_res) -{ - u32 status; - bool phy_ready = true; - struct dp_io_pll *pll_io = &dp_res->base->pll_io; - - /* poll for PHY ready status */ - if (readl_poll_timeout_atomic((pll_io->phy_base + - REG_DP_PHY_STATUS), - status, - ((status & (BIT(1))) > 0), - DP_PHY_PLL_POLL_SLEEP_US, - DP_PHY_PLL_POLL_TIMEOUT_US)) { - DRM_ERROR("%s: Phy_ready is not high. Status=%x\n", - __func__, status); - phy_ready = false; - } - - return phy_ready; -} - -static int dp_pll_enable_10nm(struct clk_hw *hw) -{ - int rc = 0; - u32 bias_en, drvr_en; - struct dp_io_pll *pll_io; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct msm_dp_pll *pll = to_msm_dp_pll(vco); - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - pll_io = &pll->pll_io; - - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_AUX_CFG2, 0x04); - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x01); - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x05); - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x01); - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x09); - - PLL_REG_W(pll_io->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); - - if (!dp_10nm_pll_lock_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x19); - /* poll for PHY ready status */ - if (!dp_10nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - DRM_DEBUG_DP("%s: PLL is locked\n", __func__); - - if (dp_res->lane_cnt == 1) { - bias_en = 0x3e; - drvr_en = 0x13; - } else { - bias_en = 0x3f; - drvr_en = 0x10; - } - - if (dp_res->lane_cnt != 4) { - if (dp_res->orientation == ORIENTATION_CC1) { - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); - } else { - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - } else { - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_HIGHZ_DRVR_EN, drvr_en); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN, bias_en); - } - - PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_POL_INV, 0x0a); - PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_POL_INV, 0x0a); - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x18); - udelay(2000); - - PLL_REG_W(pll_io->phy_base, REG_DP_PHY_CFG, 0x19); - - /* poll for PHY ready status */ - if (!dp_10nm_phy_rdy_status(dp_res)) { - rc = -EINVAL; - goto lock_err; - } - - PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_DRV_LVL, 0x38); - PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_DRV_LVL, 0x38); - PLL_REG_W(pll_io->ln_tx0_base, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, 0x20); - PLL_REG_W(pll_io->ln_tx1_base, REG_DP_PHY_TXn_TX_EMP_POST1_LVL, 0x20); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX, 0x06); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX, 0x06); - PLL_REG_W(pll_io->ln_tx0_base, - REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX, 0x07); - PLL_REG_W(pll_io->ln_tx1_base, - REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX, 0x07); - -lock_err: - return rc; -} - -static int dp_pll_disable_10nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct msm_dp_pll *pll = to_msm_dp_pll(vco); - - /* Assert DP PHY power down */ - PLL_REG_W(pll->pll_io.phy_base, REG_DP_PHY_PD_CTL, 0x2); - - return rc; -} - - -static int dp_vco_prepare_10nm(struct clk_hw *hw) -{ - int rc = 0; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct msm_dp_pll *pll = (struct msm_dp_pll *)vco->priv; - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - DRM_DEBUG_DP("%s: rate = %ld\n", __func__, vco->rate); - if ((dp_res->vco_cached_rate != 0) - && (dp_res->vco_cached_rate == vco->rate)) { - rc = dp_vco_set_rate_10nm(hw, - dp_res->vco_cached_rate, dp_res->vco_cached_rate); - if (rc) { - DRM_ERROR("index=%d vco_set_rate failed. rc=%d\n", - rc, dp_res->index); - goto error; - } - } - - rc = dp_pll_enable_10nm(hw); - if (rc) { - DRM_ERROR("ndx=%d failed to enable dp pll\n", - dp_res->index); - goto error; - } - - pll->pll_on = true; -error: - return rc; -} - -static void dp_vco_unprepare_10nm(struct clk_hw *hw) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct msm_dp_pll *pll = to_msm_dp_pll(vco); - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - if (!dp_res) { - DRM_ERROR("Invalid input parameter\n"); - return; - } - - if (!pll->pll_on) { - DRM_ERROR("pll resource can't be enabled\n"); - return; - } - dp_res->vco_cached_rate = vco->rate; - dp_pll_disable_10nm(hw); - - pll->pll_on = false; -} - -static int dp_vco_set_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - int rc; - - DRM_DEBUG_DP("DP lane CLK rate=%ld\n", rate); - - rc = dp_config_vco_rate_10nm(vco, rate); - if (rc) - DRM_ERROR("%s: Failed to set clk rate\n", __func__); - - vco->rate = rate; - - return 0; -} - -static unsigned long dp_vco_recalc_rate_10nm(struct clk_hw *hw, - unsigned long parent_rate) -{ - u32 div, hsclk_div, link_clk_div = 0; - u64 vco_rate; - struct dp_io_pll *pll_io; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - struct msm_dp_pll *pll = to_msm_dp_pll(vco); - struct dp_pll_db *dp_res = to_dp_pll_db(pll); - - pll_io = &pll->pll_io; - - div = PLL_REG_R(pll_io->pll_base, QSERDES_COM_HSCLK_SEL); - div &= 0x0f; - - if (div == 12) - hsclk_div = 6; /* Default */ - else if (div == 4) - hsclk_div = 4; - else if (div == 0) - hsclk_div = 2; - else if (div == 3) - hsclk_div = 1; - else { - DRM_DEBUG_DP("unknown divider. forcing to default\n"); - hsclk_div = 5; - } - - div = PLL_REG_R(pll_io->phy_base, REG_DP_PHY_AUX_CFG2); - div >>= 2; - - if ((div & 0x3) == 0) - link_clk_div = 5; - else if ((div & 0x3) == 1) - link_clk_div = 10; - else if ((div & 0x3) == 2) - link_clk_div = 20; - else - DRM_ERROR("%s: unsupported div. Phy_mode: %d\n", __func__, div); - - if (link_clk_div == 20) { - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - } else { - if (hsclk_div == 6) - vco_rate = DP_VCO_HSCLK_RATE_1620MHZDIV1000; - else if (hsclk_div == 4) - vco_rate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (hsclk_div == 2) - vco_rate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - vco_rate = DP_VCO_HSCLK_RATE_8100MHZDIV1000; - } - - DRM_DEBUG_DP("returning vco rate = %lu\n", (unsigned long)vco_rate); - - dp_res->vco_cached_rate = vco->rate = vco_rate; - return (unsigned long)vco_rate; -} - -long dp_vco_round_rate_10nm(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long rrate = rate; - struct dp_pll_vco_clk *vco = to_dp_vco_hw(hw); - - if (rate <= vco->min_rate) - rrate = vco->min_rate; - else if (rate <= DP_VCO_HSCLK_RATE_2700MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_2700MHZDIV1000; - else if (rate <= DP_VCO_HSCLK_RATE_5400MHZDIV1000) - rrate = DP_VCO_HSCLK_RATE_5400MHZDIV1000; - else - rrate = vco->max_rate; - - DRM_DEBUG_DP("%s: rrate=%ld\n", __func__, rrate); - - *parent_rate = rrate; - return rrate; -} diff --git a/drivers/gpu/drm/msm/dp/dp_pll_private.h b/drivers/gpu/drm/msm/dp/dp_pll_private.h deleted file mode 100644 index 434abdc396f5e..0000000000000 --- a/drivers/gpu/drm/msm/dp/dp_pll_private.h +++ /dev/null @@ -1,89 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. - */ - -#ifndef __DP_PLL_10NM_H -#define __DP_PLL_10NM_H - -#include "dp_pll.h" -#include "dp_reg.h" - -#define DP_VCO_HSCLK_RATE_1620MHZDIV1000 1620000UL -#define DP_VCO_HSCLK_RATE_2700MHZDIV1000 2700000UL -#define DP_VCO_HSCLK_RATE_5400MHZDIV1000 5400000UL -#define DP_VCO_HSCLK_RATE_8100MHZDIV1000 8100000UL - -#define NUM_DP_CLOCKS_MAX 6 - -#define DP_PHY_PLL_POLL_SLEEP_US 500 -#define DP_PHY_PLL_POLL_TIMEOUT_US 10000 - -#define DP_VCO_RATE_8100MHZDIV1000 8100000UL -#define DP_VCO_RATE_9720MHZDIV1000 9720000UL -#define DP_VCO_RATE_10800MHZDIV1000 10800000UL - -struct dp_pll_vco_clk { - struct clk_hw hw; - unsigned long rate; /* current vco rate */ - u64 min_rate; /* min vco rate */ - u64 max_rate; /* max vco rate */ - void *priv; -}; - -struct dp_pll_db { - struct msm_dp_pll *base; - - int id; - struct platform_device *pdev; - - /* private clocks: */ - bool fixed_factor_clk[NUM_DP_CLOCKS_MAX]; - struct clk_hw *hws[NUM_DP_CLOCKS_MAX]; - u32 num_hws; - - /* lane and orientation settings */ - u8 lane_cnt; - u8 orientation; - - /* COM PHY settings */ - u32 hsclk_sel; - u32 dec_start_mode0; - u32 div_frac_start1_mode0; - u32 div_frac_start2_mode0; - u32 div_frac_start3_mode0; - u32 integloop_gain0_mode0; - u32 integloop_gain1_mode0; - u32 vco_tune_map; - u32 lock_cmp1_mode0; - u32 lock_cmp2_mode0; - u32 lock_cmp3_mode0; - u32 lock_cmp_en; - - /* PHY vco divider */ - u32 phy_vco_div; - /* - * Certain pll's needs to update the same vco rate after resume in - * suspend/resume scenario. Cached the vco rate for such plls. - */ - unsigned long vco_cached_rate; - u32 cached_cfg0; - u32 cached_cfg1; - u32 cached_outdiv; - - uint32_t index; -}; - -static inline struct dp_pll_vco_clk *to_dp_vco_hw(struct clk_hw *hw) -{ - return container_of(hw, struct dp_pll_vco_clk, hw); -} - -#define to_msm_dp_pll(vco) ((struct msm_dp_pll *)vco->priv) - -#define to_dp_pll_db(x) ((struct dp_pll_db *)x->priv) - -int msm_dp_pll_10nm_init(struct msm_dp_pll *dp_pll, int id); -void msm_dp_pll_10nm_deinit(struct msm_dp_pll *dp_pll); - -#endif /* __DP_PLL_10NM_H */ diff --git a/drivers/gpu/drm/msm/dp/dp_power.c b/drivers/gpu/drm/msm/dp/dp_power.c index 34fdb2e5d644b..17c1fc6a2d44a 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.c +++ b/drivers/gpu/drm/msm/dp/dp_power.c @@ -9,6 +9,7 @@ #include <linux/clk-provider.h> #include <linux/regulator/consumer.h> #include "dp_power.h" +#include "msm_drv.h" struct dp_power_private { struct dp_parser *parser; @@ -102,16 +103,6 @@ static int dp_power_clk_init(struct dp_power_private *power) ctrl = &power->parser->mp[DP_CTRL_PM]; stream = &power->parser->mp[DP_STREAM_PM]; - if (power->parser->pll && power->parser->pll->get_provider) { - rc = power->parser->pll->get_provider(power->parser->pll, - &power->link_provider, &power->pixel_provider); - if (rc) { - DRM_ERROR("%s:provider failed,don't set parent\n", - __func__); - return 0; - } - } - rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk); if (rc) { DRM_ERROR("failed to get %s clk. err=%d\n", @@ -312,34 +303,6 @@ void dp_power_client_deinit(struct dp_power *dp_power) } -int dp_power_set_link_clk_parent(struct dp_power *dp_power) -{ - int rc = 0; - struct dp_power_private *power; - u32 num; - struct dss_clk *cfg; - char *name = "ctrl_link"; - - if (!dp_power) { - DRM_ERROR("invalid power data\n"); - rc = -EINVAL; - goto exit; - } - - power = container_of(dp_power, struct dp_power_private, dp_power); - - num = power->parser->mp[DP_CTRL_PM].num_clk; - cfg = power->parser->mp[DP_CTRL_PM].clk_config; - - while (num && strcmp(cfg->clk_name, name)) { - num--; - cfg++; - } - -exit: - return rc; -} - int dp_power_init(struct dp_power *dp_power, bool flip) { int rc = 0; diff --git a/drivers/gpu/drm/msm/dp/dp_power.h b/drivers/gpu/drm/msm/dp/dp_power.h index 5333a97d5c356..76743d7558331 100644 --- a/drivers/gpu/drm/msm/dp/dp_power.h +++ b/drivers/gpu/drm/msm/dp/dp_power.h @@ -69,15 +69,6 @@ int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type); int dp_power_clk_enable(struct dp_power *power, enum dp_pm_type pm_type, bool enable); -/** - * dp_power_set_link_clk_parent() - configures parent of link clocks - * - * @power: instance of power module - * return: 0 for success, error for failures - * - * This API will set the link clock parent source - */ -int dp_power_set_link_clk_parent(struct dp_power *power); /** * dp_power_client_init() - initialize clock and regulator modules diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index de32f6204a505..43042ff90a199 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -6,22 +6,6 @@ #ifndef _DP_REG_H_ #define _DP_REG_H_ -/* DP PHY Register Regions */ -#define REG_DP_PHY_REGION_BASE (0x088ea000) -#define REG_DP_PHY_REGION_SIZE (0x00000C00) - -#define REG_USB3_DP_COM_REGION_BASE (0x088e8000) -#define REG_USB3_DP_COM_REGION_SIZE (0x00000020) - -#define DP_PHY_PLL_OFFSET (0x00000000) -#define DP_PHY_PLL_SIZE (0x00000200) -#define DP_PHY_REG_OFFSET (0x00000A00) -#define DP_PHY_REG_SIZE (0x00000200) -#define DP_PHY_LN_TX0_OFFSET (0x00000200) -#define DP_PHY_LN_TX0_SIZE (0x00000200) -#define DP_PHY_LN_TX1_OFFSET (0x00000600) -#define DP_PHY_LN_TX1_SIZE (0x00000200) - /* DP_TX Registers */ #define REG_DP_HW_VERSION (0x00000000) @@ -290,183 +274,10 @@ #define MMSS_DP_ASYNC_FIFO_CONFIG (0x00000088) -/*DP PHY Register offsets */ -#define REG_DP_PHY_REVISION_ID0 (0x00000000) -#define REG_DP_PHY_REVISION_ID1 (0x00000004) -#define REG_DP_PHY_REVISION_ID2 (0x00000008) -#define REG_DP_PHY_REVISION_ID3 (0x0000000C) - -#define REG_DP_PHY_CFG (0x00000010) - -#define REG_DP_PHY_PD_CTL (0x00000018) -#define DP_PHY_PD_CTL_PWRDN (0x00000001) -#define DP_PHY_PD_CTL_PSR_PWRDN (0x00000002) -#define DP_PHY_PD_CTL_AUX_PWRDN (0x00000004) -#define DP_PHY_PD_CTL_LANE_0_1_PWRDN (0x00000008) -#define DP_PHY_PD_CTL_LANE_2_3_PWRDN (0x00000010) -#define DP_PHY_PD_CTL_PLL_PWRDN (0x00000020) -#define DP_PHY_PD_CTL_DP_CLAMP_EN (0x00000040) - -#define REG_DP_PHY_MODE (0x0000001C) - -#define REG_DP_PHY_AUX_CFG0 (0x00000020) -#define REG_DP_PHY_AUX_CFG1 (0x00000024) -#define REG_DP_PHY_AUX_CFG2 (0x00000028) -#define REG_DP_PHY_AUX_CFG3 (0x0000002C) -#define REG_DP_PHY_AUX_CFG4 (0x00000030) -#define REG_DP_PHY_AUX_CFG5 (0x00000034) -#define REG_DP_PHY_AUX_CFG6 (0x00000038) -#define REG_DP_PHY_AUX_CFG7 (0x0000003C) -#define REG_DP_PHY_AUX_CFG8 (0x00000040) -#define REG_DP_PHY_AUX_CFG9 (0x00000044) - -#define REG_DP_PHY_AUX_INTERRUPT_MASK (0x00000048) -#define PHY_AUX_STOP_ERR_MASK (0x00000001) -#define PHY_AUX_DEC_ERR_MASK (0x00000002) -#define PHY_AUX_SYNC_ERR_MASK (0x00000004) -#define PHY_AUX_ALIGN_ERR_MASK (0x00000008) -#define PHY_AUX_REQ_ERR_MASK (0x00000010) - - #define REG_DP_PHY_AUX_INTERRUPT_CLEAR (0x0000004C) #define REG_DP_PHY_AUX_BIST_CFG (0x00000050) #define REG_DP_PHY_AUX_INTERRUPT_STATUS (0x000000BC) -#define REG_DP_PHY_VCO_DIV 0x0064 -#define REG_DP_PHY_TX0_TX1_LANE_CTL 0x006C -#define REG_DP_PHY_TX2_TX3_LANE_CTL 0x0088 - -#define REG_DP_PHY_SPARE0 (0x00AC) -#define DP_PHY_SPARE0_MASK (0x000F) -#define DP_PHY_SPARE0_ORIENTATION_INFO_SHIFT (0x0004) - -#define REG_DP_PHY_STATUS (0x00C0) - -/* Tx registers */ -#define REG_DP_PHY_TXn_BIST_MODE_LANENO 0x0000 -#define REG_DP_PHY_TXn_CLKBUF_ENABLE 0x0008 - -#define REG_DP_PHY_TXn_TX_EMP_POST1_LVL 0x000C -#define DP_PHY_TXn_TX_EMP_POST1_LVL_MASK 0x001F -#define DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN 0x0020 - -#define REG_DP_PHY_TXn_TX_DRV_LVL 0x001C -#define DP_PHY_TXn_TX_DRV_LVL_MASK 0x001F -#define DP_PHY_TXn_TX_DRV_LVL_MUX_EN 0x0020 - -#define REG_DP_PHY_TXn_RESET_TSYNC_EN 0x0024 -#define REG_DP_PHY_TXn_PRE_STALL_LDO_BOOST_EN 0x0028 -#define REG_DP_PHY_TXn_TX_BAND 0x002C -#define REG_DP_PHY_TXn_SLEW_CNTL 0x0030 -#define REG_DP_PHY_TXn_INTERFACE_SELECT 0x0034 - -#define REG_DP_PHY_TXn_RES_CODE_LANE_TX 0x003C -#define REG_DP_PHY_TXn_RES_CODE_LANE_RX 0x0040 -#define REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_TX 0x0044 -#define REG_DP_PHY_TXn_RES_CODE_LANE_OFFSET_RX 0x0048 - -#define REG_DP_PHY_TXn_DEBUG_BUS_SEL 0x0058 -#define REG_DP_PHY_TXn_TRANSCEIVER_BIAS_EN 0x005C -#define REG_DP_PHY_TXn_HIGHZ_DRVR_EN 0x0060 -#define REG_DP_PHY_TXn_TX_POL_INV 0x0064 -#define REG_DP_PHY_TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 - -#define REG_DP_PHY_TXn_LANE_MODE_1 0x008C - -#define REG_DP_PHY_TXn_TRAN_DRVR_EMP_EN 0x00C0 -#define REG_DP_PHY_TXn_TX_INTERFACE_MODE 0x00C4 - -#define REG_DP_PHY_TXn_VMODE_CTRL1 0x00F0 - -/* PLL register offset */ -#define QSERDES_COM_ATB_SEL1 0x0000 -#define QSERDES_COM_ATB_SEL2 0x0004 -#define QSERDES_COM_FREQ_UPDATE 0x0008 -#define QSERDES_COM_BG_TIMER 0x000C -#define QSERDES_COM_SSC_EN_CENTER 0x0010 -#define QSERDES_COM_SSC_ADJ_PER1 0x0014 -#define QSERDES_COM_SSC_ADJ_PER2 0x0018 -#define QSERDES_COM_SSC_PER1 0x001C -#define QSERDES_COM_SSC_PER2 0x0020 -#define QSERDES_COM_SSC_STEP_SIZE1 0x0024 -#define QSERDES_COM_SSC_STEP_SIZE2 0x0028 -#define QSERDES_COM_POST_DIV 0x002C -#define QSERDES_COM_POST_DIV_MUX 0x0030 - -#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x0034 -#define QSERDES_COM_BIAS_EN 0x0001 -#define QSERDES_COM_BIAS_EN_MUX 0x0002 -#define QSERDES_COM_CLKBUF_R_EN 0x0004 -#define QSERDES_COM_CLKBUF_L_EN 0x0008 -#define QSERDES_COM_EN_SYSCLK_TX_SEL 0x0010 -#define QSERDES_COM_CLKBUF_RX_DRIVE_L 0x0020 -#define QSERDES_COM_CLKBUF_RX_DRIVE_R 0x0040 - -#define QSERDES_COM_CLK_ENABLE1 0x0038 -#define QSERDES_COM_SYS_CLK_CTRL 0x003C -#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x0040 -#define QSERDES_COM_PLL_EN 0x0044 -#define QSERDES_COM_PLL_IVCO 0x0048 -#define QSERDES_COM_CMN_IETRIM 0x004C -#define QSERDES_COM_CMN_IPTRIM 0x0050 - -#define QSERDES_COM_CP_CTRL_MODE0 0x0060 -#define QSERDES_COM_CP_CTRL_MODE1 0x0064 -#define QSERDES_COM_PLL_RCTRL_MODE0 0x0068 -#define QSERDES_COM_PLL_RCTRL_MODE1 0x006C -#define QSERDES_COM_PLL_CCTRL_MODE0 0x0070 -#define QSERDES_COM_PLL_CCTRL_MODE1 0x0074 -#define QSERDES_COM_PLL_CNTRL 0x0078 -#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x007C -#define QSERDES_COM_SYSCLK_EN_SEL 0x0080 -#define QSERDES_COM_CML_SYSCLK_SEL 0x0084 -#define QSERDES_COM_RESETSM_CNTRL 0x0088 -#define QSERDES_COM_RESETSM_CNTRL2 0x008C -#define QSERDES_COM_LOCK_CMP_EN 0x0090 -#define QSERDES_COM_LOCK_CMP_CFG 0x0094 -#define QSERDES_COM_LOCK_CMP1_MODE0 0x0098 -#define QSERDES_COM_LOCK_CMP2_MODE0 0x009C -#define QSERDES_COM_LOCK_CMP3_MODE0 0x00A0 - -#define QSERDES_COM_DEC_START_MODE0 0x00B0 -#define QSERDES_COM_DEC_START_MODE1 0x00B4 -#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x00B8 -#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x00BC -#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x00C0 -#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x00C4 -#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x00C8 -#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x00CC -#define QSERDES_COM_INTEGLOOP_INITVAL 0x00D0 -#define QSERDES_COM_INTEGLOOP_EN 0x00D4 -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x00D8 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x00DC -#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x00E0 -#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x00E4 -#define QSERDES_COM_VCOCAL_DEADMAN_CTRL 0x00E8 -#define QSERDES_COM_VCO_TUNE_CTRL 0x00EC -#define QSERDES_COM_VCO_TUNE_MAP 0x00F0 - -#define QSERDES_COM_CMN_STATUS 0x0124 -#define QSERDES_COM_RESET_SM_STATUS 0x0128 - -#define QSERDES_COM_CLK_SEL 0x0138 -#define QSERDES_COM_HSCLK_SEL 0x013C - -#define QSERDES_COM_CORECLK_DIV_MODE0 0x0148 - -#define QSERDES_COM_SW_RESET 0x0150 -#define QSERDES_COM_CORE_CLK_EN 0x0154 -#define QSERDES_COM_C_READY_STATUS 0x0158 -#define QSERDES_COM_CMN_CONFIG 0x015C - -#define QSERDES_COM_SVS_MODE_CLK_SEL 0x0164 - -/* DP MMSS_CC registers */ -#define MMSS_DP_LINK_CMD_RCGR (0x0138) -#define MMSS_DP_LINK_CFG_RCGR (0x013C) -#define MMSS_DP_PIXEL_M (0x01B4) -#define MMSS_DP_PIXEL_N (0x01B8) - /* DP HDCP 1.3 registers */ #define DP_HDCP_CTRL (0x0A0) #define DP_HDCP_STATUS (0x0A4) @@ -492,28 +303,4 @@ #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) -/* USB3 DP COM registers */ -#define REG_USB3_DP_COM_RESET_OVRD_CTRL (0x1C) -#define USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET (0x01) -#define USB3_DP_COM_OVRD_CTRL_SW_DPPHY_RESET_MUX (0x02) -#define USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET (0x04) -#define USB3_DP_COM_OVRD_CTRL_SW_USB3PHY_RESET_MUX (0x08) - -#define REG_USB3_DP_COM_PHY_MODE_CTRL (0x00) -#define USB3_DP_COM_PHY_MODE_DP (0x03) - -#define REG_USB3_DP_COM_SW_RESET (0x04) -#define USB3_DP_COM_SW_RESET_SET (0x01) - -#define REG_USB3_DP_COM_TYPEC_CTRL (0x10) -#define USB3_DP_COM_TYPEC_CTRL_PORTSEL (0x01) -#define USB3_DP_COM_TYPEC_CTRL_PORTSEL_MUX (0x02) - -#define REG_USB3_DP_COM_SWI_CTRL (0x0c) - -#define REG_USB3_DP_COM_POWER_DOWN_CTRL (0x08) -#define USB3_DP_COM_POWER_DOWN_CTRL_SW_PWRDN (0x01) - - - #endif /* _DP_REG_H_ */ -- GitLab From 484a8737c755071ae456adf3561f6749dd250881 Mon Sep 17 00:00:00 2001 From: Qian Cai <cai@lca.pw> Date: Sun, 7 Jun 2020 22:53:40 -0400 Subject: [PATCH 1133/1494] drm: rcar-du: Make DRM_RCAR_WRITEBACK depends on DRM_RCAR_DU There is no need to select DRM_RCAR_WRITEBACK if DRM_RCAR_DU=n which just make the generated .config a bit ugly. # ARM devices # # end of ARM devices CONFIG_DRM_RCAR_WRITEBACK=y # # Frame buffer Devices Let DRM_RCAR_WRITEBACK depend on DRM_RCAR_DU instead. Signed-off-by: Qian Cai <cai@lca.pw> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index f65d1489dc509..49b590aa69be1 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -49,3 +49,4 @@ config DRM_RCAR_VSP config DRM_RCAR_WRITEBACK bool default y if ARM64 + depends on DRM_RCAR_DU -- GitLab From c3415d91832cf47bf54973ef5415caeaba5249c6 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Date: Fri, 7 Aug 2020 18:49:48 +0100 Subject: [PATCH 1134/1494] dt-bindings: display: renesas,du: Document the r8a7742 bindings Document the RZ/G1H (R8A7742) SoC in the R-Car DU bindings. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 51cd4d1627703..3f1e3ca4bea9a 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -3,6 +3,7 @@ Required Properties: - compatible: must be one of the following. + - "renesas,du-r8a7742" for R8A7742 (RZ/G1H) compatible DU - "renesas,du-r8a7743" for R8A7743 (RZ/G1M) compatible DU - "renesas,du-r8a7744" for R8A7744 (RZ/G1N) compatible DU - "renesas,du-r8a7745" for R8A7745 (RZ/G1E) compatible DU @@ -68,6 +69,7 @@ corresponding to each DU output. Port0 Port1 Port2 Port3 ----------------------------------------------------------------------------- + R8A7742 (RZ/G1H) DPAD 0 LVDS 0 LVDS 1 - R8A7743 (RZ/G1M) DPAD 0 LVDS 0 - - R8A7744 (RZ/G1N) DPAD 0 LVDS 0 - - R8A7745 (RZ/G1E) DPAD 0 DPAD 1 - - -- GitLab From 9edf73fece3d27e6fb5a764b732eca94c941838e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Date: Fri, 7 Aug 2020 18:49:49 +0100 Subject: [PATCH 1135/1494] drm: rcar-du: Add r8a7742 support Add direct support for the r8a7742 (RZ/G1H). The RZ/G1H shares a common, compatible configuration with the r8a7790 (R-Car H2) so that device info structure is reused, the only difference being TCON is unsupported on RZ/G1H (Currently unsupported by the driver). Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index f53b0ec710850..0f870c282455c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -216,8 +216,9 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { .channels_mask = BIT(2) | BIT(1) | BIT(0), .routes = { /* - * R8A7790 has one RGB output, two LVDS outputs and one - * (currently unsupported) TCON output. + * R8A7742 and R8A7790 each have one RGB output and two LVDS + * outputs. Additionally R8A7790 supports one TCON output + * (currently unsupported by the driver). */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(2) | BIT(1) | BIT(0), @@ -443,6 +444,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { }; static const struct of_device_id rcar_du_of_table[] = { + { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info }, { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info }, -- GitLab From 109bf47277a0b94670743b0648d76e61b982696b Mon Sep 17 00:00:00 2001 From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Date: Fri, 7 Aug 2020 18:49:50 +0100 Subject: [PATCH 1136/1494] dt-bindings: display: renesas,lvds: Document r8a7742 bindings Document the RZ/G1H (R8A7742) LVDS bindings. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [Port to the YAML binding document] Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/renesas,lvds.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml index baaf2a2a6fed3..bf3dee252c1aa 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml @@ -16,6 +16,7 @@ description: | properties: compatible: enum: + - renesas,r8a7742-lvds # for RZ/G1H compatible LVDS encoders - renesas,r8a7743-lvds # for RZ/G1M compatible LVDS encoders - renesas,r8a7744-lvds # for RZ/G1N compatible LVDS encoders - renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders -- GitLab From 3fa98ed530a4bd80e4936635831fa77666eea82e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Date: Fri, 7 Aug 2020 18:49:51 +0100 Subject: [PATCH 1137/1494] drm: rcar-du: lvds: Add r8a7742 support The LVDS encoders on RZ/G1H SoC is identical to the R-Car Gen2 family. Add support for RZ/G1H (R8A7742) SoC to the LVDS encoder driver. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index bced729a96fe8..dc386e3a763c3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -978,6 +978,7 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = { }; static const struct of_device_id rcar_lvds_of_table[] = { + { .compatible = "renesas,r8a7742-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7744-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info }, -- GitLab From a9a83a92d0da38a78c0afda096c0a4a5f39f9480 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Wed, 2 Sep 2020 12:57:59 +0800 Subject: [PATCH 1138/1494] drm/kfd: fix a system crash issue during GPU recovery The crash log as the below: [Thu Aug 20 23:18:14 2020] general protection fault: 0000 [#1] SMP NOPTI [Thu Aug 20 23:18:14 2020] CPU: 152 PID: 1837 Comm: kworker/152:1 Tainted: G OE 5.4.0-42-generic #46~18.04.1-Ubuntu [Thu Aug 20 23:18:14 2020] Hardware name: GIGABYTE G482-Z53-YF/MZ52-G40-00, BIOS R12 05/13/2020 [Thu Aug 20 23:18:14 2020] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [Thu Aug 20 23:18:14 2020] RIP: 0010:evict_process_queues_cpsch+0xc9/0x130 [amdgpu] [Thu Aug 20 23:18:14 2020] Code: 49 8d 4d 10 48 39 c8 75 21 eb 44 83 fa 03 74 36 80 78 72 00 74 0c 83 ab 68 01 00 00 01 41 c6 45 41 00 48 8b 00 48 39 c8 74 25 <80> 78 70 00 c6 40 6d 01 74 ee 8b 50 28 c6 40 70 00 83 ab 60 01 00 [Thu Aug 20 23:18:14 2020] RSP: 0018:ffffb29b52f6fc90 EFLAGS: 00010213 [Thu Aug 20 23:18:14 2020] RAX: 1c884edb0a118914 RBX: ffff8a0d45ff3c00 RCX: ffff8a2d83e41038 [Thu Aug 20 23:18:14 2020] RDX: 0000000000000000 RSI: 0000000000000082 RDI: ffff8a0e2e4178c0 [Thu Aug 20 23:18:14 2020] RBP: ffffb29b52f6fcb0 R08: 0000000000001b64 R09: 0000000000000004 [Thu Aug 20 23:18:14 2020] R10: ffffb29b52f6fb78 R11: 0000000000000001 R12: ffff8a0d45ff3d28 [Thu Aug 20 23:18:14 2020] R13: ffff8a2d83e41028 R14: 0000000000000000 R15: 0000000000000000 [Thu Aug 20 23:18:14 2020] FS: 0000000000000000(0000) GS:ffff8a0e2e400000(0000) knlGS:0000000000000000 [Thu Aug 20 23:18:14 2020] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [Thu Aug 20 23:18:14 2020] CR2: 000055c783c0e6a8 CR3: 00000034a1284000 CR4: 0000000000340ee0 [Thu Aug 20 23:18:14 2020] Call Trace: [Thu Aug 20 23:18:14 2020] kfd_process_evict_queues+0x43/0xd0 [amdgpu] [Thu Aug 20 23:18:14 2020] kfd_suspend_all_processes+0x60/0xf0 [amdgpu] [Thu Aug 20 23:18:14 2020] kgd2kfd_suspend.part.7+0x43/0x50 [amdgpu] [Thu Aug 20 23:18:14 2020] kgd2kfd_pre_reset+0x46/0x60 [amdgpu] [Thu Aug 20 23:18:14 2020] amdgpu_amdkfd_pre_reset+0x1a/0x20 [amdgpu] [Thu Aug 20 23:18:14 2020] amdgpu_device_gpu_recover+0x377/0xf90 [amdgpu] [Thu Aug 20 23:18:14 2020] ? amdgpu_ras_error_query+0x1b8/0x2a0 [amdgpu] [Thu Aug 20 23:18:14 2020] amdgpu_ras_do_recovery+0x159/0x190 [amdgpu] [Thu Aug 20 23:18:14 2020] process_one_work+0x20f/0x400 [Thu Aug 20 23:18:14 2020] worker_thread+0x34/0x410 When GPU hang, user process will fail to create a compute queue whose struct object will be freed later, but driver wrongly add this queue to queue list of the proccess. And then kfd_process_evict_queues will access a freed memory, which cause a system crash. v2: The failure to execute_queues should probably not be reported to the caller of create_queue, because the queue was already created. Therefore change to ignore the return value from execute_queues. Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 560adc57a050b..069ba4be1e8f2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1302,7 +1302,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, if (q->properties.is_active) { increment_queue_count(dqm, q->properties.type); - retval = execute_queues_cpsch(dqm, + execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); } -- GitLab From edb084f487a3b7c86efce81bfa1a7aa666dd4047 Mon Sep 17 00:00:00 2001 From: Dennis Li <Dennis.Li@amd.com> Date: Wed, 2 Sep 2020 17:11:09 +0800 Subject: [PATCH 1139/1494] drm/amdkfd: fix a memory leak issue In the resume stage of GPU recovery, start_cpsch will call pm_init which set pm->allocated as false, cause the next pm_release_ib has no chance to release ib memory. Add pm_release_ib in stop_cpsch which will be called in the suspend stage of GPU recovery. Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 069ba4be1e8f2..20ef048d6a034 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1192,6 +1192,8 @@ static int stop_cpsch(struct device_queue_manager *dqm) dqm->sched_running = false; dqm_unlock(dqm); + pm_release_ib(&dqm->packets); + kfd_gtt_sa_free(dqm->dev, dqm->fence_mem); pm_uninit(&dqm->packets, hanging); -- GitLab From 2a9787dcf537d0e4f1fa41cbd883abe9d70b9fcb Mon Sep 17 00:00:00 2001 From: Liu ChengZhe <ChengZhe.Liu@amd.com> Date: Wed, 9 Sep 2020 16:00:12 +0800 Subject: [PATCH 1140/1494] drm/amdgpu: Do gpu recovery when no job is running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In function flr_work, we should do gpu recovery when no job is running. Fix the logic by inverting it. v2: modify the description Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Liu ChengZhe <ChengZhe.Liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 3 ++- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 9c07014d9bd6c..f5ce9a9f4cf57 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -262,7 +262,8 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && (amdgpu_device_has_job_running(adev) || adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT)) + && (!amdgpu_device_has_job_running(adev) || + adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT)) amdgpu_device_gpu_recover(adev, NULL); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 9c23abf9b140d..666ed99cc14b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -283,7 +283,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && (amdgpu_device_has_job_running(adev) || + && (!amdgpu_device_has_job_running(adev) || adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || adev->gfx_timeout == MAX_SCHEDULE_TIMEOUT || adev->compute_timeout == MAX_SCHEDULE_TIMEOUT || -- GitLab From c9a6b82f45e261d247b980a7949aaa6a9bfffe01 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Wed, 29 Jul 2020 12:59:45 -0400 Subject: [PATCH 1141/1494] drm/amdgpu: Implement DPC recovery Add PCI Downstream Port Containment (DPC) with basic recovery functionality v2: remove pci_save_state to avoid breaking suspend/resume v3: Fix style comments v4: Improve description. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 161 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +- 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4009d2e307275..29c0b4c872315 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -49,6 +49,8 @@ #include <linux/rbtree.h> #include <linux/hashtable.h> #include <linux/dma-fence.h> +#include <linux/pci.h> +#include <linux/aer.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> @@ -1260,6 +1262,12 @@ static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return void amdgpu_register_gpu_instance(struct amdgpu_device *adev); void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev); +pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); +pci_ers_result_t amdgpu_pci_mmio_enabled(struct pci_dev *pdev); +pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev); +void amdgpu_pci_resume(struct pci_dev *pdev); + #include "amdgpu_object.h" /* used by df_v3_6.c and amdgpu_pmu.c */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index f7307af764521..99c0e6e53e848 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2999,6 +2999,7 @@ static const struct attribute *amdgpu_dev_attributes[] = { NULL }; + /** * amdgpu_device_init - initialize the driver * @@ -3217,6 +3218,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, } } + pci_enable_pcie_error_reporting(adev->ddev.pdev); + /* Post card if necessary */ if (amdgpu_device_need_post(adev)) { if (!adev->bios) { @@ -4705,3 +4708,161 @@ int amdgpu_device_baco_exit(struct drm_device *dev) return 0; } + +/** + * amdgpu_pci_error_detected - Called when a PCI error is detected. + * @pdev: PCI device struct + * @state: PCI channel state + * + * Description: Called when a PCI error is detected. + * + * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT. + */ +pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); + + DRM_INFO("PCI error: detected callback, state(%d)!!\n", state); + + switch (state) { + case pci_channel_io_normal: + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + /* Fatal error, prepare for slot reset */ + amdgpu_device_lock_adev(adev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + /* Permanent error, prepare for device removal */ + return PCI_ERS_RESULT_DISCONNECT; + } + + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * amdgpu_pci_mmio_enabled - Enable MMIO and dump debug registers + * @pdev: pointer to PCI device + */ +pci_ers_result_t amdgpu_pci_mmio_enabled(struct pci_dev *pdev) +{ + + DRM_INFO("PCI error: mmio enabled callback!!\n"); + + /* TODO - dump whatever for debugging purposes */ + + /* This called only if amdgpu_pci_error_detected returns + * PCI_ERS_RESULT_CAN_RECOVER. Read/write to the device still + * works, no need to reset slot. + */ + + return PCI_ERS_RESULT_RECOVERED; +} + +/** + * amdgpu_pci_slot_reset - Called when PCI slot has been reset. + * @pdev: PCI device struct + * + * Description: This routine is called by the pci error recovery + * code after the PCI slot has been reset, just before we + * should resume normal operations. + */ +pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); + int r; + bool vram_lost; + + DRM_INFO("PCI error: slot reset callback!!\n"); + + pci_restore_state(pdev); + + r = amdgpu_device_ip_suspend(adev); + if (r) + goto out; + + + /* post card */ + r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + if (r) + goto out; + + r = amdgpu_device_ip_resume_phase1(adev); + if (r) + goto out; + + vram_lost = amdgpu_device_check_vram_lost(adev); + if (vram_lost) { + DRM_INFO("VRAM is lost due to GPU reset!\n"); + amdgpu_inc_vram_lost(adev); + } + + r = amdgpu_gtt_mgr_recover( + &adev->mman.bdev.man[TTM_PL_TT]); + if (r) + goto out; + + r = amdgpu_device_fw_loading(adev); + if (r) + return r; + + r = amdgpu_device_ip_resume_phase2(adev); + if (r) + goto out; + + if (vram_lost) + amdgpu_device_fill_reset_magic(adev); + + /* + * Add this ASIC as tracked as reset was already + * complete successfully. + */ + amdgpu_register_gpu_instance(adev); + + r = amdgpu_device_ip_late_init(adev); + if (r) + goto out; + + amdgpu_fbdev_set_suspend(adev, 0); + + /* must succeed. */ + amdgpu_ras_resume(adev); + + + amdgpu_irq_gpu_reset_resume_helper(adev); + r = amdgpu_ib_ring_tests(adev); + if (r) + goto out; + + r = amdgpu_device_recover_vram(adev); + +out: + + if (!r) { + DRM_INFO("PCIe error recovery succeeded\n"); + } else { + DRM_ERROR("PCIe error recovery failed, err:%d", r); + amdgpu_device_unlock_adev(adev); + } + + return r ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; +} + +/** + * amdgpu_pci_resume() - resume normal ops after PCI reset + * @pdev: pointer to PCI device + * + * Called when the error recovery driver tells us that its + * OK to resume normal operation. Use completion to allow + * halted scsi ops to resume. + */ +void amdgpu_pci_resume(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); + + amdgpu_device_unlock_adev(adev); + + DRM_INFO("PCI error: resume callback!!\n"); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6edde2b9e4020..e9daab175d170 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -32,7 +32,6 @@ #include <drm/drm_pciids.h> #include <linux/console.h> #include <linux/module.h> -#include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/vga_switcheroo.h> #include <drm/drm_probe_helper.h> @@ -1528,6 +1527,13 @@ static struct drm_driver kms_driver = { .patchlevel = KMS_DRIVER_PATCHLEVEL, }; +static struct pci_error_handlers amdgpu_pci_err_handler = { + .error_detected = amdgpu_pci_error_detected, + .mmio_enabled = amdgpu_pci_mmio_enabled, + .slot_reset = amdgpu_pci_slot_reset, + .resume = amdgpu_pci_resume, +}; + static struct pci_driver amdgpu_kms_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, @@ -1535,6 +1541,7 @@ static struct pci_driver amdgpu_kms_pci_driver = { .remove = amdgpu_pci_remove, .shutdown = amdgpu_pci_shutdown, .driver.pm = &amdgpu_pm_ops, + .err_handler = &amdgpu_pci_err_handler, }; static int __init amdgpu_init(void) -- GitLab From bf36b52e781d7412c3fce826f74ba6a73b9be4d0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Wed, 29 Jul 2020 13:10:29 -0400 Subject: [PATCH 1142/1494] drm/amdgpu: Avoid accessing HW when suspending SW state At this point the ASIC is already post reset by the HW/PSP so the HW not in proper state to be configured for suspension, some blocks might be even gated and so best is to avoid touching it. v2: Rename in_dpc to more meaningful name Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 38 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 6 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 18 ++++++---- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 3 ++ 6 files changed, 65 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 29c0b4c872315..207eba0120290 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -989,6 +989,7 @@ struct amdgpu_device { atomic_t throttling_logging_enabled; struct ratelimit_state throttling_logging_rs; uint32_t ras_features; + bool in_pci_err_recovery; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 99c0e6e53e848..4d9a8734ea202 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -319,6 +319,9 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, { uint32_t ret; + if (adev->in_pci_err_recovery) + return 0; + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && down_read_trylock(&adev->reset_sem)) { ret = amdgpu_kiq_rreg(adev, reg); @@ -356,6 +359,9 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, * Returns the 8 bit value from the offset specified. */ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) { + if (adev->in_pci_err_recovery) + return 0; + if (offset < adev->rmmio_size) return (readb(adev->rmmio + offset)); BUG(); @@ -377,6 +383,9 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) { * Writes the value specified to the offset specified. */ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) { + if (adev->in_pci_err_recovery) + return; + if (offset < adev->rmmio_size) writeb(value, adev->rmmio + offset); else @@ -387,6 +396,9 @@ static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) { + if (adev->in_pci_err_recovery) + return; + trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); if ((reg * 4) < adev->rmmio_size) @@ -414,6 +426,9 @@ static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) { + if (adev->in_pci_err_recovery) + return; + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && down_read_trylock(&adev->reset_sem)) { amdgpu_kiq_wreg(adev, reg, v); @@ -432,6 +447,9 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) { + if (adev->in_pci_err_recovery) + return; + if (amdgpu_sriov_fullaccess(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->is_rlcg_access_range) { @@ -453,6 +471,9 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t */ u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) { + if (adev->in_pci_err_recovery) + return 0; + if ((reg * 4) < adev->rio_mem_size) return ioread32(adev->rio_mem + (reg * 4)); else { @@ -472,6 +493,9 @@ u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) */ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { + if (adev->in_pci_err_recovery) + return; + if ((reg * 4) < adev->rio_mem_size) iowrite32(v, adev->rio_mem + (reg * 4)); else { @@ -491,6 +515,9 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) */ u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index) { + if (adev->in_pci_err_recovery) + return 0; + if (index < adev->doorbell.num_doorbells) { return readl(adev->doorbell.ptr + index); } else { @@ -511,6 +538,9 @@ u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index) */ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v) { + if (adev->in_pci_err_recovery) + return; + if (index < adev->doorbell.num_doorbells) { writel(v, adev->doorbell.ptr + index); } else { @@ -529,6 +559,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v) */ u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index) { + if (adev->in_pci_err_recovery) + return 0; + if (index < adev->doorbell.num_doorbells) { return atomic64_read((atomic64_t *)(adev->doorbell.ptr + index)); } else { @@ -549,6 +582,9 @@ u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index) */ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v) { + if (adev->in_pci_err_recovery) + return; + if (index < adev->doorbell.num_doorbells) { atomic64_set((atomic64_t *)(adev->doorbell.ptr + index), v); } else { @@ -4778,7 +4814,9 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) pci_restore_state(pdev); + adev->in_pci_err_recovery = true; r = amdgpu_device_ip_suspend(adev); + adev->in_pci_err_recovery = false; if (r) goto out; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index d6981425ec510..8c9bacfdbc300 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -693,6 +693,9 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; + if (adev->in_pci_err_recovery) + return 0; + BUG_ON(!ring->funcs->emit_rreg); spin_lock_irqsave(&kiq->ring_lock, flags); @@ -757,6 +760,9 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) BUG_ON(!ring->funcs->emit_wreg); + if (adev->in_pci_err_recovery) + return; + spin_lock_irqsave(&kiq->ring_lock, flags); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_wreg(ring, reg, v); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index d6c38e24f130d..a7771aaa1c519 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -219,6 +219,9 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index, int i; struct amdgpu_device *adev = psp->adev; + if (psp->adev->in_pci_err_recovery) + return 0; + for (i = 0; i < adev->usec_timeout; i++) { val = RREG32(reg_index); if (check_changed) { @@ -245,6 +248,9 @@ psp_cmd_submit_buf(struct psp_context *psp, bool ras_intr = false; bool skip_unsupport = false; + if (psp->adev->in_pci_err_recovery) + return 0; + mutex_lock(&psp->mutex); memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index d502e30f67d9a..9801bb6daa016 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6980,15 +6980,19 @@ static int gfx_v10_0_hw_fini(void *handle) amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0); amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0); + + if (!adev->in_pci_err_recovery) { #ifndef BRING_UP_DEBUG - if (amdgpu_async_gfx_ring) { - r = gfx_v10_0_kiq_disable_kgq(adev); - if (r) - DRM_ERROR("KGQ disable failed\n"); - } + if (amdgpu_async_gfx_ring) { + r = gfx_v10_0_kiq_disable_kgq(adev); + if (r) + DRM_ERROR("KGQ disable failed\n"); + } #endif - if (amdgpu_gfx_disable_kcq(adev)) - DRM_ERROR("KCQ disable failed\n"); + if (amdgpu_gfx_disable_kcq(adev)) + DRM_ERROR("KCQ disable failed\n"); + } + if (amdgpu_sriov_vf(adev)) { gfx_v10_0_cp_gfx_enable(adev, false); /* Program KIQ position of RLC_CP_SCHEDULERS during destroy */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index a58ea08cd1153..97aa72a946312 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -112,6 +112,9 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, struct amdgpu_device *adev = smu->adev; int ret = 0, index = 0; + if (smu->adev->in_pci_err_recovery) + return 0; + index = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, msg); -- GitLab From acd89fca672dd2a7c3a83038cce7601498f21105 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Wed, 29 Jul 2020 14:14:36 -0400 Subject: [PATCH 1143/1494] drm/amdgpu: Block all job scheduling activity during DPC recovery DPC recovery involves ASIC reset just as normal GPU recovery so block SW GPU schedulers and wait on all concurrent GPU resets. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 57 ++++++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 4d9a8734ea202..2d155355a05f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4745,6 +4745,20 @@ int amdgpu_device_baco_exit(struct drm_device *dev) return 0; } +static void amdgpu_cancel_all_tdr(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->sched.thread) + continue; + + cancel_delayed_work_sync(&ring->sched.work_tdr); + } +} + /** * amdgpu_pci_error_detected - Called when a PCI error is detected. * @pdev: PCI device struct @@ -4758,15 +4772,37 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta { struct drm_device *dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_to_adev(dev); + int i; DRM_INFO("PCI error: detected callback, state(%d)!!\n", state); switch (state) { case pci_channel_io_normal: return PCI_ERS_RESULT_CAN_RECOVER; - case pci_channel_io_frozen: - /* Fatal error, prepare for slot reset */ - amdgpu_device_lock_adev(adev); + /* Fatal error, prepare for slot reset */ + case pci_channel_io_frozen: + /* + * Cancel and wait for all TDRs in progress if failing to + * set adev->in_gpu_reset in amdgpu_device_lock_adev + * + * Locking adev->reset_sem will prevent any external access + * to GPU during PCI error recovery + */ + while (!amdgpu_device_lock_adev(adev, NULL)) + amdgpu_cancel_all_tdr(adev); + + /* + * Block any work scheduling as we do for regular GPU reset + * for the duration of the recovery + */ + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->sched.thread) + continue; + + drm_sched_stop(&ring->sched, NULL); + } return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: /* Permanent error, prepare for device removal */ @@ -4899,8 +4935,21 @@ void amdgpu_pci_resume(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_to_adev(dev); + int i; - amdgpu_device_unlock_adev(adev); DRM_INFO("PCI error: resume callback!!\n"); + + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->sched.thread) + continue; + + + drm_sched_resubmit_jobs(&ring->sched); + drm_sched_start(&ring->sched, true); + } + + amdgpu_device_unlock_adev(adev); } -- GitLab From 362c7b91c1b00e31ebd219af1e493e7ef50ccfb4 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Mon, 24 Aug 2020 11:02:18 -0400 Subject: [PATCH 1144/1494] drm/amdgpu: Fix SMU error failure Wait for HW/PSP initiated ASIC reset to complete before starting the recovery operations. v2: Remove typo Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2d155355a05f7..36a8f128fb6b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4843,14 +4843,32 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_to_adev(dev); - int r; + int r, i; bool vram_lost; + u32 memsize; DRM_INFO("PCI error: slot reset callback!!\n"); + /* wait for asic to come out of reset */ + msleep(500); + pci_restore_state(pdev); - adev->in_pci_err_recovery = true; + /* confirm ASIC came out of reset */ + for (i = 0; i < adev->usec_timeout; i++) { + memsize = amdgpu_asic_get_config_memsize(adev); + + if (memsize != 0xffffffff) + break; + udelay(1); + } + if (memsize == 0xffffffff) { + r = -ETIME; + goto out; + } + + /* TODO Call amdgpu_pre_asic_reset instead */ + adev->in_pci_err_recovery = true; r = amdgpu_device_ip_suspend(adev); adev->in_pci_err_recovery = false; if (r) -- GitLab From c1dd4aa624076cb6d4724fad2d9e9e71e46bbc9f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Mon, 24 Aug 2020 12:30:47 -0400 Subject: [PATCH 1145/1494] drm/amdgpu: Fix consecutive DPC recovery failures. Cache the PCI state on boot and before each case where we might loose it. v2: Add pci_restore_state while caching the PCI state to avoid breaking PCI core logic for stuff like suspend/resume. v3: Extract pci_restore_state from amdgpu_device_cache_pci_state to avoid superflous restores during GPU resets and suspend/resumes. v4: Style fixes. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 62 ++++++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +- drivers/gpu/drm/amd/amdgpu/nv.c | 4 +- drivers/gpu/drm/amd/amdgpu/soc15.c | 4 +- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 207eba0120290..6125ba905faf8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -989,7 +989,9 @@ struct amdgpu_device { atomic_t throttling_logging_enabled; struct ratelimit_state throttling_logging_rs; uint32_t ras_features; + bool in_pci_err_recovery; + struct pci_saved_state *pci_state; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) @@ -1269,6 +1271,9 @@ pci_ers_result_t amdgpu_pci_mmio_enabled(struct pci_dev *pdev); pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev); void amdgpu_pci_resume(struct pci_dev *pdev); +bool amdgpu_device_cache_pci_state(struct pci_dev *pdev); +bool amdgpu_device_load_pci_state(struct pci_dev *pdev); + #include "amdgpu_object.h" /* used by df_v3_6.c and amdgpu_pmu.c */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 36a8f128fb6b3..9be9355bb0e0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1292,7 +1292,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; pci_set_power_state(dev->pdev, PCI_D0); - pci_restore_state(dev->pdev); + amdgpu_device_load_pci_state(dev->pdev); r = pci_enable_device(dev->pdev); if (r) DRM_WARN("pci_enable_device failed (%d)\n", r); @@ -1305,7 +1305,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, drm_kms_helper_poll_disable(dev); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; amdgpu_device_suspend(dev, true); - pci_save_state(dev->pdev); + amdgpu_device_cache_pci_state(dev->pdev); /* Shut down the device */ pci_disable_device(dev->pdev); pci_set_power_state(dev->pdev, PCI_D3cold); @@ -3408,6 +3408,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (r) dev_err(adev->dev, "amdgpu_pmu_init failed\n"); + /* Have stored pci confspace at hand for restore in sudden PCI error */ + if (amdgpu_device_cache_pci_state(adev->pdev)) + pci_restore_state(pdev); + return 0; failed: @@ -3432,6 +3436,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) flush_delayed_work(&adev->delayed_init_work); adev->shutdown = true; + kfree(adev->pci_state); + /* make sure IB test finished before entering exclusive mode * to avoid preemption on IB test * */ @@ -4852,7 +4858,7 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) /* wait for asic to come out of reset */ msleep(500); - pci_restore_state(pdev); + amdgpu_device_load_pci_state(pdev); /* confirm ASIC came out of reset */ for (i = 0; i < adev->usec_timeout; i++) { @@ -4932,6 +4938,9 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) out: if (!r) { + if (amdgpu_device_cache_pci_state(adev->pdev)) + pci_restore_state(adev->pdev); + DRM_INFO("PCIe error recovery succeeded\n"); } else { DRM_ERROR("PCIe error recovery failed, err:%d", r); @@ -4971,3 +4980,50 @@ void amdgpu_pci_resume(struct pci_dev *pdev) amdgpu_device_unlock_adev(adev); } + +bool amdgpu_device_cache_pci_state(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); + int r; + + r = pci_save_state(pdev); + if (!r) { + kfree(adev->pci_state); + + adev->pci_state = pci_store_saved_state(pdev); + + if (!adev->pci_state) { + DRM_ERROR("Failed to store PCI saved state"); + return false; + } + } else { + DRM_WARN("Failed to save PCI state, err:%d\n", r); + return false; + } + + return true; +} + +bool amdgpu_device_load_pci_state(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); + int r; + + if (!adev->pci_state) + return false; + + r = pci_load_saved_state(pdev, adev->pci_state); + + if (!r) { + pci_restore_state(pdev); + } else { + DRM_WARN("Failed to load PCI state, err:%d\n", r); + return false; + } + + return true; +} + + diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index e9daab175d170..5fafb3dff1a06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1315,7 +1315,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) if (amdgpu_is_atpx_hybrid()) { pci_ignore_hotplug(pdev); } else { - pci_save_state(pdev); + amdgpu_device_cache_pci_state(pdev); pci_disable_device(pdev); pci_ignore_hotplug(pdev); pci_set_power_state(pdev, PCI_D3cold); @@ -1348,7 +1348,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) pci_set_master(pdev); } else { pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); + amdgpu_device_load_pci_state(pdev); ret = pci_enable_device(pdev); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 4d14023562627..0ec66030bd119 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -311,7 +311,7 @@ static int nv_asic_mode1_reset(struct amdgpu_device *adev) /* disable BM */ pci_clear_master(adev->pdev); - pci_save_state(adev->pdev); + amdgpu_device_cache_pci_state(adev->pdev); if (amdgpu_dpm_is_mode1_reset_supported(adev)) { dev_info(adev->dev, "GPU smu mode1 reset\n"); @@ -323,7 +323,7 @@ static int nv_asic_mode1_reset(struct amdgpu_device *adev) if (ret) dev_err(adev->dev, "GPU mode1 reset failed\n"); - pci_restore_state(adev->pdev); + amdgpu_device_load_pci_state(adev->pdev); /* wait for asic to come out of reset */ for (i = 0; i < adev->usec_timeout; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 2f93c475d6d86..ddd55e3176c47 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -484,13 +484,13 @@ static int soc15_asic_mode1_reset(struct amdgpu_device *adev) /* disable BM */ pci_clear_master(adev->pdev); - pci_save_state(adev->pdev); + amdgpu_device_cache_pci_state(adev->pdev); ret = psp_gpu_reset(adev); if (ret) dev_err(adev->dev, "GPU mode1 reset failed\n"); - pci_restore_state(adev->pdev); + amdgpu_device_load_pci_state(adev->pdev); /* wait for asic to come out of reset */ for (i = 0; i < adev->usec_timeout; i++) { -- GitLab From 7ac71382e90aba1f58e304e386acdd02af963027 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Mon, 24 Aug 2020 14:27:40 -0400 Subject: [PATCH 1146/1494] drm/amdgpu: Trim amdgpu_pci_slot_reset by reusing code. Reuse exsisting functions from GPU recovery to avoid code duplications. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 73 ++++------------------ 1 file changed, 12 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 9be9355bb0e0a..ab42d0088f574 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4117,7 +4117,8 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, struct list_head *device_list_handle, - bool *need_full_reset_arg) + bool *need_full_reset_arg, + bool skip_hw_reset) { struct amdgpu_device *tmp_adev = NULL; bool need_full_reset = *need_full_reset_arg, vram_lost = false; @@ -4127,7 +4128,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, * ASIC reset has to be done on all HGMI hive nodes ASAP * to allow proper links negotiation in FW (within 1 sec) */ - if (need_full_reset) { + if (!skip_hw_reset && need_full_reset) { list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { /* For XGMI run all resets in parallel to speed up the process */ if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) { @@ -4522,7 +4523,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, if (r) adev->asic_reset_res = r; } else { - r = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset); + r = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset, false); if (r && r == -EAGAIN) goto retry; } @@ -4850,14 +4851,19 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev); struct amdgpu_device *adev = drm_to_adev(dev); int r, i; - bool vram_lost; + bool need_full_reset = true; u32 memsize; + struct list_head device_list; DRM_INFO("PCI error: slot reset callback!!\n"); + INIT_LIST_HEAD(&device_list); + list_add_tail(&adev->gmc.xgmi.head, &device_list); + /* wait for asic to come out of reset */ msleep(500); + /* Restore PCI confspace */ amdgpu_device_load_pci_state(pdev); /* confirm ASIC came out of reset */ @@ -4873,70 +4879,15 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev) goto out; } - /* TODO Call amdgpu_pre_asic_reset instead */ adev->in_pci_err_recovery = true; - r = amdgpu_device_ip_suspend(adev); + r = amdgpu_device_pre_asic_reset(adev, NULL, &need_full_reset); adev->in_pci_err_recovery = false; if (r) goto out; - - /* post card */ - r = amdgpu_atom_asic_init(adev->mode_info.atom_context); - if (r) - goto out; - - r = amdgpu_device_ip_resume_phase1(adev); - if (r) - goto out; - - vram_lost = amdgpu_device_check_vram_lost(adev); - if (vram_lost) { - DRM_INFO("VRAM is lost due to GPU reset!\n"); - amdgpu_inc_vram_lost(adev); - } - - r = amdgpu_gtt_mgr_recover( - &adev->mman.bdev.man[TTM_PL_TT]); - if (r) - goto out; - - r = amdgpu_device_fw_loading(adev); - if (r) - return r; - - r = amdgpu_device_ip_resume_phase2(adev); - if (r) - goto out; - - if (vram_lost) - amdgpu_device_fill_reset_magic(adev); - - /* - * Add this ASIC as tracked as reset was already - * complete successfully. - */ - amdgpu_register_gpu_instance(adev); - - r = amdgpu_device_ip_late_init(adev); - if (r) - goto out; - - amdgpu_fbdev_set_suspend(adev, 0); - - /* must succeed. */ - amdgpu_ras_resume(adev); - - - amdgpu_irq_gpu_reset_resume_helper(adev); - r = amdgpu_ib_ring_tests(adev); - if (r) - goto out; - - r = amdgpu_device_recover_vram(adev); + r = amdgpu_do_asic_reset(NULL, &device_list, &need_full_reset, true); out: - if (!r) { if (amdgpu_device_cache_pci_state(adev->pdev)) pci_restore_state(adev->pdev); -- GitLab From 6894305c97ceb56c0caa6f701516546a732af95f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Mon, 24 Aug 2020 14:41:56 -0400 Subject: [PATCH 1147/1494] drm/amdgpu: Disable DPC for XGMI for now. XGMI support is more complicated than single device support as questions of synchronization between the device recovering from PCI error and other members of the hive are required. Leaving this for next round. Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ab42d0088f574..36231fe9e4e5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4783,6 +4783,11 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta DRM_INFO("PCI error: detected callback, state(%d)!!\n", state); + if (adev->gmc.xgmi.num_physical_nodes > 1) { + DRM_WARN("No support for XGMI hive yet..."); + return PCI_ERS_RESULT_DISCONNECT; + } + switch (state) { case pci_channel_io_normal: return PCI_ERS_RESULT_CAN_RECOVER; -- GitLab From 7cbbc745dc11a75e11df532ca1566949709d6695 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Mon, 31 Aug 2020 11:34:33 -0400 Subject: [PATCH 1148/1494] drm/amdgpu: Minor checkpatch fix Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 36231fe9e4e5f..d633e5448476f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -358,7 +358,8 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, * * Returns the 8 bit value from the offset specified. */ -uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) { +uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) +{ if (adev->in_pci_err_recovery) return 0; @@ -382,7 +383,8 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset) { * * Writes the value specified to the offset specified. */ -void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) { +void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) +{ if (adev->in_pci_err_recovery) return; -- GitLab From 0e4b291bb76efbda9f542e514d16f9f3956fce5b Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Thu, 10 Sep 2020 16:03:08 +0800 Subject: [PATCH 1149/1494] drm/amd/pm: update driver if file for sienna cichlid Update drive if file for sienna_cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Jiansong Chen <Jiansong.Chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../pm/inc/smu11_driver_if_sienna_cichlid.h | 20 ++++++++++++++----- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 +- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 5 ----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h index 5ef9c92f57c47..11a6cf96fe0c0 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h @@ -27,9 +27,9 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x35 +#define SMU11_DRIVER_IF_VERSION 0x37 -#define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 +#define PPTABLE_Sienna_Cichlid_SMU_VERSION 6 #define NUM_GFXCLK_DPM_LEVELS 16 #define NUM_SMNCLK_DPM_LEVELS 2 @@ -169,7 +169,7 @@ typedef enum { #define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 #define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 #define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCEFCLK 0x00000800 -#define DPM_OVERRIDE_ENABLE_FAST_FCLK_TIMER 0x00001000 +#define DPM_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00001000 #define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 #define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 @@ -793,8 +793,18 @@ typedef struct { // SECTION: Sku Reserved uint8_t CustomerVariant; - uint8_t Spare[3]; - uint32_t SkuReserved[14]; + + //VC BTC parameters are only applicable to VDD_GFX domain + uint8_t VcBtcEnabled; + uint16_t VcBtcVminT0; // T0_VMIN + uint16_t VcBtcFixedVminAgingOffset; // FIXED_VMIN_AGING_OFFSET + uint16_t VcBtcVmin2PsmDegrationGb; // VMIN_TO_PSM_DEGRADATION_GB + uint32_t VcBtcPsmA; // A_PSM + uint32_t VcBtcPsmB; // B_PSM + uint32_t VcBtcVminA; // A_VMIN + uint32_t VcBtcVminB; // B_VMIN + + uint32_t SkuReserved[9]; // MAJOR SECTION: BOARD PARAMETERS diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 1f9575a4dfe7c..99f545d3ccb80 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -30,7 +30,7 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x37 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x4 /* MP Apertures */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 5c22611d5878b..9cf4e9aef1170 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2291,11 +2291,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) dev_info(smu->adev->dev, "SkuReserved[6] = 0x%x\n", pptable->SkuReserved[6]); dev_info(smu->adev->dev, "SkuReserved[7] = 0x%x\n", pptable->SkuReserved[7]); dev_info(smu->adev->dev, "SkuReserved[8] = 0x%x\n", pptable->SkuReserved[8]); - dev_info(smu->adev->dev, "SkuReserved[9] = 0x%x\n", pptable->SkuReserved[9]); - dev_info(smu->adev->dev, "SkuReserved[10] = 0x%x\n", pptable->SkuReserved[10]); - dev_info(smu->adev->dev, "SkuReserved[11] = 0x%x\n", pptable->SkuReserved[11]); - dev_info(smu->adev->dev, "SkuReserved[12] = 0x%x\n", pptable->SkuReserved[12]); - dev_info(smu->adev->dev, "SkuReserved[13] = 0x%x\n", pptable->SkuReserved[13]); dev_info(smu->adev->dev, "GamingClk[0] = 0x%x\n", pptable->GamingClk[0]); dev_info(smu->adev->dev, "GamingClk[1] = 0x%x\n", pptable->GamingClk[1]); -- GitLab From 9c1615be19490ebf589696224cfedc0abddc9234 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Thu, 10 Sep 2020 17:08:47 +0800 Subject: [PATCH 1150/1494] drm/amd/pm: update driver if version for navy_flounder It's in accordance with pmfw 65.8.0 for navy_flounder. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 99f545d3ccb80..7ae83df83edbd 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -31,7 +31,7 @@ #define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x37 -#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x4 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x5 /* MP Apertures */ #define MP0_Public 0x03800000 -- GitLab From f399d4de2d6a2e329ef3bceaa0e6a74c9d36c3cd Mon Sep 17 00:00:00 2001 From: Changfeng <Changfeng.Zhu@amd.com> Date: Tue, 8 Sep 2020 16:12:42 +0800 Subject: [PATCH 1151/1494] drm/amdgpu: add ta DTM/HDCP print in amdgpu_firmware_info for apu It needs to add ta DTM/HDCP print to get HDCP/DTM version info when cat amdgpu_firmware_info Signed-off-by: Changfeng <Changfeng.Zhu@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 43 +++++++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 456a4a93b337a..bccaf4f77647a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -282,14 +282,25 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->feature = 0; break; case AMDGPU_INFO_FW_TA: - if (query_fw->index > 1) - return -EINVAL; - if (query_fw->index == 0) { + switch (query_fw->index) { + case 0: fw_info->ver = adev->psp.ta_fw_version; fw_info->feature = adev->psp.ta_xgmi_ucode_version; - } else { + break; + case 1: fw_info->ver = adev->psp.ta_fw_version; fw_info->feature = adev->psp.ta_ras_ucode_version; + break; + case 2: + fw_info->ver = adev->psp.ta_fw_version; + fw_info->feature = adev->psp.ta_hdcp_ucode_version; + break; + case 3: + fw_info->ver = adev->psp.ta_fw_version; + fw_info->feature = adev->psp.ta_dtm_ucode_version; + break; + default: + return -EINVAL; } break; case AMDGPU_INFO_FW_SDMA: @@ -1385,13 +1396,31 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data) fw_info.feature, fw_info.ver); query_fw.fw_type = AMDGPU_INFO_FW_TA; - for (i = 0; i < 2; i++) { + for (i = 0; i < 4; i++) { query_fw.index = i; ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); if (ret) continue; - seq_printf(m, "TA %s feature version: %u, firmware version: 0x%08x\n", - i ? "RAS" : "XGMI", fw_info.feature, fw_info.ver); + switch (query_fw.index) { + case 0: + seq_printf(m, "TA %s feature version: 0x%08x, firmware version: 0x%08x\n", + "RAS", fw_info.feature, fw_info.ver); + break; + case 1: + seq_printf(m, "TA %s feature version: 0x%08x, firmware version: 0x%08x\n", + "XGMI", fw_info.feature, fw_info.ver); + break; + case 2: + seq_printf(m, "TA %s feature version: 0x%08x, firmware version: 0x%08x\n", + "HDCP", fw_info.feature, fw_info.ver); + break; + case 3: + seq_printf(m, "TA %s feature version: 0x%08x, firmware version: 0x%08x\n", + "DTM", fw_info.feature, fw_info.ver); + break; + default: + return -EINVAL; + } } /* SMC */ -- GitLab From 2b3bbf23549f186520005cecc6795327eeb29a35 Mon Sep 17 00:00:00 2001 From: YueHaibing <yuehaibing@huawei.com> Date: Thu, 10 Sep 2020 15:50:06 +0800 Subject: [PATCH 1152/1494] drm/amdkfd: Fix -Wunused-const-variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If KFD_SUPPORT_IOMMU_V2 is not set, gcc warns: drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_device.c:121:37: warning: ‘raven_device_info’ defined but not used [-Wunused-const-variable=] static const struct kfd_device_info raven_device_info = { ^~~~~~~~~~~~~~~~~ As Huang Rui suggested, Raven already has the fallback path, so it should be out of IOMMU v2 flag. Suggested-by: Huang Rui <ray.huang@amd.com> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Acked-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 0e71a0543f987..e3fc6ed7b79c3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -503,8 +503,8 @@ static const struct kfd_device_info *kfd_supported_devices[][2] = { #ifdef KFD_SUPPORT_IOMMU_V2 [CHIP_KAVERI] = {&kaveri_device_info, NULL}, [CHIP_CARRIZO] = {&carrizo_device_info, NULL}, - [CHIP_RAVEN] = {&raven_device_info, NULL}, #endif + [CHIP_RAVEN] = {&raven_device_info, NULL}, [CHIP_HAWAII] = {&hawaii_device_info, NULL}, [CHIP_TONGA] = {&tonga_device_info, NULL}, [CHIP_FIJI] = {&fiji_device_info, &fiji_vf_device_info}, -- GitLab From 9c7e2ceb1db064da10d8386590ce23afdc7dc6f0 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Fri, 11 Sep 2020 14:26:13 +0800 Subject: [PATCH 1153/1494] drm/amdgpu: Update RAS init handling Output RAS init status If RAS init fails, teardown RAS context Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index a7771aaa1c519..9782fbc000fe1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -935,6 +935,7 @@ static int psp_ras_load(struct psp_context *psp) { int ret; struct psp_gfx_cmd_resp *cmd; + struct ta_ras_shared_memory *ras_cmd; /* * TODO: bypass the loading in sriov for now @@ -958,11 +959,20 @@ static int psp_ras_load(struct psp_context *psp) ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + ras_cmd = (struct ta_ras_shared_memory*)psp->ras.ras_shared_buf; + if (!ret) { - psp->ras.ras_initialized = true; psp->ras.session_id = cmd->resp.session_id; + + if (!ras_cmd->ras_status) + psp->ras.ras_initialized = true; + else + dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); } + if (ret || ras_cmd->ras_status) + amdgpu_ras_fini(psp->adev); + kfree(cmd); return ret; -- GitLab From 5d1c59c47997e9955be3a52e261c08e8b40b3902 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai <aurabindo.pillai@amd.com> Date: Wed, 12 Aug 2020 12:40:34 -0400 Subject: [PATCH 1154/1494] drm/amdgpu: Move existing pflip fields into separate struct [Why&How] To refactor DM IRQ management, all fields used by IRQ is best moved to a separate struct so that main amdgpu_crtc struct need not be changed Location of the new struct shall be in DM Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +-- .../display/amdgpu_dm/amdgpu_dm_irq_params.h | 33 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 04a430e0e2e1a..a04decb934b0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -46,6 +46,7 @@ #include <drm/drm_dp_mst_helper.h> #include "modules/inc/mod_freesync.h" +#include "amdgpu_dm_irq_params.h" struct amdgpu_bo; struct amdgpu_device; @@ -404,7 +405,8 @@ struct amdgpu_crtc { struct amdgpu_flip_work *pflip_works; enum amdgpu_flip_status pflip_status; int deferred_flip_completion; - u32 last_flip_vblank; + /* parameters access from DM IRQ handler */ + struct dm_irq_params dm_irq_params; /* pll sharing */ struct amdgpu_atom_ss ss; bool ss_enabled; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ec29376667df2..1f05ec92556a1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -425,7 +425,7 @@ static void dm_pflip_high_irq(void *interrupt_params) * of pageflip completion, so last_flip_vblank is the forbidden count * for queueing new pageflips if vsync + VRR is enabled. */ - amdgpu_crtc->last_flip_vblank = + amdgpu_crtc->dm_irq_params.last_flip_vblank = amdgpu_get_vblank_counter_kms(&amdgpu_crtc->base); amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; @@ -7197,7 +7197,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * on late submission of flips. */ spin_lock_irqsave(&pcrtc->dev->event_lock, flags); - last_flip_vblank = acrtc_attach->last_flip_vblank; + last_flip_vblank = acrtc_attach->dm_irq_params.last_flip_vblank; spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h new file mode 100644 index 0000000000000..55ef237eed8b7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __AMDGPU_DM_IRQ_PARAMS_H__ +#define __AMDGPU_DM_IRQ_PARAMS_H__ + +struct dm_irq_params { + u32 last_flip_vblank; +}; + +#endif /* __AMDGPU_DM_IRQ_PARAMS_H__ */ -- GitLab From 585d450c76d1d5807a50cb6c22487ae5aed0906b Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai <aurabindo.pillai@amd.com> Date: Wed, 12 Aug 2020 18:56:14 -0400 Subject: [PATCH 1155/1494] drm/amd/display: Refactor to prevent crtc state access in DM IRQ handler [Why&How] Currently commit_tail holds global locks and wait for dependencies which is against the DRM API contracts. Inorder to fix this, IRQ handler should be able to run without having to access crtc state. Required parameters are copied over so that they can be directly accessed from the interrupt handler Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 117 ++++++++++-------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 - .../display/amdgpu_dm/amdgpu_dm_irq_params.h | 4 + 3 files changed, 69 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1f05ec92556a1..b044fab05a2f6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -228,17 +228,14 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) return 0; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state( - acrtc->base.state); - - if (acrtc_state->stream == NULL) { + if (acrtc->dm_irq_params.stream == NULL) { DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", crtc); return 0; } - return dc_stream_get_vblank_counter(acrtc_state->stream); + return dc_stream_get_vblank_counter(acrtc->dm_irq_params.stream); } } @@ -251,10 +248,8 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, return -EINVAL; else { struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; - struct dm_crtc_state *acrtc_state = to_dm_crtc_state( - acrtc->base.state); - if (acrtc_state->stream == NULL) { + if (acrtc->dm_irq_params.stream == NULL) { DRM_ERROR("dc_stream_state is NULL for crtc '%d'!\n", crtc); return 0; @@ -264,7 +259,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, * TODO rework base driver to use values directly. * for now parse it back into reg-format */ - dc_stream_get_scanoutpos(acrtc_state->stream, + dc_stream_get_scanoutpos(acrtc->dm_irq_params.stream, &v_blank_start, &v_blank_end, &h_position, @@ -323,6 +318,14 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev, return NULL; } +static inline bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc) +{ + return acrtc->dm_irq_params.freesync_config.state == + VRR_STATE_ACTIVE_VARIABLE || + acrtc->dm_irq_params.freesync_config.state == + VRR_STATE_ACTIVE_FIXED; +} + static inline bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state) { return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE || @@ -343,7 +346,6 @@ static void dm_pflip_high_irq(void *interrupt_params) struct amdgpu_device *adev = irq_params->adev; unsigned long flags; struct drm_pending_vblank_event *e; - struct dm_crtc_state *acrtc_state; uint32_t vpos, hpos, v_blank_start, v_blank_end; bool vrr_active; @@ -375,12 +377,11 @@ static void dm_pflip_high_irq(void *interrupt_params) if (!e) WARN_ON(1); - acrtc_state = to_dm_crtc_state(amdgpu_crtc->base.state); - vrr_active = amdgpu_dm_vrr_active(acrtc_state); + vrr_active = amdgpu_dm_vrr_active_irq(amdgpu_crtc); /* Fixed refresh rate, or VRR scanout position outside front-porch? */ if (!vrr_active || - !dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start, + !dc_stream_get_scanoutpos(amdgpu_crtc->dm_irq_params.stream, &v_blank_start, &v_blank_end, &hpos, &vpos) || (vpos < v_blank_start)) { /* Update to correct count and vblank timestamp if racing with @@ -441,17 +442,17 @@ static void dm_vupdate_high_irq(void *interrupt_params) struct common_irq_params *irq_params = interrupt_params; struct amdgpu_device *adev = irq_params->adev; struct amdgpu_crtc *acrtc; - struct dm_crtc_state *acrtc_state; unsigned long flags; + int vrr_active; acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); if (acrtc) { - acrtc_state = to_dm_crtc_state(acrtc->base.state); + vrr_active = amdgpu_dm_vrr_active_irq(acrtc); DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d\n", acrtc->crtc_id, - amdgpu_dm_vrr_active(acrtc_state)); + vrr_active); /* Core vblank handling is done here after end of front-porch in * vrr mode, as vblank timestamping will give valid results @@ -459,22 +460,22 @@ static void dm_vupdate_high_irq(void *interrupt_params) * page-flip completion events that have been queued to us * if a pageflip happened inside front-porch. */ - if (amdgpu_dm_vrr_active(acrtc_state)) { + if (vrr_active) { drm_crtc_handle_vblank(&acrtc->base); /* BTR processing for pre-DCE12 ASICs */ - if (acrtc_state->stream && + if (acrtc->dm_irq_params.stream && adev->family < AMDGPU_FAMILY_AI) { spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); mod_freesync_handle_v_update( adev->dm.freesync_module, - acrtc_state->stream, - &acrtc_state->vrr_params); + acrtc->dm_irq_params.stream, + &acrtc->dm_irq_params.vrr_params); dc_stream_adjust_vmin_vmax( adev->dm.dc, - acrtc_state->stream, - &acrtc_state->vrr_params.adjust); + acrtc->dm_irq_params.stream, + &acrtc->dm_irq_params.vrr_params.adjust); spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } } @@ -493,18 +494,17 @@ static void dm_crtc_high_irq(void *interrupt_params) struct common_irq_params *irq_params = interrupt_params; struct amdgpu_device *adev = irq_params->adev; struct amdgpu_crtc *acrtc; - struct dm_crtc_state *acrtc_state; unsigned long flags; + int vrr_active; acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); if (!acrtc) return; - acrtc_state = to_dm_crtc_state(acrtc->base.state); + vrr_active = amdgpu_dm_vrr_active_irq(acrtc); DRM_DEBUG_VBL("crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id, - amdgpu_dm_vrr_active(acrtc_state), - acrtc_state->active_planes); + vrr_active, acrtc->dm_irq_params.active_planes); /** * Core vblank handling at start of front-porch is only possible @@ -512,7 +512,7 @@ static void dm_crtc_high_irq(void *interrupt_params) * valid results while done in front-porch. Otherwise defer it * to dm_vupdate_high_irq after end of front-porch. */ - if (!amdgpu_dm_vrr_active(acrtc_state)) + if (!vrr_active) drm_crtc_handle_vblank(&acrtc->base); /** @@ -527,14 +527,16 @@ static void dm_crtc_high_irq(void *interrupt_params) spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); - if (acrtc_state->stream && acrtc_state->vrr_params.supported && - acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { + if (acrtc->dm_irq_params.stream && + acrtc->dm_irq_params.vrr_params.supported && + acrtc->dm_irq_params.freesync_config.state == + VRR_STATE_ACTIVE_VARIABLE) { mod_freesync_handle_v_update(adev->dm.freesync_module, - acrtc_state->stream, - &acrtc_state->vrr_params); + acrtc->dm_irq_params.stream, + &acrtc->dm_irq_params.vrr_params); - dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc_state->stream, - &acrtc_state->vrr_params.adjust); + dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc->dm_irq_params.stream, + &acrtc->dm_irq_params.vrr_params.adjust); } /* @@ -549,7 +551,7 @@ static void dm_crtc_high_irq(void *interrupt_params) */ if (adev->family >= AMDGPU_FAMILY_RV && acrtc->pflip_status == AMDGPU_FLIP_SUBMITTED && - acrtc_state->active_planes == 0) { + acrtc->dm_irq_params.active_planes == 0) { if (acrtc->event) { drm_crtc_send_vblank_event(&acrtc->base, acrtc->event); acrtc->event = NULL; @@ -4809,7 +4811,6 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) } state->active_planes = cur->active_planes; - state->vrr_params = cur->vrr_params; state->vrr_infopacket = cur->vrr_infopacket; state->abm_level = cur->abm_level; state->vrr_supported = cur->vrr_supported; @@ -6862,6 +6863,7 @@ static void update_freesync_state_on_stream( struct mod_vrr_params vrr_params; struct dc_info_packet vrr_infopacket = {0}; struct amdgpu_device *adev = dm->adev; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc); unsigned long flags; if (!new_stream) @@ -6876,7 +6878,7 @@ static void update_freesync_state_on_stream( return; spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); - vrr_params = new_crtc_state->vrr_params; + vrr_params = acrtc->dm_irq_params.vrr_params; if (surface) { mod_freesync_handle_preflip( @@ -6907,7 +6909,7 @@ static void update_freesync_state_on_stream( &vrr_infopacket); new_crtc_state->freesync_timing_changed |= - (memcmp(&new_crtc_state->vrr_params.adjust, + (memcmp(&acrtc->dm_irq_params.vrr_params.adjust, &vrr_params.adjust, sizeof(vrr_params.adjust)) != 0); @@ -6916,10 +6918,10 @@ static void update_freesync_state_on_stream( &vrr_infopacket, sizeof(vrr_infopacket)) != 0); - new_crtc_state->vrr_params = vrr_params; + acrtc->dm_irq_params.vrr_params = vrr_params; new_crtc_state->vrr_infopacket = vrr_infopacket; - new_stream->adjust = new_crtc_state->vrr_params.adjust; + new_stream->adjust = acrtc->dm_irq_params.vrr_params.adjust; new_stream->vrr_infopacket = vrr_infopacket; if (new_crtc_state->freesync_vrr_info_changed) @@ -6931,7 +6933,7 @@ static void update_freesync_state_on_stream( spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } -static void pre_update_freesync_state_on_stream( +static void update_stream_irq_parameters( struct amdgpu_display_manager *dm, struct dm_crtc_state *new_crtc_state) { @@ -6939,6 +6941,7 @@ static void pre_update_freesync_state_on_stream( struct mod_vrr_params vrr_params; struct mod_freesync_config config = new_crtc_state->freesync_config; struct amdgpu_device *adev = dm->adev; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_crtc_state->base.crtc); unsigned long flags; if (!new_stream) @@ -6952,7 +6955,7 @@ static void pre_update_freesync_state_on_stream( return; spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); - vrr_params = new_crtc_state->vrr_params; + vrr_params = acrtc->dm_irq_params.vrr_params; if (new_crtc_state->vrr_supported && config.min_refresh_in_uhz && @@ -6969,11 +6972,14 @@ static void pre_update_freesync_state_on_stream( &config, &vrr_params); new_crtc_state->freesync_timing_changed |= - (memcmp(&new_crtc_state->vrr_params.adjust, - &vrr_params.adjust, - sizeof(vrr_params.adjust)) != 0); + (memcmp(&acrtc->dm_irq_params.vrr_params.adjust, + &vrr_params.adjust, sizeof(vrr_params.adjust)) != 0); - new_crtc_state->vrr_params = vrr_params; + new_crtc_state->freesync_config = config; + /* Copy state for access from DM IRQ handler */ + acrtc->dm_irq_params.freesync_config = config; + acrtc->dm_irq_params.active_planes = new_crtc_state->active_planes; + acrtc->dm_irq_params.vrr_params = vrr_params; spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } @@ -7281,7 +7287,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_lock_irqsave(&pcrtc->dev->event_lock, flags); dc_stream_adjust_vmin_vmax( dm->dc, acrtc_state->stream, - &acrtc_state->vrr_params.adjust); + &acrtc_attach->dm_irq_params.vrr_params.adjust); spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } mutex_lock(&dm->dc_lock); @@ -7433,6 +7439,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; + struct dm_crtc_state *dm_old_crtc_state; struct amdgpu_device *adev = drm_to_adev(dev); int i; @@ -7454,10 +7461,14 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + if (old_crtc_state->active && (!new_crtc_state->active || - drm_atomic_crtc_needs_modeset(new_crtc_state))) + drm_atomic_crtc_needs_modeset(new_crtc_state))) { manage_dm_interrupts(adev, acrtc, false); + dc_stream_release(dm_old_crtc_state->stream); + } } /* * Add check here for SoC's that support hardware cursor plane, to @@ -7603,7 +7614,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) if (!status) status = dc_stream_get_status_from_state(dc_state, dm_new_crtc_state->stream); - if (!status) DC_ERR("got no status for stream %p on acrtc%p\n", dm_new_crtc_state->stream, acrtc); else @@ -7729,8 +7739,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - /* Update freesync active state. */ - pre_update_freesync_state_on_stream(dm, dm_new_crtc_state); + /* For freesync config update on crtc state and params for irq */ + update_stream_irq_parameters(dm, dm_new_crtc_state); /* Handle vrr on->off / off->on transitions */ amdgpu_dm_handle_vrr_transition(dm_old_crtc_state, @@ -7746,10 +7756,15 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + if (new_crtc_state->active && (!old_crtc_state->active || drm_atomic_crtc_needs_modeset(new_crtc_state))) { + dc_stream_retain(dm_new_crtc_state->stream); + acrtc->dm_irq_params.stream = dm_new_crtc_state->stream; manage_dm_interrupts(adev, acrtc, true); + #ifdef CONFIG_DEBUG_FS /** * Frontend may have changed so reapply the CRC capture @@ -7993,8 +8008,6 @@ static void reset_freesync_config_for_crtc( { new_crtc_state->vrr_supported = false; - memset(&new_crtc_state->vrr_params, 0, - sizeof(new_crtc_state->vrr_params)); memset(&new_crtc_state->vrr_infopacket, 0, sizeof(new_crtc_state->vrr_infopacket)); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a7856ae2e5f50..71a81cabd6eb0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -434,7 +434,6 @@ struct dm_crtc_state { bool vrr_supported; struct mod_freesync_config freesync_config; - struct mod_vrr_params vrr_params; struct dc_info_packet vrr_infopacket; int abm_level; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h index 55ef237eed8b7..45825a34f8ebb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h @@ -28,6 +28,10 @@ struct dm_irq_params { u32 last_flip_vblank; + struct mod_vrr_params vrr_params; + struct dc_stream_state *stream; + int active_planes; + struct mod_freesync_config freesync_config; }; #endif /* __AMDGPU_DM_IRQ_PARAMS_H__ */ -- GitLab From 6d90a208cfff94c519caaecbc5da3af3929bf374 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai <aurabindo.pillai@amd.com> Date: Fri, 11 Sep 2020 15:10:11 -0400 Subject: [PATCH 1156/1494] drm/amd/display: Move disable interrupt into commit tail [Why&How] Since there is no need for accessing crtc state in the interrupt handler, interrupts need not be disabled well in advance, and can be moved to commit_tail where it should be. Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 47 ++++++------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b044fab05a2f6..7ad2c3f7e281b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7437,39 +7437,6 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock) { - struct drm_crtc *crtc; - struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct dm_crtc_state *dm_old_crtc_state; - struct amdgpu_device *adev = drm_to_adev(dev); - int i; - - /* - * We evade vblank and pflip interrupts on CRTCs that are undergoing - * a modeset, being disabled, or have no active planes. - * - * It's done in atomic commit rather than commit tail for now since - * some of these interrupt handlers access the current CRTC state and - * potentially the stream pointer itself. - * - * Since the atomic state is swapped within atomic commit and not within - * commit tail this would leave to new state (that hasn't been committed yet) - * being accesssed from within the handlers. - * - * TODO: Fix this so we can do this in commit tail and not have to block - * in atomic check. - */ - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - - dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - - if (old_crtc_state->active && - (!new_crtc_state->active || - drm_atomic_crtc_needs_modeset(new_crtc_state))) { - manage_dm_interrupts(adev, acrtc, false); - dc_stream_release(dm_old_crtc_state->stream); - } - } /* * Add check here for SoC's that support hardware cursor plane, to * unset legacy_cursor_update @@ -7519,6 +7486,20 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dc_resource_state_copy_construct_current(dm->dc, dc_state); } + for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state, + new_crtc_state, i) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); + + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + + if (old_crtc_state->active && + (!new_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state))) { + manage_dm_interrupts(adev, acrtc, false); + dc_stream_release(dm_old_crtc_state->stream); + } + } + /* update changed items */ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); -- GitLab From 62f6b1162e91a4d31c17ed13ff7c2dcc86eda501 Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Fri, 11 Sep 2020 17:24:14 -0400 Subject: [PATCH 1157/1494] drm/amdgpu: Enable SDMA utilization for Arcturus SDMA utilization calculations are enabled/disabled by writing to SDMAx_PUB_DUMMY_REG2 register. Currently, enable this only for Arcturus. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 856c50386c86f..edea8743f26eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1063,6 +1063,15 @@ static void sdma_v4_0_ctx_switch_enable(struct amdgpu_device *adev, bool enable) WREG32_SDMA(i, mmSDMA0_PHASE2_QUANTUM, phase_quantum); } WREG32_SDMA(i, mmSDMA0_CNTL, f32_cntl); + + /* + * Enable SDMA utilization. Its only supported on + * Arcturus for the moment and firmware version 14 + * and above. + */ + if (adev->asic_type == CHIP_ARCTURUS && + adev->sdma.instance[i].fw_version >= 14) + WREG32_SDMA(i, mmSDMA0_PUB_DUMMY_REG2, enable); } } -- GitLab From 26652cd8deae0b039b00e07e77706d29415b5bce Mon Sep 17 00:00:00 2001 From: Flora Cui <flora.cui@amd.com> Date: Tue, 8 Sep 2020 15:26:43 +0800 Subject: [PATCH 1158/1494] drm/amdgpu: drop BOOLEAN define in display part use bool directly Signed-off-by: Flora Cui <flora.cui@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 2 +- drivers/gpu/drm/amd/display/dc/dm_pp_smu.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index c5f2216e59c47..6a28fdd50e05f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -810,7 +810,7 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) } static enum pp_smu_status pp_nv_set_pstate_handshake_support( - struct pp_smu *pp, BOOLEAN pstate_handshake_supported) + struct pp_smu *pp, bool pstate_handshake_supported) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; diff --git a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h index ae608c329366d..3586934df25f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h +++ b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h @@ -30,8 +30,6 @@ * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC */ -typedef bool BOOLEAN; - enum pp_smu_ver { /* * PP_SMU_INTERFACE_X should be interpreted as the interface defined @@ -240,7 +238,7 @@ struct pp_smu_funcs_nv { * DC hardware */ enum pp_smu_status (*set_pstate_handshake_support)(struct pp_smu *pp, - BOOLEAN pstate_handshake_supported); + bool pstate_handshake_supported); }; #define PP_SMU_NUM_SOCCLK_DPM_LEVELS 8 -- GitLab From 39767222bf311e6aa6465315f8eb4acc022db48d Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Mon, 14 Sep 2020 14:42:51 +0800 Subject: [PATCH 1159/1494] drm/amd/pm: support runtime pptable update for sienna_cichlid etc. This avoids smu issue when enabling runtime pptable update for sienna_cichlid and so on. Runtime pptable udpate is needed for test and debug purpose. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Kenneth Feng <kenneth.feng@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7a55ece1f1246..7618f9972b8c3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1129,7 +1129,7 @@ static int smu_disable_dpms(struct smu_context *smu) */ if (smu->uploading_custom_pp_table && (adev->asic_type >= CHIP_NAVI10) && - (adev->asic_type <= CHIP_NAVI12)) + (adev->asic_type <= CHIP_NAVY_FLOUNDER)) return 0; /* @@ -1214,7 +1214,9 @@ static int smu_hw_fini(void *handle) int smu_reset(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - int ret = 0; + int ret; + + amdgpu_gfx_off_ctrl(smu->adev, false); ret = smu_hw_fini(adev); if (ret) @@ -1225,8 +1227,12 @@ int smu_reset(struct smu_context *smu) return ret; ret = smu_late_init(adev); + if (ret) + return ret; - return ret; + amdgpu_gfx_off_ctrl(smu->adev, true); + + return 0; } static int smu_suspend(void *handle) -- GitLab From 8e8e9463a8fdcdd74cd727864bb84bc509caf48e Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Mon, 17 Aug 2020 09:59:57 -0400 Subject: [PATCH 1160/1494] drm/amd/display: [FW Promotion] Release 0.0.30 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index d7e7f2eda92fd..5eb642fe93150 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x4e5b2f46f +#define DMUB_FW_VERSION_GIT_HASH 0xb18f2464d #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 29 +#define DMUB_FW_VERSION_REVISION 30 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 -- GitLab From 14ae69026f840bf3a1ff861ccd43d4e96d6b08cf Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 17 Aug 2020 12:16:28 -0400 Subject: [PATCH 1161/1494] drm/amd/display: 3.2.100 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1d9c8e09c08b2..7416fd37e7d8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.99" +#define DC_VER "3.2.100" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From a861736dae644a0d7abbca0c638ae6aad28feeb8 Mon Sep 17 00:00:00 2001 From: Naveed Ashfaq <Naveed.Ashfaq@amd.com> Date: Fri, 14 Aug 2020 13:48:13 -0400 Subject: [PATCH 1162/1494] drm/amd/display: Fixed Intermittent blue screen on OLED panel [why] Changing to smaller modes on OLED panel caused a blue screen crash as driver reported dram change during vactive when it shouldn't [how] Added an extra condition to prevent incorrect dram change timing Signed-off-by: Naveed Ashfaq <Naveed.Ashfaq@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/dc/dml/dcn20/display_mode_vba_20v2.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 80170f9721ce9..860e72a51534c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -2635,15 +2635,14 @@ static void dml20v2_DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndP } if (mode_lib->vba.DRAMClockChangeSupportsVActive && - mode_lib->vba.MinActiveDRAMClockChangeMargin > 60) { + mode_lib->vba.MinActiveDRAMClockChangeMargin > 60 && + mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) { mode_lib->vba.DRAMClockChangeWatermark += 25; for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { - if (mode_lib->vba.PrefetchMode[mode_lib->vba.VoltageLevel][mode_lib->vba.maxMpcComb] == 0) { - if (mode_lib->vba.DRAMClockChangeWatermark > - dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)) - mode_lib->vba.MinTTUVBlank[k] += 25; - } + if (mode_lib->vba.DRAMClockChangeWatermark > + dml_max(mode_lib->vba.StutterEnterPlusExitWatermark, mode_lib->vba.UrgentWatermark)) + mode_lib->vba.MinTTUVBlank[k] += 25; } mode_lib->vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive; -- GitLab From 498563cf9ca00dc4ee389cf2729dae81417a144f Mon Sep 17 00:00:00 2001 From: "JinZe.Xu" <JinZe.Xu@amd.com> Date: Thu, 13 Aug 2020 16:59:24 +0800 Subject: [PATCH 1163/1494] drm/amd/display: Detect plane change when detect pipe change. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] If plane has changed, dcn20_detect_pipe_changes doesn't update dc_plane_state->update_flags, and the following dcn20_program_pipe can't reprogram hubp correctly. [How] Add a new flags bit "plane_changed" in pipe_ctx->update_flags.If old plane isn’t identical to new plane, this bit will be set and guide “dcn20_program_pipe†to programing HUBP correctly. Signed-off-by: JinZe.Xu <JinZe.Xu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 12 +++++++++++- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index c8cfd3ba1c156..ee3348711abee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1251,6 +1251,11 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx return; } + /* Detect plane change */ + if (old_pipe->plane_state != new_pipe->plane_state) { + new_pipe->update_flags.bits.plane_changed = true; + } + /* Detect top pipe only changes */ if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) { /* Detect odm changes */ @@ -1392,6 +1397,7 @@ static void dcn20_update_dchubp_dpp( &pipe_ctx->ttu_regs); if (pipe_ctx->update_flags.bits.enable || + pipe_ctx->update_flags.bits.plane_changed || plane_state->update_flags.bits.bpp_change || plane_state->update_flags.bits.input_csc_change || plane_state->update_flags.bits.color_space_change || @@ -1414,6 +1420,7 @@ static void dcn20_update_dchubp_dpp( } if (pipe_ctx->update_flags.bits.mpcc + || pipe_ctx->update_flags.bits.plane_changed || plane_state->update_flags.bits.global_alpha_change || plane_state->update_flags.bits.per_pixel_alpha_change) { // MPCC inst is equal to pipe index in practice @@ -1515,6 +1522,7 @@ static void dcn20_update_dchubp_dpp( } if (pipe_ctx->update_flags.bits.enable || + pipe_ctx->update_flags.bits.plane_changed || pipe_ctx->update_flags.bits.opp_changed || plane_state->update_flags.bits.pixel_format_change || plane_state->update_flags.bits.horizontal_mirror_change || @@ -1539,7 +1547,9 @@ static void dcn20_update_dchubp_dpp( hubp->power_gated = false; } - if (pipe_ctx->update_flags.bits.enable || plane_state->update_flags.bits.addr_update) + if (pipe_ctx->update_flags.bits.enable || + pipe_ctx->update_flags.bits.plane_changed || + plane_state->update_flags.bits.addr_update) hws->funcs.update_plane_addr(dc, pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 329395ee74610..cc5f053ef5a33 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -300,6 +300,7 @@ union pipe_update_flags { uint32_t gamut_remap : 1; uint32_t scaler : 1; uint32_t viewport : 1; + uint32_t plane_changed : 1; } bits; uint32_t raw; }; -- GitLab From 958000cb24cc2db5f3ce1c70b9ad2b3e20b73581 Mon Sep 17 00:00:00 2001 From: Harmanprit Tatla <harmanprit.tatla@amd.com> Date: Wed, 19 Aug 2020 17:39:45 -0400 Subject: [PATCH 1164/1494] drm/amd/display: Add CP_IRQ clear capability [Why] Currently we do not clear the CP_IRQ bit upon receiving it. [How] Added a function to clear CP_IRQ bit. Signed-off-by: Harmanprit Tatla <harmanprit.tatla@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/modules/hdcp/hdcp.c | 9 +++++++++ .../gpu/drm/amd/display/modules/hdcp/hdcp.h | 1 + .../drm/amd/display/modules/hdcp/hdcp_ddc.c | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index e9fbd94f8635e..a82975970e870 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -470,6 +470,15 @@ enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, if (reset_status != MOD_HDCP_STATUS_SUCCESS) push_error_status(hdcp, reset_status); } + + /* Clear CP_IRQ status if needed */ + if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ && + event_ctx.unexpected_event == 0) { + status = mod_hdcp_clear_cp_irq_status(hdcp); + if (status != MOD_HDCP_STATUS_SUCCESS) + push_error_status(hdcp, status); + } + return status; } diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index b0cefed2eb026..6c678cfb82e39 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -386,6 +386,7 @@ enum mod_hdcp_status mod_hdcp_write_eks(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_write_repeater_auth_ack(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_write_stream_manage(struct mod_hdcp *hdcp); enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp); +enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp); /* hdcp version helpers */ static inline uint8_t is_dp_hdcp(struct mod_hdcp *hdcp) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index bb5130f4228db..9dd8c854fd819 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -645,3 +645,22 @@ enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp) status = MOD_HDCP_STATUS_INVALID_OPERATION; return status; } + +enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp) +{ + uint8_t clear_cp_irq_bit = 2; + uint32_t size = 1; + + if (is_dp_hdcp(hdcp)) { + if (hdcp->connection.link.dp.rev >= 0x14) + return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, + DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &clear_cp_irq_bit, size) + ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; + else + return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, + DP_DEVICE_SERVICE_IRQ_VECTOR, &clear_cp_irq_bit, size) + ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; + } + + return MOD_HDCP_STATUS_INVALID_OPERATION; +} -- GitLab From 0b02e1fda5422a144a8bfca9be22547b4d291f20 Mon Sep 17 00:00:00 2001 From: Joshua Aberback <joshua.aberback@amd.com> Date: Thu, 20 Aug 2020 00:57:22 -0400 Subject: [PATCH 1165/1494] drm/amd/display: Compare mpcc_inst to mpcc_count instead of a constant [Why] This assert triggers a false negative because there are more than 4 MPCCs on many asics. [How] - change assert comparisson - remove unused variable Signed-off-by: Joshua Aberback <joshua.aberback@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index a5d750ed569e1..1390ff1ce7bef 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -220,15 +220,13 @@ static void dcn30_set_writeback( struct dc_writeback_info *wb_info, struct dc_state *context) { - struct dwbc *dwb; struct mcif_wb *mcif_wb; struct mcif_buf_params *mcif_buf_params; ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES); ASSERT(wb_info->wb_enabled); ASSERT(wb_info->mpcc_inst >= 0); - ASSERT(wb_info->mpcc_inst < 4); - dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; + ASSERT(wb_info->mpcc_inst < dc->res_pool->mpcc_count); mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst]; mcif_buf_params = &wb_info->mcif_buf_params; -- GitLab From ce17ce17af328a3a1fd0c5e00f6b04af94b0be01 Mon Sep 17 00:00:00 2001 From: Wenjing Liu <wenjing.liu@amd.com> Date: Fri, 7 Aug 2020 19:08:25 -0400 Subject: [PATCH 1166/1494] drm/amd/display: add option to override cr training pattern Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 33 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 1 + .../amd/display/include/link_service_types.h | 1 + 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d1d95d3e248a7..2334ec428098c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -101,7 +101,16 @@ static void dpcd_set_training_pattern( dpcd_pattern.v1_4.TRAINING_PATTERN_SET); } -static enum dc_dp_training_pattern get_supported_tp(struct dc_link *link) +static enum dc_dp_training_pattern decide_cr_training_pattern( + const struct dc_link_settings *link_settings) +{ + enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_1; + + return pattern; +} + +static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, + const struct dc_link_settings *link_settings) { enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2; struct encoder_feature_support *features = &link->link_enc->features; @@ -132,7 +141,6 @@ static void dpcd_set_link_settings( union down_spread_ctrl downspread = { {0} }; union lane_count_set lane_count_set = { {0} }; - enum dc_dp_training_pattern dp_tr_pattern; downspread.raw = (uint8_t) (lt_settings->link_settings.link_spread); @@ -143,9 +151,8 @@ static void dpcd_set_link_settings( lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing; lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; - dp_tr_pattern = get_supported_tp(link); - if (dp_tr_pattern != DP_TRAINING_PATTERN_SEQUENCE_4) { + if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) { lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; } @@ -979,7 +986,7 @@ static void start_clock_recovery_pattern_early(struct dc_link *link, { DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n", __func__); - dp_set_hw_training_pattern(link, DP_TRAINING_PATTERN_SEQUENCE_1, offset); + dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset); dp_set_hw_lane_settings(link, lt_settings, offset); udelay(400); } @@ -994,7 +1001,6 @@ static enum link_training_result perform_clock_recovery_sequence( uint32_t wait_time_microsec; struct link_training_settings req_settings; enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; - enum dc_dp_training_pattern tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_1; union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; union lane_align_status_updated dpcd_lane_status_updated; @@ -1002,7 +1008,7 @@ static enum link_training_result perform_clock_recovery_sequence( retry_count = 0; if (!link->ctx->dc->work_arounds.lt_early_cr_pattern) - dp_set_hw_training_pattern(link, tr_pattern, offset); + dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset); /* najeeb - The synaptics MST hub can put the LT in * infinite loop by switching the VS @@ -1029,7 +1035,7 @@ static enum link_training_result perform_clock_recovery_sequence( dpcd_set_lt_pattern_and_lane_settings( link, lt_settings, - tr_pattern, + lt_settings->pattern_for_cr, offset); else dpcd_set_lane_settings( @@ -1113,7 +1119,7 @@ static inline enum link_training_result perform_link_training_int( * TPS4 must be used instead of POST_LT_ADJ_REQ. */ if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || - get_supported_tp(link) == DP_TRAINING_PATTERN_SEQUENCE_4) + lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) return status; if (status == LINK_TRAINING_SUCCESS && @@ -1252,10 +1258,14 @@ static void initialize_training_settings( else lt_settings->eq_pattern_time = get_training_aux_rd_interval(link, 400); + if (overrides->pattern_for_cr != NULL) + lt_settings->pattern_for_cr = *overrides->pattern_for_cr; + else + lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting); if (overrides->pattern_for_eq != NULL) lt_settings->pattern_for_eq = *overrides->pattern_for_eq; else - lt_settings->pattern_for_eq = get_supported_tp(link); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting); if (overrides->enhanced_framing != NULL) lt_settings->enhanced_framing = *overrides->enhanced_framing; @@ -1457,7 +1467,6 @@ bool dc_link_dp_perform_link_training_skip_aux( const struct dc_link_settings *link_setting) { struct link_training_settings lt_settings; - enum dc_dp_training_pattern pattern_for_cr = DP_TRAINING_PATTERN_SEQUENCE_1; initialize_training_settings( link, @@ -1468,7 +1477,7 @@ bool dc_link_dp_perform_link_training_skip_aux( /* 1. Perform_clock_recovery_sequence. */ /* transmit training pattern for clock recovery */ - dp_set_hw_training_pattern(link, pattern_for_cr, DPRX); + dp_set_hw_training_pattern(link, lt_settings.pattern_for_cr, DPRX); /* call HWSS to set lane settings*/ dp_set_hw_lane_settings(link, <_settings, DPRX); diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index a8a3b06435057..80a2191a3115c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -123,6 +123,7 @@ struct dc_link_training_overrides { uint16_t *cr_pattern_time; uint16_t *eq_pattern_time; + enum dc_dp_training_pattern *pattern_for_cr; enum dc_dp_training_pattern *pattern_for_eq; enum dc_link_spread *downspread; diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 550f46e9b95f6..7392a89e771ff 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -80,6 +80,7 @@ struct link_training_settings { uint16_t cr_pattern_time; uint16_t eq_pattern_time; + enum dc_dp_training_pattern pattern_for_cr; enum dc_dp_training_pattern pattern_for_eq; bool enhanced_framing; -- GitLab From 091018a51c16ec28db3603dcf85832ec57ccf5fe Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Fri, 21 Aug 2020 11:33:22 -0400 Subject: [PATCH 1167/1494] drm/amd/display: Triplebuffering should not be used by default Disable triplebuffering by default. Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 +++------ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 13 ++++++------- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- .../gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 ++ .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7ad2c3f7e281b..643eb8e337aab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3375,9 +3375,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) goto fail; } - /* No userspace support. */ - dm->dc->debug.disable_tri_buf = true; - return 0; fail: kfree(aencoder); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index dc463d99ef503..511ab25b3f1aa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2415,8 +2415,7 @@ static void commit_planes_for_stream(struct dc *dc, plane_state->triplebuffer_flips = false; if (update_type == UPDATE_TYPE_FAST && dc->hwss.program_triplebuffer != NULL && - !plane_state->flip_immediate && - !dc->debug.disable_tri_buf) { + !plane_state->flip_immediate && dc->debug.enable_tri_buf) { /*triple buffer for VUpdate only*/ plane_state->triplebuffer_flips = true; } @@ -2443,8 +2442,7 @@ static void commit_planes_for_stream(struct dc *dc, ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); - if (dc->hwss.program_triplebuffer != NULL && - !dc->debug.disable_tri_buf) { + if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); @@ -2509,8 +2507,7 @@ static void commit_planes_for_stream(struct dc *dc, if (pipe_ctx->plane_state != plane_state) continue; /*program triple buffer after lock based on flip type*/ - if (dc->hwss.program_triplebuffer != NULL && - !dc->debug.disable_tri_buf) { + if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { /*only enable triplebuffer for fast_update*/ dc->hwss.program_triplebuffer( dc, pipe_ctx, plane_state->triplebuffer_flips); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 7416fd37e7d8d..0607122e04ded 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -476,7 +476,7 @@ struct dc_debug_options { unsigned int force_odm_combine_4to1; //bit vector based on otg inst #endif unsigned int force_fclk_khz; - bool disable_tri_buf; + bool enable_tri_buf; bool dmub_offload_enabled; bool dmcub_emulation; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index ee3348711abee..ee56060943f1c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1642,16 +1642,15 @@ void dcn20_program_front_end_for_ctx( struct dce_hwseq *hws = dc->hwseq; DC_LOGGER_INIT(dc->ctx->logger); - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { - ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); - if (dc->hwss.program_triplebuffer != NULL && - !dc->debug.disable_tri_buf) { + if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { + ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( - dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); } } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 1b98744451345..55ce2c7df84ef 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1075,7 +1075,6 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_pplib_wm_range = false, .scl_reset_length10 = true, .sanity_checks = false, - .disable_tri_buf = true, .underflow_assert_delay_us = 0xFFFFFFFF, }; @@ -1092,6 +1091,7 @@ static const struct dc_debug_options debug_defaults_diags = { .disable_stutter = true, .scl_reset_length10 = true, .underflow_assert_delay_us = 0xFFFFFFFF, + .enable_tri_buf = true, }; void dcn20_dpp_destroy(struct dpp **dpp) diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 78743ae37851f..e73785e74cba8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -894,6 +894,8 @@ static const struct dc_debug_options debug_defaults_diags = { .disable_pplib_wm_range = true, .disable_stutter = true, .disable_48mhz_pwrdwn = true, + .disable_psr = true, + .enable_tri_buf = true }; enum dcn20_clk_src_array_id { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 8be4f21169d07..6746d582d723c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -865,6 +865,7 @@ static const struct dc_debug_options debug_defaults_diags = { .scl_reset_length10 = true, .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, + .enable_tri_buf = true, }; void dcn30_dpp_destroy(struct dpp **dpp) -- GitLab From 4b4f21ff7f5d11bb77e169b306dcbc5b216f5db5 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Date: Thu, 20 Aug 2020 14:26:07 -0400 Subject: [PATCH 1168/1494] drm/amd/display: Check clock table return During the load processes for Renoir, our display code needs to retrieve the SMU clock and voltage table, however, this operation can fail which means that we have to check this scenario. Currently, we are not handling this case properly and as a result, we have seen the following dmesg log during the boot: RIP: 0010:rn_clk_mgr_construct+0x129/0x3d0 [amdgpu] ... Call Trace: dc_clk_mgr_create+0x16a/0x1b0 [amdgpu] dc_create+0x231/0x760 [amdgpu] This commit fixes this issue by checking the return status retrieved from the clock table before try to populate any bandwidth. Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 543afa34d87aa..136ae6d70c809 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -761,6 +761,7 @@ void rn_clk_mgr_construct( { struct dc_debug_options *debug = &ctx->dc->debug; struct dpm_clocks clock_table = { 0 }; + enum pp_smu_status status = 0; clk_mgr->base.ctx = ctx; clk_mgr->base.funcs = &dcn21_funcs; @@ -818,8 +819,10 @@ void rn_clk_mgr_construct( clk_mgr->base.bw_params = &rn_bw_params; if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) { - pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table); - if (ctx->dc_bios && ctx->dc_bios->integrated_info) { + status = pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table); + + if (status == PP_SMU_RESULT_OK && + ctx->dc_bios && ctx->dc_bios->integrated_info) { rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info); } } -- GitLab From 81ac89cab037c5ebe0f27638dbb2cf45ef7e26df Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Sun, 23 Aug 2020 20:18:11 -0400 Subject: [PATCH 1169/1494] drm/amd/display: [FW Promotion] Release 0.0.31 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 5eb642fe93150..3f84060d79c02 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xb18f2464d +#define DMUB_FW_VERSION_GIT_HASH 0x08aa15e57 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 30 +#define DMUB_FW_VERSION_REVISION 31 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 -- GitLab From 64fbb86d6b6f72c420dfcf23f82811a44d1c4670 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 24 Aug 2020 10:25:33 -0400 Subject: [PATCH 1170/1494] drm/amd/display: 3.2.101 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0607122e04ded..464f2c657597d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.100" +#define DC_VER "3.2.101" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 3fb068c3ec862b63b002e7818896cebea925e109 Mon Sep 17 00:00:00 2001 From: Wenjing Liu <wenjing.liu@amd.com> Date: Tue, 11 Aug 2020 18:27:48 -0400 Subject: [PATCH 1171/1494] drm/amd/display: always use 100us for cr aux rd interval [why] The cr training aux rd interval is modified without following specs requirements. According to the commit message the change was not intended to modify the value. Therefore it looks like it is caused by a typo in the change. Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 2334ec428098c..e4b3b71dad03c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -49,14 +49,14 @@ static struct dc_link_settings get_common_supported_link_settings( struct dc_link_settings link_setting_a, struct dc_link_settings link_setting_b); -static uint32_t get_training_aux_rd_interval( +static uint32_t get_eq_training_aux_rd_interval( struct dc_link *link, - uint32_t default_wait_in_micro_secs) + const struct dc_link_settings *link_settings) { union training_aux_rd_interval training_rd_interval; + uint32_t wait_in_micro_secs = 400; memset(&training_rd_interval, 0, sizeof(training_rd_interval)); - /* overwrite the delay if rev > 1.1*/ if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { /* DP 1.2 or later - retrieve delay through @@ -68,10 +68,10 @@ static uint32_t get_training_aux_rd_interval( sizeof(training_rd_interval)); if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) - default_wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; } - return default_wait_in_micro_secs; + return wait_in_micro_secs; } static void wait_for_training_aux_rd_interval( @@ -1251,12 +1251,12 @@ static void initialize_training_settings( if (overrides->cr_pattern_time != NULL) lt_settings->cr_pattern_time = *overrides->cr_pattern_time; else - lt_settings->cr_pattern_time = get_training_aux_rd_interval(link, 100); + lt_settings->cr_pattern_time = 100; if (overrides->eq_pattern_time != NULL) lt_settings->eq_pattern_time = *overrides->eq_pattern_time; else - lt_settings->eq_pattern_time = get_training_aux_rd_interval(link, 400); + lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting); if (overrides->pattern_for_cr != NULL) lt_settings->pattern_for_cr = *overrides->pattern_for_cr; -- GitLab From 05e3d830fac89af58b9b6a78e5a498f2984cd2cf Mon Sep 17 00:00:00 2001 From: Wesley Chalmers <Wesley.Chalmers@amd.com> Date: Tue, 25 Aug 2020 10:57:24 -0400 Subject: [PATCH 1172/1494] drm/amd/display: Only use offset for first ODM pipe [WHY] Only the first pipe in ODM combine group should have nonzero recout offset. All other pipes should have recout offset 0; otherwise there will be gaps in the image. [HOW] Set recout.x to 0 if the pipe is not the leftmost ODM pipe. When computing viewports, calculate the horizontal offset of a pipe's src based on the current pipe's position in the ODM group, plus whatever offset the leftmost ODM pipe has; otherwise there will be discontinuity in the image. Since ODM combine can only combine pipes horizontally, nothing needs to be done for recout.y. Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index c6b737dd84255..4cea9344d8aae 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -782,7 +782,13 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); - data->recout.x = stream->dst.x; + /* + * Only the leftmost ODM pipe should be offset by a nonzero distance + */ + if (!pipe_ctx->prev_odm_pipe) + data->recout.x = stream->dst.x; + else + data->recout.x = 0; if (stream->src.x < surf_clip.x) data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; @@ -957,7 +963,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe = pipe_ctx->prev_odm_pipe; + struct pipe_ctx *odm_pipe = pipe_ctx; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; @@ -988,21 +994,24 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) swap(src.width, src.height); } + /*modified recout_skip_h calculation due to odm having no recout offset*/ + while (odm_pipe->prev_odm_pipe) { + odm_idx++; + odm_pipe = odm_pipe->prev_odm_pipe; + } + /*odm_pipe is the leftmost pipe in the ODM group*/ + recout_skip_h = odm_idx * data->recout.width; + /* Recout matching initial vp offset = recout_offset - (stream dst offset + * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) * - (surf surf_src offset * 1/ full scl ratio)) */ - recout_skip_h = data->recout.x - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) + recout_skip_h += odm_pipe->plane_res.scl_data.recout.x + - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) * stream->dst.width / stream->src.width - src.x * plane_state->dst_rect.width / src.width * stream->dst.width / stream->src.width); - /*modified recout_skip_h calculation due to odm having no recout offset*/ - while (odm_pipe) { - odm_idx++; - odm_pipe = odm_pipe->prev_odm_pipe; - } - if (odm_idx) - recout_skip_h += odm_idx * data->recout.width; + recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - -- GitLab From 5cd04c4846a3f910fc8a7150cae81542a0ab32d3 Mon Sep 17 00:00:00 2001 From: Harmanprit Tatla <harmanprit.tatla@amd.com> Date: Thu, 20 Aug 2020 15:52:18 -0400 Subject: [PATCH 1173/1494] drm/amd/display: Fix CP_IRQ clear bit and logic [Why] Currently clearing the wrong bit for CP_IRQ, and logic on when to clear needs to be fixed. [How] Corrected bit to clear and improved logic for decision to clear. Signed-off-by: Harmanprit Tatla <harmanprit.tatla@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c | 3 +-- .../gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index a82975970e870..20e554e771d16 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -472,8 +472,7 @@ enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, } /* Clear CP_IRQ status if needed */ - if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ && - event_ctx.unexpected_event == 0) { + if (event_ctx.event == MOD_HDCP_EVENT_CPIRQ) { status = mod_hdcp_clear_cp_irq_status(hdcp); if (status != MOD_HDCP_STATUS_SUCCESS) push_error_status(hdcp, status); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index 9dd8c854fd819..f7b5583ee609a 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -30,6 +30,8 @@ #define KSV_READ_SIZE 0xf /* 0x6803b - 0x6802c */ #define HDCP_MAX_AUX_TRANSACTION_SIZE 16 +#define DP_CP_IRQ (1 << 2) + enum mod_hdcp_ddc_message_id { MOD_HDCP_MESSAGE_ID_INVALID = -1, @@ -648,18 +650,14 @@ enum mod_hdcp_status mod_hdcp_write_content_type(struct mod_hdcp *hdcp) enum mod_hdcp_status mod_hdcp_clear_cp_irq_status(struct mod_hdcp *hdcp) { - uint8_t clear_cp_irq_bit = 2; + uint8_t clear_cp_irq_bit = DP_CP_IRQ; uint32_t size = 1; if (is_dp_hdcp(hdcp)) { - if (hdcp->connection.link.dp.rev >= 0x14) - return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, - DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0, &clear_cp_irq_bit, size) - ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; - else - return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, - DP_DEVICE_SERVICE_IRQ_VECTOR, &clear_cp_irq_bit, size) - ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; + uint32_t cp_irq_addrs = (hdcp->connection.link.dp.rev >= 0x14) + ? DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0:DP_DEVICE_SERVICE_IRQ_VECTOR; + return hdcp->config.ddc.funcs.write_dpcd(hdcp->config.ddc.handle, cp_irq_addrs, + &clear_cp_irq_bit, size) ? MOD_HDCP_STATUS_SUCCESS : MOD_HDCP_STATUS_DDC_FAILURE; } return MOD_HDCP_STATUS_INVALID_OPERATION; -- GitLab From 172c9b77816549c660aaa79e5df5c1be479f266b Mon Sep 17 00:00:00 2001 From: Ashley Thomas <Ashley.Thomas2@amd.com> Date: Thu, 6 Aug 2020 19:18:37 -0700 Subject: [PATCH 1174/1494] drm/amd/display: Power eDP panel back ON before link training retry [why] When link training failures occur for eDP, dp_disable_link_phy is called which powers OFF eDP panel. After link training retry delay, the next retry begins by calling dp_enable_link_phy which does not issue a correspnding eDP panel power ON, leaving panel powered OFF which leads to display OFF/dark. [how] Power ON eDP before next link training retry. Signed-off-by: Ashley Thomas <Ashley.Thomas2@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 ++ .../drm/amd/display/dc/core/dc_link_hwss.c | 6 ++ .../display/dc/dce110/dce110_hw_sequencer.c | 84 ++++++++++++++----- 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e4b3b71dad03c..47fb09f41bfbe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1619,6 +1619,9 @@ bool perform_link_training_with_retries( for (j = 0; j < attempts; ++j) { + DC_LOG_HW_LINK_TRAINING("%s: Beginning link training attempt %u of %d\n", + __func__, (unsigned int)j + 1, attempts); + dp_enable_link_phy( link, signal, @@ -1647,6 +1650,9 @@ bool perform_link_training_with_retries( if (j == (attempts - 1)) break; + DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n", + __func__, (unsigned int)j + 1, attempts); + dp_disable_link_phy(link, signal); msleep(delay_between_attempts); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index dd88eb348dfa6..81c026319ccdd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -104,6 +104,12 @@ void dp_enable_link_phy( struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source; unsigned int i; + + if (link->connector_signal == SIGNAL_TYPE_EDP) { + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + } + /* If the current pixel clock source is not DTO(happens after * switching from HDMI passive dongle to DP on the same connector), * switch the pixel clock source to DTO. diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 0603ddca7bd06..1002ce9979dce 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -810,37 +810,66 @@ void dce110_edp_power_control( if (power_up != link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl)) { + + unsigned long long current_ts = dm_get_timestamp(ctx); + unsigned long long time_since_edp_poweroff_ms = + div64_u64(dm_get_elapse_time_in_ns( + ctx, + current_ts, + link->link_trace.time_stamp.edp_poweroff), 1000000); + unsigned long long time_since_edp_poweron_ms = + div64_u64(dm_get_elapse_time_in_ns( + ctx, + current_ts, + link->link_trace.time_stamp.edp_poweron), 1000000); + DC_LOG_HW_RESUME_S3( + "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu", + __func__, + power_up, + current_ts, + link->link_trace.time_stamp.edp_poweroff, + link->link_trace.time_stamp.edp_poweron, + time_since_edp_poweroff_ms, + time_since_edp_poweron_ms); + /* Send VBIOS command to prompt eDP panel power */ if (power_up) { - unsigned long long current_ts = dm_get_timestamp(ctx); - unsigned long long duration_in_ms = - div64_u64(dm_get_elapse_time_in_ns( - ctx, - current_ts, - link->link_trace.time_stamp.edp_poweroff), 1000000); - unsigned long long wait_time_ms = 0; - - /* max 500ms from LCDVDD off to on */ - unsigned long long edp_poweroff_time_ms = 500; + /* edp requires a min of 500ms from LCDVDD off to on */ + unsigned long long remaining_min_edp_poweroff_time_ms = 500; + /* add time defined by a patch, if any (usually patch extra_t12_ms is 0) */ if (link->local_sink != NULL) - edp_poweroff_time_ms = - 500 + link->local_sink->edid_caps.panel_patch.extra_t12_ms; - if (link->link_trace.time_stamp.edp_poweroff == 0) - wait_time_ms = edp_poweroff_time_ms; - else if (duration_in_ms < edp_poweroff_time_ms) - wait_time_ms = edp_poweroff_time_ms - duration_in_ms; - - if (wait_time_ms) { - msleep(wait_time_ms); - dm_output_to_console("%s: wait %lld ms to power on eDP.\n", - __func__, wait_time_ms); + remaining_min_edp_poweroff_time_ms += + link->local_sink->edid_caps.panel_patch.extra_t12_ms; + + /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */ + if (link->link_trace.time_stamp.edp_poweroff != 0) { + if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms) + remaining_min_edp_poweroff_time_ms = + remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms; + else + remaining_min_edp_poweroff_time_ms = 0; } + if (remaining_min_edp_poweroff_time_ms) { + DC_LOG_HW_RESUME_S3( + "%s: remaining_min_edp_poweroff_time_ms=%llu: begin wait.\n", + __func__, remaining_min_edp_poweroff_time_ms); + msleep(remaining_min_edp_poweroff_time_ms); + DC_LOG_HW_RESUME_S3( + "%s: remaining_min_edp_poweroff_time_ms=%llu: end wait.\n", + __func__, remaining_min_edp_poweroff_time_ms); + dm_output_to_console("%s: wait %lld ms to power on eDP.\n", + __func__, remaining_min_edp_poweroff_time_ms); + } else { + DC_LOG_HW_RESUME_S3( + "%s: remaining_min_edp_poweroff_time_ms=%llu: no wait required.\n", + __func__, remaining_min_edp_poweroff_time_ms); + } } DC_LOG_HW_RESUME_S3( - "%s: Panel Power action: %s\n", + "%s: BEGIN: Panel Power action: %s\n", __func__, (power_up ? "On":"Off")); cntl.action = power_up ? @@ -864,12 +893,23 @@ void dce110_edp_power_control( bp_result = link_transmitter_control(ctx->dc_bios, &cntl); + DC_LOG_HW_RESUME_S3( + "%s: END: Panel Power action: %s bp_result=%u\n", + __func__, (power_up ? "On":"Off"), + bp_result); + if (!power_up) /*save driver power off time stamp*/ link->link_trace.time_stamp.edp_poweroff = dm_get_timestamp(ctx); else link->link_trace.time_stamp.edp_poweron = dm_get_timestamp(ctx); + DC_LOG_HW_RESUME_S3( + "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n", + __func__, + link->link_trace.time_stamp.edp_poweroff, + link->link_trace.time_stamp.edp_poweron); + if (bp_result != BP_RESULT_OK) DC_LOG_ERROR( "%s: Panel Power bp_result: %d\n", -- GitLab From 123ecf6836904bc38bd24402f583e464e6c51fc9 Mon Sep 17 00:00:00 2001 From: Aidan Gratton <Aidan.Gratton@amd.com> Date: Mon, 17 Aug 2020 14:50:12 -0600 Subject: [PATCH 1175/1494] drm/amd/display: Increase Max EDID Size Constant [HOW & WHY] Change max EDID size constant to 1280 to support 10-block EDIDs. Signed-off-by: Aidan Gratton <Aidan.Gratton@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index aa8e0955db482..c47a19719de2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -122,7 +122,7 @@ struct dc_context { }; -#define DC_MAX_EDID_BUFFER_SIZE 1024 +#define DC_MAX_EDID_BUFFER_SIZE 1280 #define DC_EDID_BLOCK_SIZE 128 #define MAX_SURFACE_NUM 4 #define NUM_PIXEL_FORMATS 10 -- GitLab From e8cb7a4dd9dffff72172d94dcea4577219426106 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Fri, 21 Aug 2020 11:26:51 -0400 Subject: [PATCH 1176/1494] drm/amd/display: Flip pending check timeout due to disabled hubp [Why] When pipe locks are being taken we wait for flip pending to clear first. In some cases the pipe mapping is changed and the pending we're checking for will never clear. [How] Don't check disabled pipes for flip pending. Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index cedf359a00f5c..db5615a51fea8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -734,6 +734,9 @@ bool hubp1_is_flip_pending(struct hubp *hubp) struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); struct dc_plane_address earliest_inuse_address; + if (hubp && hubp->power_gated) + return false; + REG_GET(DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, &flip_pending); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index bb920d0e0b892..368818d2dfc63 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -908,6 +908,9 @@ bool hubp2_is_flip_pending(struct hubp *hubp) struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); struct dc_plane_address earliest_inuse_address; + if (hubp && hubp->power_gated) + return false; + REG_GET(DCSURF_FLIP_CONTROL, SURFACE_FLIP_PENDING, &flip_pending); -- GitLab From 6c95320d01dcac321e9e89903a26a840838a0ef6 Mon Sep 17 00:00:00 2001 From: George Shen <george.shen@amd.com> Date: Tue, 18 Aug 2020 18:42:55 -0400 Subject: [PATCH 1177/1494] drm/amd/display: Rename set_mst_bandwidth to align with DP spec [Why] The function set_mst_bandwidth is poorly name since it isn't clear what it does, and it also does not reflect any part of the allocation sequence described in the DP spec. [How] Rename the function set_mst_bandwidth to set_throttled_vcp_size. Signed-off-by: George Shen <george.shen@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c | 6 +++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 6 +++--- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h | 2 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c | 4 ++-- .../drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 +- .../drm/amd/display/dc/virtual/virtual_stream_encoder.c | 9 +++++---- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 437d1a7a16fe7..1871ff6119ae0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2946,7 +2946,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) pbn = get_pbn_from_timing(pipe_ctx); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - stream_encoder->funcs->set_mst_bandwidth( + stream_encoder->funcs->set_throttled_vcp_size( stream_encoder, avg_time_slots_per_mtp); @@ -2974,7 +2974,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) */ /* slot X.Y */ - stream_encoder->funcs->set_mst_bandwidth( + stream_encoder->funcs->set_throttled_vcp_size( stream_encoder, avg_time_slots_per_mtp); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 4cdaaf4d881cc..5054bb567b748 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -710,7 +710,7 @@ static void dce110_stream_encoder_lvds_set_stream_attribute( ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); } -static void dce110_stream_encoder_set_mst_bandwidth( +static void dce110_stream_encoder_set_throttled_vcp_size( struct stream_encoder *enc, struct fixed31_32 avg_time_slots_per_mtp) { @@ -1621,8 +1621,8 @@ static const struct stream_encoder_funcs dce110_str_enc_funcs = { dce110_stream_encoder_dvi_set_stream_attribute, .lvds_set_stream_attribute = dce110_stream_encoder_lvds_set_stream_attribute, - .set_mst_bandwidth = - dce110_stream_encoder_set_mst_bandwidth, + .set_throttled_vcp_size = + dce110_stream_encoder_set_throttled_vcp_size, .update_hdmi_info_packets = dce110_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 842abb4c475bc..9cf139be3f40e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -619,7 +619,7 @@ void enc1_stream_encoder_dvi_set_stream_attribute( enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); } -void enc1_stream_encoder_set_mst_bandwidth( +void enc1_stream_encoder_set_throttled_vcp_size( struct stream_encoder *enc, struct fixed31_32 avg_time_slots_per_mtp) { @@ -1616,8 +1616,8 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { enc1_stream_encoder_hdmi_set_stream_attribute, .dvi_set_stream_attribute = enc1_stream_encoder_dvi_set_stream_attribute, - .set_mst_bandwidth = - enc1_stream_encoder_set_mst_bandwidth, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, .update_hdmi_info_packets = enc1_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index 30eae7459d509..b99d2527cf036 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -588,7 +588,7 @@ void enc1_stream_encoder_dvi_set_stream_attribute( struct dc_crtc_timing *crtc_timing, bool is_dual_link); -void enc1_stream_encoder_set_mst_bandwidth( +void enc1_stream_encoder_set_throttled_vcp_size( struct stream_encoder *enc, struct fixed31_32 avg_time_slots_per_mtp); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index e3984f02b7b3e..4075ae1115304 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -561,8 +561,8 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { enc1_stream_encoder_hdmi_set_stream_attribute, .dvi_set_stream_attribute = enc1_stream_encoder_dvi_set_stream_attribute, - .set_mst_bandwidth = - enc1_stream_encoder_set_mst_bandwidth, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, .update_hdmi_info_packets = enc2_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index f5e80a0db72b7..6c0f7ef0a3dfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -790,8 +790,8 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { enc3_stream_encoder_hdmi_set_stream_attribute, .dvi_set_stream_attribute = enc3_stream_encoder_dvi_set_stream_attribute, - .set_mst_bandwidth = - enc1_stream_encoder_set_mst_bandwidth, + .set_throttled_vcp_size = + enc1_stream_encoder_set_throttled_vcp_size, .update_hdmi_info_packets = enc3_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 11ce06e69d3ff..0184cefb083bf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -143,7 +143,7 @@ struct stream_encoder_funcs { struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing); - void (*set_mst_bandwidth)( + void (*set_throttled_vcp_size)( struct stream_encoder *enc, struct fixed31_32 avg_time_slots_per_mtp); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 944c0327763c1..f0a0d419e555c 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -46,9 +46,10 @@ static void virtual_stream_encoder_dvi_set_stream_attribute( struct dc_crtc_timing *crtc_timing, bool is_dual_link) {} -static void virtual_stream_encoder_set_mst_bandwidth( +static void virtual_stream_encoder_set_throttled_vcp_size( struct stream_encoder *enc, - struct fixed31_32 avg_time_slots_per_mtp) {} + struct fixed31_32 avg_time_slots_per_mtp) +{} static void virtual_stream_encoder_update_hdmi_info_packets( struct stream_encoder *enc, @@ -107,8 +108,8 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { virtual_stream_encoder_hdmi_set_stream_attribute, .dvi_set_stream_attribute = virtual_stream_encoder_dvi_set_stream_attribute, - .set_mst_bandwidth = - virtual_stream_encoder_set_mst_bandwidth, + .set_throttled_vcp_size = + virtual_stream_encoder_set_throttled_vcp_size, .update_hdmi_info_packets = virtual_stream_encoder_update_hdmi_info_packets, .stop_hdmi_info_packets = -- GitLab From f9663cbd46815c214b1841f4eef5c5e9e6350ff9 Mon Sep 17 00:00:00 2001 From: Roman Li <roman.li@amd.com> Date: Thu, 27 Aug 2020 17:54:57 -0400 Subject: [PATCH 1178/1494] drm/amd/display: remove early return from dm_late_init [Why] ABM feature initialization was not executed due to early return. dm_late_init() had an early return in case if DMCU is not used. With the implementation of ABM on DMUB, DMCU can be disabled but ABM still needs to be initialized. [How] Remove verification for DMCU from the top of the function. The existing logic will handle the case when DMCU is not used. Signed-off-by: Roman Li <roman.li@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 643eb8e337aab..1fdc92a2c0c0b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1427,9 +1427,6 @@ static int dm_late_init(void *handle) struct dmcu *dmcu = NULL; bool ret = true; - if (!adev->dm.fw_dmcu && !adev->dm.dmub_fw) - return detect_mst_link_for_all_connectors(adev_to_drm(adev)); - dmcu = adev->dm.dc->res_pool->dmcu; for (i = 0; i < 16; i++) -- GitLab From 5fd35f1291316a3a9dc2fb7f976446d20b65106a Mon Sep 17 00:00:00 2001 From: Zhan Liu <zhan.liu@amd.com> Date: Sun, 23 Aug 2020 20:48:44 -0400 Subject: [PATCH 1179/1494] drm/amd/display: Enabling PSR on DCN30 on driver side [Why] PSR needs to be enabled on DCN30. This is the driver part of PSR enablement. Also disabled retired DMCU on driver side, since DMCU is not supported on DCN30 anymore. [How] Add necessary changes to enable PSR on DCN30. Signed-off-by: Zhan Liu <zhan.liu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 6746d582d723c..88f23f12aeb85 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -79,6 +79,7 @@ #include "reg_helper.h" #include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" #include "dce/dce_aux.h" #include "dce/dce_i2c.h" @@ -832,7 +833,7 @@ static const struct dc_plane_cap plane_cap = { }; static const struct dc_debug_options debug_defaults_drv = { - .disable_dmcu = true, + .disable_dmcu = true, //No DMCU on DCN30 .force_abm_enable = false, .timing_trace = false, .clock_trace = true, @@ -849,10 +850,11 @@ static const struct dc_debug_options debug_defaults_drv = { .underflow_assert_delay_us = 0xFFFFFFFF, .dwb_fi_phase = -1, // -1 = disable, .dmub_command_table = true, + .disable_psr = false, }; static const struct dc_debug_options debug_defaults_diags = { - .disable_dmcu = true, + .disable_dmcu = true, //No dmcu on DCN30 .force_abm_enable = false, .timing_trace = true, .clock_trace = true, @@ -865,6 +867,7 @@ static const struct dc_debug_options debug_defaults_diags = { .scl_reset_length10 = true, .dwb_fi_phase = -1, // -1 = disable .dmub_command_table = true, + .disable_psr = true, .enable_tri_buf = true, }; @@ -1313,6 +1316,9 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) dce_abm_destroy(&pool->base.multiple_abms[i]); } + if (pool->base.psr != NULL) + dmub_psr_destroy(&pool->base.psr); + if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); } @@ -2624,6 +2630,14 @@ static bool dcn30_resource_construct( } } pool->base.timing_generator_count = i; + /* PSR */ + pool->base.psr = dmub_psr_create(ctx); + + if (pool->base.psr == NULL) { + dm_error("DC: failed to create PSR obj!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } /* ABM */ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) { -- GitLab From 6cd792372489a56686c7b38e80ddad62cb3d0fec Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Fri, 28 Aug 2020 10:09:05 -0400 Subject: [PATCH 1180/1494] drm/amd/display: Compare plane when looking for pipe split being lost [Why] There are situations where we go from 2 pipe to 1 pipe in MPO, but this isn't a pipe split being lost -- it's a plane disappearing in (i.e. video overlay goes away) so we lose one pipe. In these situations we don't want to disable the pipe in a separate operation from the rest of the pipe programming sequence. We only want to disable a pipe in a separate operation when we're actually disabling pipe split. [How] Make sure the pipe being lost has the same stream AND plane as the old top pipe to ensure. Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 8ca94f5061957..d0f3bf953d027 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2765,7 +2765,7 @@ bool dcn10_disconnect_pipes( struct dc *dc, struct dc_state *context) { - bool found_stream = false; + bool found_pipe = false; int i, j; struct dce_hwseq *hws = dc->hwseq; struct dc_state *old_ctx = dc->current_state; @@ -2805,26 +2805,28 @@ bool dcn10_disconnect_pipes( old_ctx->res_ctx.pipe_ctx[i].top_pipe) { /* Find the top pipe in the new ctx for the bottom pipe that we - * want to remove by comparing the streams. If both pipes are being - * disabled then do it in the regular pipe programming sequence + * want to remove by comparing the streams and planes. If both + * pipes are being disabled then do it in the regular pipe + * programming sequence */ for (j = 0; j < dc->res_pool->pipe_count; j++) { if (old_ctx->res_ctx.pipe_ctx[i].top_pipe->stream == context->res_ctx.pipe_ctx[j].stream && + old_ctx->res_ctx.pipe_ctx[i].top_pipe->plane_state == context->res_ctx.pipe_ctx[j].plane_state && !context->res_ctx.pipe_ctx[j].top_pipe && !context->res_ctx.pipe_ctx[j].update_flags.bits.disable) { - found_stream = true; + found_pipe = true; break; } } // Disconnect if the top pipe lost it's pipe split - if (found_stream && !context->res_ctx.pipe_ctx[j].bottom_pipe) { + if (found_pipe && !context->res_ctx.pipe_ctx[j].bottom_pipe) { hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); mpcc_disconnected = true; } } - found_stream = false; + found_pipe = false; } } -- GitLab From bd80d584cd8e2502b6be48544a14970016c86aa4 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Fri, 28 Aug 2020 11:09:38 -0400 Subject: [PATCH 1181/1494] drm/amd/display: Don't use DRM_ERROR() for DTM add topology [Why] Previously we were only calling add_topology when hdcp was being enabled. Now we call add_topology by default so the ERROR messages are printed if the firmware is not loaded. This error message is not relevant for normal display functionality so no need to print a ERROR message. [How] Change DRM_ERROR to DRM_INFO Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index fb1161dd7ea80..3a367a5968ae1 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -88,7 +88,7 @@ enum mod_hdcp_status mod_hdcp_add_display_to_topology(struct mod_hdcp *hdcp, enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; if (!psp->dtm_context.dtm_initialized) { - DRM_ERROR("Failed to add display topology, DTM TA is not initialized."); + DRM_INFO("Failed to add display topology, DTM TA is not initialized."); display->state = MOD_HDCP_DISPLAY_INACTIVE; return MOD_HDCP_STATUS_FAILURE; } -- GitLab From 48e48e5984782171ac8d2ec09b7e688e141d7c86 Mon Sep 17 00:00:00 2001 From: Zhan Liu <zhan.liu@amd.com> Date: Fri, 28 Aug 2020 14:18:56 -0400 Subject: [PATCH 1182/1494] drm/amd/display: Disable idle optimization when PSR is enabled [Why] Idle optimization and PSR conflict each other. If both enabled at the same time, display flickering will be observed. [How] Disable idle optimization when PSR is enabled. Signed-off-by: Zhan Liu <zhan.liu@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn30/dcn30_hwseq.c | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 1390ff1ce7bef..7886c32d8315f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -690,26 +690,23 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx) bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) { - unsigned int surface_size; - if (!dc->ctx->dmub_srv) return false; if (enable) { - if (dc->current_state - && dc->current_state->stream_count == 1 // single display only - && dc->current_state->stream_status[0].plane_count == 1 // single surface only - && dc->current_state->stream_status[0].plane_states[0]->address.page_table_base.quad_part == 0 // no VM - // Only 8 and 16 bit formats - && dc->current_state->stream_status[0].plane_states[0]->format <= SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F - && dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888) { - - surface_size = dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_pitch * - dc->current_state->stream_status[0].plane_states[0]->plane_size.surface_size.height * - (dc->current_state->stream_status[0].plane_states[0]->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); - + if (dc->current_state) { + int i; + + /* First, check no-memory-requests case */ + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->stream_status[i] + .plane_count) + /* Fail eligibility on a visible stream */ + break; + } } + /* No applicable optimizations */ return false; } -- GitLab From e4863f118a7d58e080c16dc0cd354736691c2f66 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Sun, 23 Aug 2020 22:32:14 -0400 Subject: [PATCH 1183/1494] drm/amd/display: Multi display cause system lag on mode change [Why] DCValidator is created/destroyed repeatedly for cofunctional validation which causes a lot of memory thrashing, particularly when Driver Verifer is enabled. [How] Implement a basic caching algorithm that will cache DCValidator with a matching topology. When a match is found, the DCValidator can be reused. If there is no match, a new one will be created and inserted into the cache if there is space or an unreference entry can be evicted. Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 511ab25b3f1aa..ce5303c76b118 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1481,13 +1481,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) return true; } -struct dc_state *dc_create_state(struct dc *dc) +static void init_state(struct dc *dc, struct dc_state *context) { - struct dc_state *context = kvzalloc(sizeof(struct dc_state), - GFP_KERNEL); - - if (!context) - return NULL; /* Each context must have their own instance of VBA and in order to * initialize and obtain IP and SOC the base DML instance from DC is * initially copied into every context @@ -1495,6 +1490,17 @@ struct dc_state *dc_create_state(struct dc *dc) #ifdef CONFIG_DRM_AMD_DC_DCN memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib)); #endif +} + +struct dc_state *dc_create_state(struct dc *dc) +{ + struct dc_state *context = kzalloc(sizeof(struct dc_state), + GFP_KERNEL); + + if (!context) + return NULL; + + init_state(dc, context); kref_init(&context->refcount); -- GitLab From 20cc44c9e82a9131c64d0a95d32b18e28d9728f4 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Thu, 27 Aug 2020 15:21:03 -0400 Subject: [PATCH 1184/1494] drm/amd/display: make dcn20 stream_gating use a pointer for dsc_pg_control This allows us to reuse these on different asics. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index ee56060943f1c..5720b6e5d321b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1918,9 +1918,9 @@ void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream_res.dsc) { struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; - dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true); + hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true); while (odm_pipe) { - dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true); + hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true); odm_pipe = odm_pipe->next_odm_pipe; } } @@ -1933,9 +1933,9 @@ void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream_res.dsc) { struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; - dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false); + hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false); while (odm_pipe) { - dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false); + hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false); odm_pipe = odm_pipe->next_odm_pipe; } } -- GitLab From 0749ddeb7d6c87e04446c068c03b097d4aa19173 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Fri, 14 Aug 2020 14:50:19 -0400 Subject: [PATCH 1185/1494] drm/amd/display: Add DSC force disable to dsc_clock_en debugfs entry [why] For debug purposes we want not to enable DSC on certain connectors even if algorithm deesires to do so, instead it should enable DSC on other capable connectors or fail the atomic check. [how] Adding the third option to connector's debugfs entry dsc_clock_en. Accepted inputs: 0x0 - connector is using default DSC enablement policy 0x1 - force enable DSC on the connector, if it supports DSC 0x2 - force disable DSC on the connector, if DSC is supported Ex. # echo 0x2 > /sys/kernel/debug/dri/0/DP-1/dsc_clock_en Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 10 ++++++++-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 15 ++++++++++++--- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 10 +++++----- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1fdc92a2c0c0b..4684820e4dc8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4685,9 +4685,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, dc_link_get_link_cap(aconnector->dc_link)); #if defined(CONFIG_DRM_AMD_DC_DCN) - if (dsc_caps.is_dsc_supported) { + if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported) { /* Set DSC policy according to dsc_clock_en */ - dc_dsc_policy_set_enable_dsc_when_not_needed(aconnector->dsc_settings.dsc_clock_en); + dc_dsc_policy_set_enable_dsc_when_not_needed( + aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE); if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], &dsc_caps, @@ -4697,7 +4698,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, &stream->timing.dsc_cfg)) stream->timing.flags.DSC = 1; /* Overwrite the stream flag if DSC is enabled through debugfs */ - if (aconnector->dsc_settings.dsc_clock_en) + if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE) stream->timing.flags.DSC = 1; if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 71a81cabd6eb0..ec8bd5fc8776c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -340,11 +340,17 @@ struct amdgpu_display_manager { * fake encoders used for DP MST. */ struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; - bool force_timing_sync; + bool force_timing_sync; +}; + +enum dsc_clock_force_state { + DSC_CLK_FORCE_DEFAULT = 0, + DSC_CLK_FORCE_ENABLE, + DSC_CLK_FORCE_DISABLE, }; struct dsc_preferred_settings { - bool dsc_clock_en; + enum dsc_clock_force_state dsc_force_enable; uint32_t dsc_slice_width; uint32_t dsc_slice_height; uint32_t dsc_bits_per_pixel; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 94fcb086154c9..5cf3ba3ec5dab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -111,7 +111,6 @@ static int parse_write_buffer_into_params(char *wr_buf, uint32_t wr_buf_size, if (*param_nums > max_param_num) *param_nums = max_param_num; -; wr_buf_ptr = wr_buf; /* reset buf pointer */ wr_buf_count = 0; /* number of char already checked */ @@ -1200,9 +1199,14 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, * * The write function: dp_dsc_clock_en_write * enables to force DSC on the connector. - * User can write to either force enable DSC + * User can write to either force enable or force disable DSC * on the next modeset or set it to driver default * + * Accepted inputs: + * 0 - default DSC enablement policy + * 1 - force enable DSC on the connector + * 2 - force disable DSC on the connector (might cause fail in atomic_check) + * * Writing DSC settings is done with the following command: * - To force enable DSC (you need to specify * connector like DP-1): @@ -1262,7 +1266,12 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, if (!pipe_ctx || !pipe_ctx->stream) goto done; - aconnector->dsc_settings.dsc_clock_en = param[0]; + if (param[0] == 1) + aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_ENABLE; + else if (param[0] == 2) + aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DISABLE; + else + aconnector->dsc_settings.dsc_force_enable = DSC_CLK_FORCE_DEFAULT; done: kfree(wr_buf); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index adbb44822e944..14c04c1ac9bb3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -453,7 +453,7 @@ struct dsc_mst_fairness_params { struct dc_dsc_bw_range bw_range; bool compression_possible; struct drm_dp_mst_port *port; - bool clock_overwrite; + enum dsc_clock_force_state clock_force_enable; uint32_t slice_width_overwrite; uint32_t slice_height_overwrite; uint32_t bpp_overwrite; @@ -638,7 +638,7 @@ static void try_disable_dsc(struct drm_atomic_state *state, for (i = 0; i < count; i++) { if (vars[i].dsc_enabled && vars[i].bpp_x16 == params[i].bw_range.max_target_bpp_x16 - && !params[i].clock_overwrite) { + && !params[i].clock_force_enable == DSC_CLK_FORCE_DEFAULT) { kbps_increase[i] = params[i].bw_range.stream_kbps - params[i].bw_range.max_kbps; tried[i] = false; remaining_to_try += 1; @@ -718,8 +718,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].sink = stream->sink; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; params[count].port = aconnector->port; - params[count].clock_overwrite = aconnector->dsc_settings.dsc_clock_en; - if (params[count].clock_overwrite) + params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; + if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) debugfs_overwrite = true; params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; @@ -756,7 +756,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, /* Try max compression */ for (i = 0; i < count; i++) { - if (params[i].compression_possible) { + if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); vars[i].dsc_enabled = true; vars[i].bpp_x16 = params[i].bw_range.min_target_bpp_x16; -- GitLab From 6b29bb37373bfdcc851b2c907f6a9049427b1661 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Thu, 27 Aug 2020 15:45:06 -0400 Subject: [PATCH 1186/1494] drm/amd/display: Add trigger connector unplug [why] We need a virtual tool that would emulate a physical connector unplug to usermode, while connector is still physically plugged in. [how] Added a new option to debugfs entry "trigger_hotplug". It emulates hotplug irq handling scenario by clearing DC and DM connector states. It can be triggered with the following command: echo 0 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 5cf3ba3ec5dab..7c7f937166dc5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1058,12 +1058,17 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data) * * echo 1 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug * + * This function can perform HPD unplug: + * + * echo 0 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug + * */ static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, size_t size, loff_t *pos) { struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; struct drm_connector *connector = &aconnector->base; + struct dc_link *link = NULL; struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; char *wr_buf = NULL; @@ -1114,11 +1119,33 @@ static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, drm_modeset_unlock_all(dev); drm_kms_helper_hotplug_event(dev); + } else if (param[0] == 0) { + if (!aconnector->dc_link) + goto unlock; -unlock: - mutex_unlock(&aconnector->hpd_lock); + link = aconnector->dc_link; + + if (link->local_sink) { + dc_sink_release(link->local_sink); + link->local_sink = NULL; + } + + link->dpcd_sink_count = 0; + link->type = dc_connection_none; + link->dongle_max_pix_clk = 0; + + amdgpu_dm_update_connector_after_detect(aconnector); + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + drm_kms_helper_hotplug_event(dev); } +unlock: + mutex_unlock(&aconnector->hpd_lock); + kfree(wr_buf); return size; } -- GitLab From 6b85151f6bcdb796dfdb4d2e07dbeb4340b6b173 Mon Sep 17 00:00:00 2001 From: Martin Leung <martin.leung@amd.com> Date: Fri, 28 Aug 2020 10:48:41 -0400 Subject: [PATCH 1187/1494] drm/amd/display: adding pathway to retrieve stutter period why: some functions may need be dependent on stutter period in the future how: Extract from stutter calculations and place into perf_params structure Signed-off-by: Martin Leung <martin.leung@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 3 +++ .../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 12 +++++++++--- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 88f23f12aeb85..168e6e4efaf49 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2210,6 +2210,9 @@ static void dcn30_calculate_wm( context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->perf_params.stutter_period_us = + context->bw_ctx.dml.vba.StutterPeriod; + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 2beb284f89b0a..8f8bf83a60a17 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -597,7 +597,8 @@ static void CalculateStutterEfficiency( double meta_row_bw[], double dpte_row_bw[], double *StutterEfficiencyNotIncludingVBlank, - double *StutterEfficiency); + double *StutterEfficiency, + double *StutterPeriodOut); static void CalculateSwathAndDETConfiguration( bool ForceSingleDPP, @@ -3134,7 +3135,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->meta_row_bw, v->dpte_row_bw, &v->StutterEfficiencyNotIncludingVBlank, - &v->StutterEfficiency); + &v->StutterEfficiency, + &v->StutterPeriod); } static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) @@ -6151,7 +6153,8 @@ static void CalculateStutterEfficiency( double meta_row_bw[], double dpte_row_bw[], double *StutterEfficiencyNotIncludingVBlank, - double *StutterEfficiency) + double *StutterEfficiency, + double *StutterPeriodOut) { double FullDETBufferingTimeY[DC__NUM_DPP__MAX] = { 0 }; double FrameTimeForMinFullDETBufferingTime = 0; @@ -6262,6 +6265,9 @@ static void CalculateStutterEfficiency( } *StutterEfficiency = (*StutterEfficiencyNotIncludingVBlank / 100.0 * (FrameTimeForMinFullDETBufferingTime - SmallestVBlank) + SmallestVBlank) / FrameTimeForMinFullDETBufferingTime * 100; + + if (StutterPeriodOut) + *StutterPeriodOut = StutterPeriod; } static void CalculateSwathAndDETConfiguration( diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index cc5f053ef5a33..3ec1d9dd16700 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -411,6 +411,10 @@ struct dc_state { struct clk_mgr *clk_mgr; struct kref refcount; + + struct { + unsigned int stutter_period_us; + } perf_params; }; #endif /* _CORE_TYPES_H_ */ -- GitLab From 8b3f6b9857dd07f6023694f33b346a6b35939aa5 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Mon, 31 Aug 2020 09:39:52 -0400 Subject: [PATCH 1188/1494] drm/amd/display: [FW Promotion] Release 0.0.32 | [Header Changes] | - Add debug flag to log line numbers for PSR debug Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 3f84060d79c02..a0bd502dc7d7e 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x08aa15e57 +#define DMUB_FW_VERSION_GIT_HASH 0x82f998da6 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 31 +#define DMUB_FW_VERSION_REVISION 32 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -97,6 +97,7 @@ union dmub_psr_debug_flags { struct { uint32_t visual_confirm : 1; uint32_t use_hw_lock_mgr : 1; + uint32_t log_line_nums : 1; } bitfields; uint32_t u32All; -- GitLab From a4832640e29a118256bad7ed50bccde600e4f052 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 31 Aug 2020 11:09:18 -0400 Subject: [PATCH 1189/1494] drm/amd/display: 3.2.102 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 464f2c657597d..8631d290afee8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.101" +#define DC_VER "3.2.102" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 0825d9658b5e6b9ec6220ac5d2500f683c9601e7 Mon Sep 17 00:00:00 2001 From: Eric Yang <Eric.Yang2@amd.com> Date: Fri, 21 Aug 2020 17:15:36 -0400 Subject: [PATCH 1190/1494] drm/amd/display: implement notify stream mask [Why] Send stream active state info to DMUB [How] Implement GPINT to notify stream mask Signed-off-by: Eric Yang <Eric.Yang2@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 ++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 2 ++ .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + 4 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ce5303c76b118..1190c58275c3a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1246,6 +1246,19 @@ void dc_trigger_sync(struct dc *dc, struct dc_state *context) } } +static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context) +{ + int i; + unsigned int stream_mask = 0; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].stream) + stream_mask |= 1 << i; + } + + return stream_mask; +} + /* * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. @@ -1362,6 +1375,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->hwss.optimize_bandwidth(dc, context); } + context->stream_mask = get_stream_mask(dc, context); + + if (context->stream_mask != dc->current_state->stream_mask) + dc_dmub_srv_notify_stream_mask(dc->ctx->dmub_srv, context->stream_mask); + for (i = 0; i < context->stream_count; i++) context->streams[i]->mode_changed = false; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index eea2429ac67d8..b987548119772 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -132,3 +132,19 @@ void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv) /* Continue spinning so we don't hang the ASIC. */ } } + +bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, + unsigned int stream_mask) +{ + struct dmub_srv *dmub; + const uint32_t timeout = 30; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return false; + + dmub = dc_dmub_srv->dmub; + + return dmub_srv_send_gpint_command( + dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, + stream_mask, timeout) == DMUB_STATUS_OK; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index a3a09ccb6d266..bb4ab61887e4c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -56,4 +56,6 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv); void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv); +bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, + unsigned int stream_mask); #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 3ec1d9dd16700..1daa563c8ff44 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -397,6 +397,7 @@ struct dc_state { struct dc_stream_state *streams[MAX_PIPES]; struct dc_stream_status stream_status[MAX_PIPES]; uint8_t stream_count; + uint8_t stream_mask; struct resource_context res_ctx; -- GitLab From 4b675aad9695070c728c386b8f15ff8f27cd3e34 Mon Sep 17 00:00:00 2001 From: Joshua Aberback <joshua.aberback@amd.com> Date: Mon, 31 Aug 2020 01:58:03 -0400 Subject: [PATCH 1191/1494] drm/amd/display: Update idle optimization handling [How] - use dc interface instead of hwss interface in cursor functions, to keep dc->idle_optimizations_allowed updated - add dc interface to check if idle optimizations might apply to a plane Signed-off-by: Joshua Aberback <joshua.aberback@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++++ drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 11 +++++------ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1190c58275c3a..7ab82d6a5630c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3039,4 +3039,10 @@ void dc_lock_memory_clock_frequency(struct dc *dc) if (dc->current_state->res_ctx.pipe_ctx[i].plane_state) core_link_enable_stream(dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); } + +bool dc_is_plane_eligible_for_idle_optimizaitons(struct dc *dc, + struct dc_plane_state *plane) +{ + return false; +} #endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index f42a17d765e37..6fef9078f3d17 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -298,7 +298,7 @@ bool dc_stream_set_cursor_attributes( #if defined(CONFIG_DRM_AMD_DC_DCN3_0) /* disable idle optimizations while updating cursor */ if (dc->idle_optimizations_allowed) { - dc->hwss.apply_idle_power_optimizations(dc, false); + dc_allow_idle_optimizations(dc, false); reset_idle_optimizations = true; } @@ -326,7 +326,7 @@ bool dc_stream_set_cursor_attributes( #if defined(CONFIG_DRM_AMD_DC_DCN3_0) /* re-enable idle optimizations if necessary */ if (reset_idle_optimizations) - dc->hwss.apply_idle_power_optimizations(dc, true); + dc_allow_idle_optimizations(dc, true); #endif return true; @@ -359,9 +359,8 @@ bool dc_stream_set_cursor_position( #if defined(CONFIG_DRM_AMD_DC_DCN3_0) /* disable idle optimizations if enabling cursor */ - if (dc->idle_optimizations_allowed && - !stream->cursor_position.enable && position->enable) { - dc->hwss.apply_idle_power_optimizations(dc, false); + if (dc->idle_optimizations_allowed && !stream->cursor_position.enable && position->enable) { + dc_allow_idle_optimizations(dc, false); reset_idle_optimizations = true; } @@ -392,7 +391,7 @@ bool dc_stream_set_cursor_position( #if defined(CONFIG_DRM_AMD_DC_DCN3_0) /* re-enable idle optimizations if necessary */ if (reset_idle_optimizations) - dc->hwss.apply_idle_power_optimizations(dc, true); + dc_allow_idle_optimizations(dc, true); #endif return true; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8631d290afee8..9d7d5dd9e8208 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1250,6 +1250,9 @@ enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32 void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg); #if defined(CONFIG_DRM_AMD_DC_DCN3_0) +bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, + struct dc_plane_state *plane); + void dc_allow_idle_optimizations(struct dc *dc, bool allow); /* -- GitLab From 918698d5c2b50433714d2042f55b55b090faa167 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Thu, 27 Aug 2020 16:48:38 -0400 Subject: [PATCH 1192/1494] drm/amd/display: Return the number of bytes parsed than allocated [why & how] Previously we were returning the number of bytes allocated for a write buffer from debugfs and when manually used it wouldn't rise any errors, but it wouldn't match the size of the parameters passed from userspace. In successful case return the size passed by usermode otherwise the error code is returned. That simplifies the parser helper and removes a potential error of returning mismatched input size. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 7c7f937166dc5..240a4fc403df8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -264,7 +264,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, if (!wr_buf) return -ENOSPC; - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -423,7 +423,7 @@ static ssize_t dp_phy_settings_write(struct file *f, const char __user *buf, if (!wr_buf) return -ENOSPC; - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -575,7 +575,7 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us if (!wr_buf) return -ENOSPC; - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -1090,7 +1090,7 @@ static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, return -ENOSPC; } - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) @@ -1269,7 +1269,7 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, return -ENOSPC; } - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -1423,7 +1423,7 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, return -ENOSPC; } - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -1572,7 +1572,7 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, return -ENOSPC; } - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { @@ -1714,7 +1714,7 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu return -ENOSPC; } - if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, ¶m_nums)) { -- GitLab From 28b2f656d3ae27e85a3ac312876d1f3114a2463d Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Thu, 27 Aug 2020 16:57:14 -0400 Subject: [PATCH 1193/1494] drm/amd/display: Calculate DSC number of slices in debugfs when forced [why] When comparing current DSC timing settings with enforced through debugfs we have to calculate number of both vertical and horisontal slices. So instead of doing that every time we should just use number of slices rather than setting its dimensions. [how] In connector's dsc preferred settings structure change slice height and slice width parameters to number of slices vertical and horisontal. Also calculate number of slices in debugfs rather in create_stream_for_sink. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 ++-- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 14 +++++++++++-- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 20 ++++++++----------- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4684820e4dc8d..13ac3bf8ee9d2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4701,13 +4701,11 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE) stream->timing.flags.DSC = 1; - if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) - stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable, - aconnector->dsc_settings.dsc_slice_width); + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_h) + stream->timing.dsc_cfg.num_slices_h = aconnector->dsc_settings.dsc_num_slices_h; - if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height) - stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable, - aconnector->dsc_settings.dsc_slice_height); + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_num_slices_v) + stream->timing.dsc_cfg.num_slices_v = aconnector->dsc_settings.dsc_num_slices_v; if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index ec8bd5fc8776c..9c1e003d9c295 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -351,8 +351,8 @@ enum dsc_clock_force_state { struct dsc_preferred_settings { enum dsc_clock_force_state dsc_force_enable; - uint32_t dsc_slice_width; - uint32_t dsc_slice_height; + uint32_t dsc_num_slices_v; + uint32_t dsc_num_slices_h; uint32_t dsc_bits_per_pixel; }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 240a4fc403df8..9be2f291382df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1447,7 +1447,12 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, if (!pipe_ctx || !pipe_ctx->stream) goto done; - aconnector->dsc_settings.dsc_slice_width = param[0]; + if (param[0] > 0) + aconnector->dsc_settings.dsc_num_slices_h = DIV_ROUND_UP( + pipe_ctx->stream->timing.h_addressable, + param[0]); + else + aconnector->dsc_settings.dsc_num_slices_h = 0; done: kfree(wr_buf); @@ -1596,7 +1601,12 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, if (!pipe_ctx || !pipe_ctx->stream) goto done; - aconnector->dsc_settings.dsc_slice_height = param[0]; + if (param[0] > 0) + aconnector->dsc_settings.dsc_num_slices_v = DIV_ROUND_UP( + pipe_ctx->stream->timing.v_addressable, + param[0]); + else + aconnector->dsc_settings.dsc_num_slices_v = 0; done: kfree(wr_buf); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 14c04c1ac9bb3..9d7333a36facf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -454,8 +454,8 @@ struct dsc_mst_fairness_params { bool compression_possible; struct drm_dp_mst_port *port; enum dsc_clock_force_state clock_force_enable; - uint32_t slice_width_overwrite; - uint32_t slice_height_overwrite; + uint32_t num_slices_h; + uint32_t num_slices_v; uint32_t bpp_overwrite; }; @@ -496,15 +496,11 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p else params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; - if (params[i].slice_width_overwrite) - params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( - params[i].timing->h_addressable, - params[i].slice_width_overwrite); + if (params[i].num_slices_h) + params[i].timing->dsc_cfg.num_slices_h = params[i].num_slices_h; - if (params[i].slice_height_overwrite) - params[i].timing->dsc_cfg.num_slices_v = DIV_ROUND_UP( - params[i].timing->v_addressable, - params[i].slice_height_overwrite); + if (params[i].num_slices_v) + params[i].timing->dsc_cfg.num_slices_v = params[i].num_slices_v; } else { params[i].timing->flags.DSC = 0; } @@ -721,8 +717,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) debugfs_overwrite = true; - params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; - params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; + params[count].num_slices_h = aconnector->dsc_settings.dsc_num_slices_h; + params[count].num_slices_v = aconnector->dsc_settings.dsc_num_slices_v; params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); -- GitLab From c44a22b3128d143a66421004b728eed688c21ee6 Mon Sep 17 00:00:00 2001 From: Eryk Brol <eryk.brol@amd.com> Date: Thu, 27 Aug 2020 17:13:57 -0400 Subject: [PATCH 1194/1494] drm/amd/display: Add connector to the state if DSC debugfs is set [why] We want to trigger atomic check on connector, which DSC debugfs properties have changed. [how] Add a helper function that iterates through all active connectors and add them to the state if DSC debugfs parameters have changed. Signed-off-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Mikita Lipski <mikita.lipski@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 13ac3bf8ee9d2..8c13572d5c163 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -880,6 +880,45 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) return 0; } +static void amdgpu_check_debugfs_connector_property_change(struct amdgpu_device *adev, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_crtc *crtc; + struct amdgpu_dm_connector *amdgpu_dm_connector; + struct drm_connector_state *conn_state; + struct dm_crtc_state *acrtc_state; + struct drm_crtc_state *crtc_state; + struct dc_stream_state *stream; + struct drm_device *dev = adev_to_drm(adev); + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + amdgpu_dm_connector = to_amdgpu_dm_connector(connector); + conn_state = connector->state; + + if (!(conn_state && conn_state->crtc)) + continue; + + crtc = conn_state->crtc; + acrtc_state = to_dm_crtc_state(crtc->state); + + if (!(acrtc_state && acrtc_state->stream)) + continue; + + stream = acrtc_state->stream; + + if (amdgpu_dm_connector->dsc_settings.dsc_force_enable || + amdgpu_dm_connector->dsc_settings.dsc_num_slices_v || + amdgpu_dm_connector->dsc_settings.dsc_num_slices_h || + amdgpu_dm_connector->dsc_settings.dsc_bits_per_pixel) { + conn_state = drm_atomic_get_connector_state(state, connector); + crtc_state = drm_atomic_get_crtc_state(state, crtc); + crtc_state->mode_changed = true; + } + } +} + static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; @@ -8552,6 +8591,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, int ret, i; bool lock_and_validation_needed = false; + amdgpu_check_debugfs_connector_property_change(adev, state); + ret = drm_atomic_helper_check_modeset(dev, state); if (ret) goto fail; -- GitLab From ece11e7b4a9ca8f967d11db1afd3b2ac8c945ecb Mon Sep 17 00:00:00 2001 From: Josip Pavic <Josip.Pavic@amd.com> Date: Tue, 1 Sep 2020 17:25:38 -0400 Subject: [PATCH 1195/1494] drm/amd/display: remove dc context from transfer function [Why] The ctx field of dc_transfer_func is not always populated and therefore isn't reliable. [How] Remove dc context from dc_transfer_func Signed-off-by: Josip Pavic <Josip.Pavic@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 - drivers/gpu/drm/amd/display/dc/core/dc_surface.c | 7 +------ drivers/gpu/drm/amd/display/dc/dc.h | 2 -- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c | 4 ---- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c | 4 ---- 5 files changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 6fef9078f3d17..d48fd87d3b953 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -123,7 +123,6 @@ static bool dc_stream_construct(struct dc_stream_state *stream, return false; } stream->out_transfer_func->type = TF_TYPE_BYPASS; - stream->out_transfer_func->ctx = stream->ctx; stream->stream_id = stream->ctx->dc_stream_id_count; stream->ctx->dc_stream_id_count++; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index ea1229a3e2b2c..3d7d27435f15e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -48,22 +48,17 @@ static void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *pl plane_state->in_transfer_func = dc_create_transfer_func(); if (plane_state->in_transfer_func != NULL) { plane_state->in_transfer_func->type = TF_TYPE_BYPASS; - plane_state->in_transfer_func->ctx = ctx; } plane_state->in_shaper_func = dc_create_transfer_func(); if (plane_state->in_shaper_func != NULL) { plane_state->in_shaper_func->type = TF_TYPE_BYPASS; - plane_state->in_shaper_func->ctx = ctx; } plane_state->lut3d_func = dc_create_3dlut_func(); - if (plane_state->lut3d_func != NULL) { - plane_state->lut3d_func->ctx = ctx; - } + plane_state->blend_tf = dc_create_transfer_func(); if (plane_state->blend_tf != NULL) { plane_state->blend_tf->type = TF_TYPE_BYPASS; - plane_state->blend_tf->ctx = ctx; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9d7d5dd9e8208..d9b22d6a985a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -745,7 +745,6 @@ struct dc_transfer_func { enum dc_transfer_func_predefined tf; /* FP16 1.0 reference level in nits, default is 80 nits, only for PQ*/ uint32_t sdr_ref_white_level; - struct dc_context *ctx; union { struct pwl_params pwl; struct dc_transfer_func_distributed_points tf_pts; @@ -772,7 +771,6 @@ struct dc_3dlut { struct tetrahedral_params lut_3d; struct fixed31_32 hdr_multiplier; union dc_3dlut_state state; - struct dc_context *ctx; }; /* * This structure is filled in by dc_surface_get_status and contains diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index 47a39eb9400bb..7a00fe525dfba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -325,8 +325,6 @@ bool cm_helper_translate_curve_to_hw_format( if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; - PERF_TRACE_CTX(output_tf->ctx); - corner_points = lut_params->corner_points; rgb_resulted = lut_params->rgb_resulted; hw_points = 0; @@ -524,8 +522,6 @@ bool cm_helper_translate_curve_to_degamma_hw_format( if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; - PERF_TRACE_CTX(output_tf->ctx); - corner_points = lut_params->corner_points; rgb_resulted = lut_params->rgb_resulted; hw_points = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index a139a87a1a81c..41a1d0e9b7e20 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -122,8 +122,6 @@ bool cm3_helper_translate_curve_to_hw_format( if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; - PERF_TRACE_CTX(output_tf->ctx); - corner_points = lut_params->corner_points; rgb_resulted = lut_params->rgb_resulted; hw_points = 0; @@ -314,8 +312,6 @@ bool cm3_helper_translate_curve_to_degamma_hw_format( if (output_tf == NULL || lut_params == NULL || output_tf->type == TF_TYPE_BYPASS) return false; - PERF_TRACE_CTX(output_tf->ctx); - corner_points = lut_params->corner_points; rgb_resulted = lut_params->rgb_resulted; hw_points = 0; -- GitLab From de32a50be7ab2da22002678926242d69e90933cc Mon Sep 17 00:00:00 2001 From: Roman Li <roman.li@amd.com> Date: Mon, 31 Aug 2020 21:30:26 -0400 Subject: [PATCH 1196/1494] drm/amd/display: fix compile warning in dml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] gcc version 5.4.0 fails compilation with: ‘PixelPTEReqHeightPTEs’ may be used uninitialized in this function [-Werror=maybe-uninitialized] [How] Initialized variable explicitly with 0 Signed-off-by: Roman Li <roman.li@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index a576eed94d9b0..367c82b5ab4c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -1294,7 +1294,7 @@ static unsigned int CalculateVMAndRowBytes( unsigned int MacroTileHeight; unsigned int ExtraDPDEBytesFrame; unsigned int PDEAndMetaPTEBytesFrame; - unsigned int PixelPTEReqHeightPTEs; + unsigned int PixelPTEReqHeightPTEs = 0; if (DCCEnable == true) { *MetaRequestHeight = 8 * BlockHeight256Bytes; -- GitLab From a354b942b46326ff156d7f85e07ce2a632f04165 Mon Sep 17 00:00:00 2001 From: Jun Lei <jun.lei@amd.com> Date: Thu, 3 Sep 2020 16:17:46 -0400 Subject: [PATCH 1197/1494] drm/amd/display: update nv1x stutter latencies [why] Recent characterization shows increased stutter latencies on some SKUs, leading to underflow. [how] Update SOC params to account for this worst case latency. Signed-off-by: Jun Lei <jun.lei@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 55ce2c7df84ef..18b9465057fff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -409,8 +409,8 @@ static struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = { }, }, .num_states = 5, - .sr_exit_time_us = 8.6, - .sr_enter_plus_exit_time_us = 10.9, + .sr_exit_time_us = 11.6, + .sr_enter_plus_exit_time_us = 13.9, .urgent_latency_us = 4.0, .urgent_latency_pixel_data_only_us = 4.0, .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, -- GitLab From e9462a32792c46d5ce25cb2eb37dd8f8241c8c08 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo <Jerry.Zuo@amd.com> Date: Wed, 2 Sep 2020 16:04:53 -0400 Subject: [PATCH 1198/1494] drm/amd/display: Further fix of psr eDP p-state warning [Why] psr doesn't get fully disabled before hitting hubbub1_wm_change_req_wa. [How] Pass TRUE to "wait" parameter to get psr fully disabled. Follow-Up fix to: dc: PSR eDP p-state warning occurs intermittently after unplug DP Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7ab82d6a5630c..f01610df8045e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2986,7 +2986,7 @@ bool dc_set_psr_allow_active(struct dc *dc, bool enable) if (enable && !link->psr_settings.psr_allow_active) return dc_link_set_psr_allow_active(link, true, false); else if (!enable && link->psr_settings.psr_allow_active) - return dc_link_set_psr_allow_active(link, false, false); + return dc_link_set_psr_allow_active(link, false, true); } } -- GitLab From 93669c8e480dca87235d8dcd364f47406b6129b3 Mon Sep 17 00:00:00 2001 From: Jun Lei <Jun.Lei@amd.com> Date: Wed, 12 Feb 2020 11:29:06 -0500 Subject: [PATCH 1199/1494] drm/amd/display: get socBB from VBIOS [why] Some SOC BB paramters may vary per SKU, and it does not make sense for driver to hardcode these values [how] Parse the values from VBIOS if available, and use them if valid Signed-off-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/bios/bios_parser2.c | 71 ++++++++++++++++++- .../gpu/drm/amd/display/dc/dc_bios_types.h | 4 ++ .../drm/amd/display/dc/dcn30/dcn30_resource.c | 16 +++++ .../amd/display/include/bios_parser_types.h | 6 ++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 2d5c7daaee231..29d64e7e304f4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -847,6 +847,73 @@ static enum bp_result bios_parser_get_spread_spectrum_info( return result; } +static enum bp_result get_soc_bb_info_v4_4( + struct bios_parser *bp, + struct bp_soc_bb_info *soc_bb_info) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL; + + if (!soc_bb_info) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + if (!DATA_TABLES(smu_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + soc_bb_info->dram_clock_change_latency_100ns = disp_cntl_tbl->max_mclk_chg_lat; + soc_bb_info->dram_sr_enter_exit_latency_100ns = disp_cntl_tbl->max_sr_enter_exit_lat; + soc_bb_info->dram_sr_exit_latency_100ns = disp_cntl_tbl->max_sr_exit_lat; + + return result; +} + +static enum bp_result bios_parser_get_soc_bb_info( + struct dc_bios *dcb, + struct bp_soc_bb_info *soc_bb_info) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!soc_bb_info) /* check for bad input */ + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_UNSUPPORTED; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + get_atom_data_table_revision(header, &tbl_revision); + + switch (tbl_revision.major) { + case 4: + switch (tbl_revision.minor) { + case 1: + case 2: + case 3: + break; + case 4: + result = get_soc_bb_info_v4_4(bp, soc_bb_info); + default: + break; + } + break; + default: + break; + } + + return result; +} + static enum bp_result get_embedded_panel_info_v2_1( struct bios_parser *bp, struct embedded_panel_info *info) @@ -2222,7 +2289,9 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_atom_dc_golden_table = bios_get_atom_dc_golden_table, - .enable_lvtma_control = bios_parser_enable_lvtma_control + .enable_lvtma_control = bios_parser_enable_lvtma_control, + + .get_soc_bb_info = bios_parser_get_soc_bb_info, }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 0811f941f4304..e146e3cba8ebe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -140,6 +140,10 @@ struct dc_vbios_funcs { enum bp_result (*enable_lvtma_control)( struct dc_bios *bios, uint8_t uc_pwr_on); + + enum bp_result (*get_soc_bb_info)( + struct dc_bios *dcb, + struct bp_soc_bb_info *soc_bb_info); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 168e6e4efaf49..dde87baf1370b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1828,6 +1828,22 @@ static bool init_soc_bounding_box(struct dc *dc, loaded_ip->max_num_dpp = pool->base.pipe_count; loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; dcn20_patch_bounding_box(dc, loaded_bb); + + if (!bb && dc->ctx->dc_bios->funcs->get_soc_bb_info) { + struct bp_soc_bb_info bb_info = {0}; + + if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { + if (bb_info.dram_clock_change_latency_100ns > 0) + dcn3_0_soc.dram_clock_change_latency_us = bb_info.dram_clock_change_latency_100ns * 10; + + if (bb_info.dram_sr_enter_exit_latency_100ns > 0) + dcn3_0_soc.sr_enter_plus_exit_time_us = bb_info.dram_sr_enter_exit_latency_100ns * 10; + + if (bb_info.dram_sr_exit_latency_100ns > 0) + dcn3_0_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10; + } + } + return true; } diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 21011edea337b..7c782924c9419 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -318,4 +318,10 @@ struct bp_encoder_cap_info { uint32_t RESERVED:27; }; +struct bp_soc_bb_info { + uint32_t dram_clock_change_latency_100ns; + uint32_t dram_sr_exit_latency_100ns; + uint32_t dram_sr_enter_exit_latency_100ns; +}; + #endif /*__DAL_BIOS_PARSER_TYPES_H__ */ -- GitLab From f833d625b5626f428be99309ebb5fbe682373ec6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Wed, 2 Sep 2020 16:23:46 -0400 Subject: [PATCH 1200/1494] drm/amd/display: update dcn30_optc header with missing declarations Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 5 ++--- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index 224c8d145eba4..6d13431ff6937 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -179,8 +179,7 @@ void optc3_set_dsc_config(struct timing_generator *optc, } - -static void optc3_set_odm_bypass(struct timing_generator *optc, +void optc3_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) { struct optc *optc1 = DCN10TG_FROM_TG(optc); @@ -277,7 +276,7 @@ static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, in * * Options: any time, start of frame, dp start of frame (range timing) */ -void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable) +static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool enable) { struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t mode = enable ? 2 : 0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h index 33f13c1e7520f..3796168316368 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h @@ -339,4 +339,8 @@ void optc3_set_dsc_config(struct timing_generator *optc, void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable); +void optc3_set_odm_bypass(struct timing_generator *optc, + const struct dc_crtc_timing *dc_crtc_timing); +void optc3_tg_init(struct timing_generator *optc); + #endif /* __DC_OPTC_DCN30_H__ */ -- GitLab From 598c13b21e25542c804dd19b193ca86ca3f5b8c1 Mon Sep 17 00:00:00 2001 From: Lewis Huang <Lewis.Huang@amd.com> Date: Thu, 3 Sep 2020 14:04:58 +0800 Subject: [PATCH 1201/1494] drm/amd/display: update clock when non-seamless boot stream exist [Why] Seamless boot skip porgram clock when set path mode. It cause driverprogram clock after unblank stream. [How] update clock when non-seamless boot stream exist Signed-off-by: Lewis Huang <Lewis.Huang@amd.com> Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f01610df8045e..83ce55edb3aa0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1286,7 +1286,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->optimize_seamless_boot_streams++; } - if (dc->optimize_seamless_boot_streams == 0) + if (context->stream_count > dc->optimize_seamless_boot_streams) dc->hwss.prepare_bandwidth(dc, context); disable_dangling_plane(dc, context); @@ -1368,7 +1368,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - if (dc->optimize_seamless_boot_streams == 0) { + if (context->stream_count > dc->optimize_seamless_boot_streams) { /* Must wait for no flips to be pending before doing optimize bw */ wait_for_no_pipes_pending(dc, context); /* pplib is notified if disp_num changed */ -- GitLab From ce87c98db428e779bf19c9cedc850fda22d58576 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Date: Thu, 10 Sep 2020 13:59:33 -0400 Subject: [PATCH 1202/1494] drm/amdgpu: Include sienna_cichlid in USBC PD FW support. Create sysfs interface also for sienna_cichlid. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 9782fbc000fe1..2c66e20b2ed9a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -178,7 +178,7 @@ static int psp_sw_init(void *handle) return ret; } - if (adev->asic_type == CHIP_NAVI10) { + if (adev->asic_type == CHIP_NAVI10 || adev->asic_type == CHIP_SIENNA_CICHLID) { ret= psp_sysfs_init(adev); if (ret) { return ret; -- GitLab From 91b5900507871c735a99842ebfe959dd33a66690 Mon Sep 17 00:00:00 2001 From: Oak Zeng <Oak.Zeng@amd.com> Date: Wed, 5 Aug 2020 10:53:09 -0500 Subject: [PATCH 1203/1494] drm/amdgpu: Add comment to function amdgpu_ttm_alloc_gart Add comments to refect what function does Signed-off-by: Oak Zeng <Oak.Zeng@amd.com> Reviewed-by: Christian Konig <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a18dc878339ab..257a1bab01473 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1155,7 +1155,12 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, } /** - * amdgpu_ttm_alloc_gart - Allocate GART memory for buffer object + * amdgpu_ttm_alloc_gart - Make sure buffer object is accessible either + * through AGP or GART aperture. + * + * If bo is accessible through AGP aperture, then use AGP aperture + * to access bo; otherwise allocate logical space in GART aperture + * and map bo to GART aperture. */ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) { -- GitLab From 719a6513fb4985305ca36a5dc468a531568e697b Mon Sep 17 00:00:00 2001 From: Oak Zeng <Oak.Zeng@amd.com> Date: Wed, 9 Sep 2020 12:51:45 -0500 Subject: [PATCH 1204/1494] drm/amdgpu: More accurate description of a function param Add more accurate description of the pe parameter of function amdgpu_vm_sdma_udpate and amdgpu_vm_cpu_update Signed-off-by: Oak Zeng <Oak.Zeng@amd.com> Reviewed-by: Christian Konig <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c index 39c704a1fb0e5..0786e7555554b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c @@ -59,7 +59,7 @@ static int amdgpu_vm_cpu_prepare(struct amdgpu_vm_update_params *p, * * @p: see amdgpu_vm_update_params definition * @bo: PD/PT to update - * @pe: kmap addr of the page entry + * @pe: byte offset of the PDE/PTE, relative to start of PDB/PTB * @addr: dst addr to write into pe * @count: number of page entries to update * @incr: increase next addr by incr bytes diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c index 189d46ea603be..db790574dc2e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c @@ -155,7 +155,7 @@ static void amdgpu_vm_sdma_copy_ptes(struct amdgpu_vm_update_params *p, * * @p: see amdgpu_vm_update_params definition * @bo: PD/PT to update - * @pe: addr of the page entry + * @pe: byte offset of the PDE/PTE, relative to start of PDB/PTB * @addr: dst addr to write into pe * @count: number of page entries to update * @incr: increase next addr by incr bytes @@ -187,7 +187,7 @@ static void amdgpu_vm_sdma_set_ptes(struct amdgpu_vm_update_params *p, * * @p: see amdgpu_vm_update_params definition * @bo: PD/PT to update - * @pe: addr of the page entry + * @pe: byte offset of the PDE/PTE, relative to start of PDB/PTB * @addr: dst addr to write into pe * @count: number of page entries to update * @incr: increase next addr by incr bytes -- GitLab From 0f3cd13d846105795de271ac64bb807df38513b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 9 Sep 2020 13:12:46 +0200 Subject: [PATCH 1205/1494] drm/radeon: revert "Prefer lower feedback dividers" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turns out this breaks a lot of different hardware. This reverts commit fc8c70526bd30733ea8667adb8b8ffebea30a8ed. Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 7b69d6dfe44a3..e0ae911ef427d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -933,7 +933,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, /* get matching reference and feedback divider */ *ref_div = min(max(den/post_div, 1u), ref_div_max); - *fb_div = max(nom * *ref_div * post_div / den, 1u); + *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); /* limit fb divider to its maximum */ if (*fb_div > fb_div_max) { -- GitLab From 7c679ef6678c7718d6c7284e6f9dd8dd4c27d4e4 Mon Sep 17 00:00:00 2001 From: Jonathan Kim <jonathan.kim@amd.com> Date: Tue, 4 Aug 2020 16:26:20 -0400 Subject: [PATCH 1206/1494] drm/amdgpu: stop resetting xgmi perfmons on disable Disabling perf events does not specify reset in ABI so stop doing it in hardware. Signed-off-by: Jonathan Kim <Jonathan.Kim@amd.com> Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_df.h | 4 ++-- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h index 61a26c15c8dd5..373cdebe0e2fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_df.h @@ -44,9 +44,9 @@ struct amdgpu_df_funcs { void (*enable_ecc_force_par_wr_rmw)(struct amdgpu_device *adev, bool enable); int (*pmc_start)(struct amdgpu_device *adev, uint64_t config, - int is_enable); + int is_add); int (*pmc_stop)(struct amdgpu_device *adev, uint64_t config, - int is_disable); + int is_remove); void (*pmc_get_count)(struct amdgpu_device *adev, uint64_t config, uint64_t *count); uint64_t (*get_fica)(struct amdgpu_device *adev, uint32_t ficaa_val); diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 2eab808fffeb5..7b89fd2aa44a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -455,7 +455,8 @@ static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev, uint32_t *lo_base_addr, uint32_t *hi_base_addr, uint32_t *lo_val, - uint32_t *hi_val) + uint32_t *hi_val, + bool is_enable) { uint32_t eventsel, instance, unitmask; @@ -477,7 +478,8 @@ static int df_v3_6_pmc_get_ctrl_settings(struct amdgpu_device *adev, instance_5432 = (instance >> 2) & 0xf; instance_76 = (instance >> 6) & 0x3; - *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel | (1 << 22); + *lo_val = (unitmask << 8) | (instance_10 << 6) | eventsel; + *lo_val = is_enable ? *lo_val | (1 << 22) : *lo_val & ~(1 << 22); *hi_val = (instance_76 << 29) | instance_5432; DRM_DEBUG_DRIVER("config=%llx addr=%08x:%08x val=%08x:%08x", @@ -572,14 +574,14 @@ static void df_v3_6_reset_perfmon_cntr(struct amdgpu_device *adev, } static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config, - int is_enable) + int is_add) { uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val; int err = 0, ret = 0; switch (adev->asic_type) { case CHIP_VEGA20: - if (is_enable) + if (is_add) return df_v3_6_pmc_add_cntr(adev, config); df_v3_6_reset_perfmon_cntr(adev, config); @@ -589,7 +591,8 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config, &lo_base_addr, &hi_base_addr, &lo_val, - &hi_val); + &hi_val, + true); if (ret) return ret; @@ -612,7 +615,7 @@ static int df_v3_6_pmc_start(struct amdgpu_device *adev, uint64_t config, } static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config, - int is_disable) + int is_remove) { uint32_t lo_base_addr, hi_base_addr, lo_val, hi_val; int ret = 0; @@ -624,15 +627,17 @@ static int df_v3_6_pmc_stop(struct amdgpu_device *adev, uint64_t config, &lo_base_addr, &hi_base_addr, &lo_val, - &hi_val); + &hi_val, + false); if (ret) return ret; - df_v3_6_reset_perfmon_cntr(adev, config); - if (is_disable) + if (is_remove) { + df_v3_6_reset_perfmon_cntr(adev, config); df_v3_6_pmc_release_cntr(adev, config); + } break; default: -- GitLab From cce63598976a9834e31c783d395533fc83f95b51 Mon Sep 17 00:00:00 2001 From: Chen Zhou <chenzhou10@huawei.com> Date: Tue, 8 Sep 2020 21:35:52 +0800 Subject: [PATCH 1207/1494] drm/amd/display: Remove duplicate include Remove duplicate header which is included twice. Signed-off-by: Chen Zhou <chenzhou10@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 7886c32d8315f..204773ffc376f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -35,7 +35,6 @@ #include "dcn30_dpp.h" #include "dcn10/dcn10_cm_common.h" #include "dcn30_cm_common.h" -#include "clk_mgr.h" #include "reg_helper.h" #include "abm.h" #include "clk_mgr.h" -- GitLab From 2634682fdffd9ba6e74b76be8aa91cf8b2e05c41 Mon Sep 17 00:00:00 2001 From: Randy Dunlap <rdunlap@infradead.org> Date: Tue, 8 Sep 2020 16:56:09 -0700 Subject: [PATCH 1208/1494] drm: amd/display: fix spelling of "function" Fix spellos of "function" in drivers/gpu/drm/amd/display/. Signed-off-by: Randy Dunlap <rdunlap@infradead.org> Cc: Harry Wentland <harry.wentland@amd.com> Cc: Leo Li <sunpeng.li@amd.com> Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h | 2 +- .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h | 2 +- .../gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h | 2 +- drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_factory_dcn21.c | 2 +- drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h index 1e557ddcb6385..d0b90947f5409 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h @@ -33,7 +33,7 @@ struct display_mode_lib; // Function: dml_rq_dlg_get_rq_reg // Main entry point for test to get the register values out of this DML class. -// This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate +// This function calls <get_rq_param> and <extract_rq_regs> functions to calculate // and then populate the rq_regs struct // Input: // pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h index 0d53e871a9d1e..27cf8bed9376f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h @@ -33,7 +33,7 @@ struct display_mode_lib; // Function: dml_rq_dlg_get_rq_reg // Main entry point for test to get the register values out of this DML class. -// This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate +// This function calls <get_rq_param> and <extract_rq_regs> functions to calculate // and then populate the rq_regs struct // Input: // pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h index e5b17e1104c61..c04965cceff35 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h @@ -32,7 +32,7 @@ struct display_mode_lib; // Function: dml_rq_dlg_get_rq_reg // Main entry point for test to get the register values out of this DML class. -// This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate +// This function calls <get_rq_param> and <extract_rq_regs> functions to calculate // and then populate the rq_regs struct // Input: // pipe_param - pipe source configuration (e.g. vp, pitch, scaling, dest, etc.) diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c index cf98aa827a9a0..e883864cff3c2 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c @@ -162,7 +162,7 @@ static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) } -/* fucntion table */ +/* function table */ static const struct hw_factory_funcs funcs = { .init_ddc_data = dal_hw_ddc_init, .init_generic = NULL, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c index b38c96c9fed3a..7d36b56346a6f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c @@ -194,7 +194,7 @@ static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) } -/* fucntion table */ +/* function table */ static const struct hw_factory_funcs funcs = { .init_ddc_data = dal_hw_ddc_init, .init_generic = dal_hw_generic_init, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c index 83f798cb8b210..9b63c6c0cc844 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn20/hw_factory_dcn20.c @@ -221,7 +221,7 @@ static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en) generic->base.regs = &generic_regs[en].gpio; } -/* fucntion table */ +/* function table */ static const struct hw_factory_funcs funcs = { .init_ddc_data = dal_hw_ddc_init, .init_generic = dal_hw_generic_init, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_factory_dcn21.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_factory_dcn21.c index 907c5911eb9e8..2f57ee6deabc0 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_factory_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_factory_dcn21.c @@ -202,7 +202,7 @@ static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) } -/* fucntion table */ +/* function table */ static const struct hw_factory_funcs funcs = { .init_ddc_data = dal_hw_ddc_init, .init_generic = dal_hw_generic_init, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c index 7e7fb65721073..3be2c90b0c618 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c @@ -218,7 +218,7 @@ static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) } -/* fucntion table */ +/* function table */ static const struct hw_factory_funcs funcs = { .init_ddc_data = dal_hw_ddc_init, .init_generic = dal_hw_generic_init, -- GitLab From 05f59762bcbfb3b943da3416fa2bc5ea7fdb662b Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Wed, 9 Sep 2020 15:57:05 +0800 Subject: [PATCH 1209/1494] drm/scheduler: fix sched_fence.c kernel-doc warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix kernel-doc warnings. drivers/gpu/drm/scheduler/sched_fence.c:110: warning: Function parameter or member 'f' not described in 'drm_sched_fence_release_scheduled' drivers/gpu/drm/scheduler/sched_fence.c:110: warning: Excess function parameter 'fence' description in 'drm_sched_fence_release_scheduled' Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/scheduler/sched_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index 8b45c3a1b84e8..69de2c76731f4 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -101,7 +101,7 @@ static void drm_sched_fence_free(struct rcu_head *rcu) /** * drm_sched_fence_release_scheduled - callback that fence can be freed * - * @fence: fence + * @f: fence * * This function is called when the reference count becomes zero. * It just RCU schedules freeing up the fence. -- GitLab From 052813d9fa22d52857b10356c2a7d9c53c285c72 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman <sandy.8925@gmail.com> Date: Wed, 9 Sep 2020 16:34:33 +0530 Subject: [PATCH 1210/1494] drm/radeon: Add sclk frequency as hwmon sensor This patch adds support for reporting sclk values for Radeon GPUs, where supported. Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_pm.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 8c5d6fda0d757..05c4196a8212d 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -712,6 +712,31 @@ static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1_ static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, radeon_hwmon_get_pwm1_min, NULL, 0); static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, radeon_hwmon_get_pwm1_max, NULL, 0); +static ssize_t radeon_hwmon_show_sclk(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct radeon_device *rdev = dev_get_drvdata(dev); + struct drm_device *ddev = rdev->ddev; + u32 sclk = 0; + + /* Can't get clock frequency when the card is off */ + if ((rdev->flags & RADEON_IS_PX) && + (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) + return -EINVAL; + + if (rdev->asic->dpm.get_current_sclk) + sclk = radeon_dpm_get_current_sclk(rdev); + + /* Value returned by dpm is in 10 KHz units, need to convert it into Hz + for hwmon */ + sclk *= 10000; + + return snprintf(buf, PAGE_SIZE, "%u\n", sclk); +} + +static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, radeon_hwmon_show_sclk, NULL, + 0); + static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -721,6 +746,7 @@ static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_pwm1_enable.dev_attr.attr, &sensor_dev_attr_pwm1_min.dev_attr.attr, &sensor_dev_attr_pwm1_max.dev_attr.attr, + &sensor_dev_attr_freq1_input.dev_attr.attr, NULL }; @@ -738,7 +764,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1.dev_attr.attr || attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || + attr == &sensor_dev_attr_freq1_input.dev_attr.attr)) return 0; /* Skip fan attributes if fan is not present */ -- GitLab From 7b3fa67d6e0aabb7eb0394608d481eb2aa65f22c Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:13 +0800 Subject: [PATCH 1211/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in gfx_v9_0.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c:2805:5-11: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 93c63ff3b35ee..d898c9ff35269 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2800,7 +2800,7 @@ static void pwr_10_0_gfxip_control_over_cgpg(struct amdgpu_device *adev, uint32_t default_data = 0; default_data = data = RREG32(SOC15_REG_OFFSET(PWR, 0, mmPWR_MISC_CNTL_STATUS)); - if (enable == true) { + if (enable) { /* enable GFXIP control over CGPG */ data |= PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN_MASK; if(default_data != data) -- GitLab From 89cf8b06378ff930fece568d0f18dd2f719694f9 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:14 +0800 Subject: [PATCH 1212/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in gfx_v10_0.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c:3563:5-31: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 9801bb6daa016..17fb2efdadd3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3560,7 +3560,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev) break; } - if (adev->gfx.cp_fw_write_wait == false) + if (!adev->gfx.cp_fw_write_wait) DRM_WARN_ONCE("CP firmware version too old, please update!"); } -- GitLab From 960a06ff9151ab8f27108939ff803538f0612b34 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:15 +0800 Subject: [PATCH 1213/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in sdma_v5_0.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c:619:5-11: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index e2232dd12d8e3..48c95a78a1739 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -616,7 +616,7 @@ static void sdma_v5_0_enable(struct amdgpu_device *adev, bool enable) u32 f32_cntl; int i; - if (enable == false) { + if (!enable) { sdma_v5_0_gfx_stop(adev); sdma_v5_0_rlc_stop(adev); } -- GitLab From 4bbbe77c15c633fae464ce7f7106762a1fe7c7a9 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:16 +0800 Subject: [PATCH 1214/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in sdma_v5_2.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c:562:5-11: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 46a9617fee5f4..34ccf376ee45e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -559,7 +559,7 @@ static void sdma_v5_2_enable(struct amdgpu_device *adev, bool enable) u32 f32_cntl; int i; - if (enable == false) { + if (!enable) { sdma_v5_2_gfx_stop(adev); sdma_v5_2_rlc_stop(adev); } -- GitLab From e66cdf250e7cba9fa7308b179fceeb2fdcbed3ba Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:17 +0800 Subject: [PATCH 1215/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in si.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/si.c:1342:5-10: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/si.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 455d5e366c690..e5e336fd9e941 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1339,7 +1339,7 @@ static void si_vga_set_state(struct amdgpu_device *adev, bool state) uint32_t temp; temp = RREG32(CONFIG_CNTL); - if (state == false) { + if (!state) { temp &= ~(1<<0); temp |= (1<<1); } else { -- GitLab From 3d0c75afdc2963a8ea62598160397d0f69058231 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:18 +0800 Subject: [PATCH 1216/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in uvd_v6_0.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c:1243:14-25: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 0a880bc101b84..ed30fb48b9dbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1240,8 +1240,8 @@ static int uvd_v6_0_process_interrupt(struct amdgpu_device *adev, break; } - if (false == int_handled) - DRM_ERROR("Unhandled interrupt: %d %d\n", + if (!int_handled) + DRM_ERROR("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data[0]); return 0; -- GitLab From 8f00d1fc9d305add493e6bd379a4b05c284b11e9 Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:19 +0800 Subject: [PATCH 1217/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in amdgpu_atpx_handler.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c:619:15-49: WARNING: Comparison to bool drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c:629:15-49: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index 3e35a8f2c5e55..7abe9500c0c64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -616,7 +616,7 @@ static bool amdgpu_atpx_detect(void) while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { vga_count++; - has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); + has_atpx |= amdgpu_atpx_pci_probe_handle(pdev); parent_pdev = pci_upstream_bridge(pdev); d3_supported |= parent_pdev && parent_pdev->bridge_d3; @@ -626,7 +626,7 @@ static bool amdgpu_atpx_detect(void) while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { vga_count++; - has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true); + has_atpx |= amdgpu_atpx_pci_probe_handle(pdev); parent_pdev = pci_upstream_bridge(pdev); d3_supported |= parent_pdev && parent_pdev->bridge_d3; -- GitLab From 724dc53b922c98aced93d42d90ffd66a628069af Mon Sep 17 00:00:00 2001 From: Zheng Bin <zhengbin13@huawei.com> Date: Wed, 9 Sep 2020 21:07:20 +0800 Subject: [PATCH 1218/1494] drm/amd/amdgpu: fix comparison pointer to bool warning in sdma_v4_0.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes coccicheck warning: drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c:1003:4-9: WARNING: Comparison to bool drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c:1083:5-11: WARNING: Comparison to bool Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Zheng Bin <zhengbin13@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index edea8743f26eb..810635cbf4c15 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1000,7 +1000,7 @@ static void sdma_v4_0_page_stop(struct amdgpu_device *adev) sdma[i] = &adev->sdma.instance[i].page; if ((adev->mman.buffer_funcs_ring == sdma[i]) && - (unset == false)) { + (!unset)) { amdgpu_ttm_set_buffer_funcs_status(adev, false); unset = true; } @@ -1089,7 +1089,7 @@ static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable) u32 f32_cntl; int i; - if (enable == false) { + if (!enable) { sdma_v4_0_gfx_stop(adev); sdma_v4_0_rlc_stop(adev); if (adev->sdma.has_page_queue) -- GitLab From d56b83f7c1a42c27fe499be2fb5c75a038459c04 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Wed, 9 Sep 2020 19:05:04 -0700 Subject: [PATCH 1219/1494] drm/amd/display: optimize code runtime a bit In fnction is_cr_done & is_ch_eq_done, when done = false happened once, no need to circle left ln_count. This change is to make the code run a bit fast. Signed-off-by: Bernard Zhao <bernard@vivo.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 47fb09f41bfbe..b9b66db8332b9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -380,34 +380,30 @@ static void dpcd_set_lt_pattern_and_lane_settings( static bool is_cr_done(enum dc_lane_count ln_count, union lane_status *dpcd_lane_status) { - bool done = true; uint32_t lane; /*LANEx_CR_DONE bits All 1's?*/ for (lane = 0; lane < (uint32_t)(ln_count); lane++) { if (!dpcd_lane_status[lane].bits.CR_DONE_0) - done = false; + return false; } - return done; - + return true; } static bool is_ch_eq_done(enum dc_lane_count ln_count, union lane_status *dpcd_lane_status, union lane_align_status_updated *lane_status_updated) { - bool done = true; uint32_t lane; if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE) - done = false; + return false; else { for (lane = 0; lane < (uint32_t)(ln_count); lane++) { if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 || !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) - done = false; + return false; } } - return done; - + return true; } static void update_drive_settings( -- GitLab From d75fa679b056375494501ad47ea98fca5d712ff0 Mon Sep 17 00:00:00 2001 From: YueHaibing <yuehaibing@huawei.com> Date: Thu, 10 Sep 2020 11:26:36 +0800 Subject: [PATCH 1220/1494] drm/amd/display: Fix possible memleak in dp_trigger_hotplug() If parse_write_buffer_into_params() fails, we should free wr_buf before return. Fixes: 6f77b2ac6280 ("drm/amd/display: Add connector HPD trigger debugfs entry") Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9be2f291382df..47cc39ad47f9b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1093,8 +1093,10 @@ static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, if (parse_write_buffer_into_params(wr_buf, size, (long *)param, buf, max_param_num, - ¶m_nums)) + ¶m_nums)) { + kfree(wr_buf); return -EINVAL; + } if (param_nums <= 0) { DRM_DEBUG_DRIVER("user data not be read\n"); -- GitLab From 04a238e9c51118962203f2e332aa464eb563278d Mon Sep 17 00:00:00 2001 From: YueHaibing <yuehaibing@huawei.com> Date: Thu, 10 Sep 2020 11:13:52 +0800 Subject: [PATCH 1221/1494] drm/amd/display: Create trigger_hotplug entry Add trigger_hotplug debugfs entry. Fixes: 6f77b2ac6280 ("drm/amd/display: Add connector HPD trigger debugfs entry") Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 47cc39ad47f9b..004cd8d382145 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2146,6 +2146,7 @@ static const struct { const struct file_operations *fops; } dp_debugfs_entries[] = { {"link_settings", &dp_link_settings_debugfs_fops}, + {"trigger_hotplug", &dp_trigger_hotplug_debugfs_fops}, {"phy_settings", &dp_phy_settings_debugfs_fop}, {"test_pattern", &dp_phy_test_pattern_fops}, #ifdef CONFIG_DRM_AMD_DC_HDCP -- GitLab From ea68573d408fdf8df31dc93e826c35a1f6218f36 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Sun, 6 Sep 2020 12:05:12 -0400 Subject: [PATCH 1222/1494] drm/amdgpu: Fail to load on RAVEN if SME is active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to hardware bugs, scatter/gather display on raven requires a 1:1 IOMMU mapping, however, SME (System Memory Encryption) requires an indirect IOMMU mapping because the encryption bit is beyond the DMA mask of the chip. As such, the two are incompatible. Acked-by: Joerg Roedel <jroedel@suse.de> Reviewed-by: Christian König <christian.koenig@amd.com> Acked-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 5fafb3dff1a06..52cf9488bbbff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1101,6 +1101,16 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENODEV; } + /* Due to hardware bugs, S/G Display on raven requires a 1:1 IOMMU mapping, + * however, SME requires an indirect IOMMU mapping because the encryption + * bit is beyond the DMA mask of the chip. + */ + if (mem_encrypt_active() && ((flags & AMD_ASIC_MASK) == CHIP_RAVEN)) { + dev_info(&pdev->dev, + "SME is not compatible with RAVEN\n"); + return -ENOTSUPP; + } + #ifdef CONFIG_DRM_AMDGPU_SI if (!amdgpu_si_support) { switch (flags & AMD_ASIC_MASK) { -- GitLab From f4075be88246eeb9b6cf50339fd6ebf9201f2091 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 14 Sep 2020 11:36:21 -0400 Subject: [PATCH 1223/1494] drm/amdgpu/gmc9: remove mmhub client duplicated case Copy paste typo. Reported-by: kernel test robot <lkp@intel.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 91629c2b1d5c2..c605a1885374b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -269,7 +269,6 @@ static const char *mmhub_client_ids_arcturus[][2] = { [14][1] = "HDP", [15][1] = "SDMA0", [32+15][1] = "SDMA1", - [32+15][1] = "SDMA1", [64+15][1] = "SDMA2", [96+15][1] = "SDMA3", [128+15][1] = "SDMA4", -- GitLab From b836a274b797e90ff0b3bccf0a1e6f8557f590bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com> Date: Fri, 4 Sep 2020 12:43:04 +0200 Subject: [PATCH 1224/1494] drm/amdgpu/dc: Require primary plane to be enabled whenever the CRTC is MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't check drm_crtc_state::active for this either, per its documentation in include/drm/drm_crtc.h: * Hence drivers must not consult @active in their various * &drm_mode_config_funcs.atomic_check callback to reject an atomic * commit. atomic_remove_fb disables the CRTC as needed for disabling the primary plane. This prevents at least the following problems if the primary plane gets disabled (e.g. due to destroying the FB assigned to the primary plane, as happens e.g. with mutter in Wayland mode): * The legacy cursor ioctl returned EINVAL for a non-0 cursor FB ID (which enables the cursor plane). * If the cursor plane was enabled, changing the legacy DPMS property value from off to on returned EINVAL. v2: * Minor changes to code comment and commit log, per review feedback. GitLab: https://gitlab.gnome.org/GNOME/mutter/-/issues/1108 GitLab: https://gitlab.gnome.org/GNOME/mutter/-/issues/1165 GitLab: https://gitlab.gnome.org/GNOME/mutter/-/issues/1344 Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Michel Dänzer <mdaenzer@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8c13572d5c163..57738164625b4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5460,19 +5460,6 @@ static void dm_crtc_helper_disable(struct drm_crtc *crtc) { } -static bool does_crtc_have_active_cursor(struct drm_crtc_state *new_crtc_state) -{ - struct drm_device *dev = new_crtc_state->crtc->dev; - struct drm_plane *plane; - - drm_for_each_plane_mask(plane, dev, new_crtc_state->plane_mask) { - if (plane->type == DRM_PLANE_TYPE_CURSOR) - return true; - } - - return false; -} - static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state) { struct drm_atomic_state *state = new_crtc_state->state; @@ -5536,19 +5523,20 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, return ret; } - /* In some use cases, like reset, no stream is attached */ - if (!dm_crtc_state->stream) - return 0; - /* - * We want at least one hardware plane enabled to use - * the stream with a cursor enabled. + * We require the primary plane to be enabled whenever the CRTC is, otherwise + * drm_mode_cursor_universal may end up trying to enable the cursor plane while all other + * planes are disabled, which is not supported by the hardware. And there is legacy + * userspace which stops using the HW cursor altogether in response to the resulting EINVAL. */ - if (state->enable && state->active && - does_crtc_have_active_cursor(state) && - dm_crtc_state->active_planes == 0) + if (state->enable && + !(state->plane_mask & drm_plane_mask(crtc->primary))) return -EINVAL; + /* In some use cases, like reset, no stream is attached */ + if (!dm_crtc_state->stream) + return 0; + if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK) return 0; -- GitLab From 400d4953f1f434d50640524707106eb889be8a11 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa <anusha.srivatsa@intel.com> Date: Fri, 28 Aug 2020 14:10:56 -0700 Subject: [PATCH 1225/1494] drm/i915/pll: Centralize PLL_ENABLE register lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currenty check for platform at multiple parts in the driver to grab the correct PLL. Let us begin to centralize it through a helper function. v2: s/intel_get_pll_enable_reg()/intel_combo_pll_enable_reg() (Ville) v3: Clean up combo_pll_disable() (Rodrigo) v4: s/dev_priv/i915 (Jani) Move static and return type to the same line( Ville, Jani) Suggested-by: Matt Roper <matthew.d.roper@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Signed-off-by: Anusha Srivatsa <anusha.srivatsa@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200914175703.15024-1-anusha.srivatsa@intel.com Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c9013f8f766fa..e08684e34078a 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -147,6 +147,18 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, pll->info->name, onoff(state), onoff(cur_state)); } +static i915_reg_t +intel_combo_pll_enable_reg(struct drm_i915_private *i915, + struct intel_shared_dpll *pll) +{ + + if (IS_ELKHARTLAKE(i915) && (pll->info->id == DPLL_ID_EHL_DPLL4)) + return MG_PLL_ENABLE(0); + + return CNL_DPLL_ENABLE(pll->info->id); + + +} /** * intel_prepare_shared_dpll - call a dpll's prepare hook * @crtc_state: CRTC, and its state, which has a shared dpll @@ -3842,12 +3854,7 @@ static bool combo_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { - i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); - - if (IS_ELKHARTLAKE(dev_priv) && - pll->info->id == DPLL_ID_EHL_DPLL4) { - enable_reg = MG_PLL_ENABLE(0); - } + i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); return icl_pll_get_hw_state(dev_priv, pll, hw_state, enable_reg); } @@ -4045,11 +4052,10 @@ static void icl_pll_enable(struct drm_i915_private *dev_priv, static void combo_pll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { - i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); + i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); if (IS_ELKHARTLAKE(dev_priv) && pll->info->id == DPLL_ID_EHL_DPLL4) { - enable_reg = MG_PLL_ENABLE(0); /* * We need to disable DC states when this DPLL is enabled. @@ -4157,19 +4163,14 @@ static void icl_pll_disable(struct drm_i915_private *dev_priv, static void combo_pll_disable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { - i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id); + i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); - if (IS_ELKHARTLAKE(dev_priv) && - pll->info->id == DPLL_ID_EHL_DPLL4) { - enable_reg = MG_PLL_ENABLE(0); - icl_pll_disable(dev_priv, pll, enable_reg); + icl_pll_disable(dev_priv, pll, enable_reg); + if (IS_ELKHARTLAKE(dev_priv) && + pll->info->id == DPLL_ID_EHL_DPLL4) intel_display_power_put(dev_priv, POWER_DOMAIN_DPLL_DC_OFF, pll->wakeref); - return; - } - - icl_pll_disable(dev_priv, pll, enable_reg); } static void tbt_pll_disable(struct drm_i915_private *dev_priv, -- GitLab From 7eec915138279d7a83ff8f219846bf7c8ae637c1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 10:21:15 +1000 Subject: [PATCH 1226/1494] drm/ttm/tt: add wrappers to set tt state. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds 2 getters and 4 setters, however unbound and populated are currently the same thing, this will change, it also drops a BUG_ON that seems not that useful. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +-- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +-- drivers/gpu/drm/radeon/radeon_mn.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 4 +-- drivers/gpu/drm/ttm/ttm_bo_util.c | 2 +- drivers/gpu/drm/ttm/ttm_page_alloc.c | 6 ++-- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 6 ++-- drivers/gpu/drm/ttm/ttm_tt.c | 20 ++++++-------- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 4 +-- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 2 +- include/drm/ttm/ttm_tt.h | 32 +++++++++++++++++++++- 11 files changed, 57 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c2678e021f955..3e8376891ec82 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1304,7 +1304,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev, return -ENOMEM; ttm->page_flags |= TTM_PAGE_FLAG_SG; - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } @@ -1324,7 +1324,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev, drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, gtt->ttm.dma_address, ttm->num_pages); - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index b062ea8afffd8..963bac0730dab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1298,14 +1298,14 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev, struct device *dev; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); - if (ttm->state != tt_unpopulated) + if (ttm_tt_is_populated(ttm)) return 0; if (slave && ttm->sg) { /* make userspace faulting work */ drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, ttm_dma->dma_address, ttm->num_pages); - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index f93829f08a4dc..b6293fb910300 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -53,7 +53,7 @@ static bool radeon_mn_invalidate(struct mmu_interval_notifier *mn, struct ttm_operation_ctx ctx = { false, false }; long r; - if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound) + if (!bo->tbo.ttm || !ttm_tt_is_bound(bo->tbo.ttm)) return true; if (!mmu_notifier_range_blockable(range)) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 96be5c3c12692..b0e8c9337f547 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -611,14 +611,14 @@ static int radeon_ttm_tt_populate(struct ttm_bo_device *bdev, return -ENOMEM; ttm->page_flags |= TTM_PAGE_FLAG_SG; - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } if (slave && ttm->sg) { drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, gtt->ttm.dma_address, ttm->num_pages); - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 1b56432dfa438..44b47ccdeaf7e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -249,7 +249,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, * Don't move nonexistent data. Clear destination instead. */ if (old_iomap == NULL && - (ttm == NULL || (ttm->state == tt_unpopulated && + (ttm == NULL || (!ttm_tt_is_populated(ttm) && !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) { memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE); goto out2; diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index b40a4678c2963..14660f723f71a 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -1044,7 +1044,7 @@ ttm_pool_unpopulate_helper(struct ttm_tt *ttm, unsigned mem_count_update) put_pages: ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags, ttm->caching_state); - ttm->state = tt_unpopulated; + ttm_tt_set_unpopulated(ttm); } int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) @@ -1053,7 +1053,7 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) unsigned i; int ret; - if (ttm->state != tt_unpopulated) + if (ttm_tt_is_populated(ttm)) return 0; if (ttm_check_under_lowerlimit(mem_glob, ttm->num_pages, ctx)) @@ -1083,7 +1083,7 @@ int ttm_pool_populate(struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) } } - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } EXPORT_SYMBOL(ttm_pool_populate); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index faefaaef79099..5e2df11685e7c 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -894,7 +894,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev, unsigned i; int ret; - if (ttm->state != tt_unpopulated) + if (ttm_tt_is_populated(ttm)) return 0; if (ttm_check_under_lowerlimit(mem_glob, num_pages, ctx)) @@ -982,7 +982,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev, } } - ttm->state = tt_unbound; + ttm_tt_set_populated(ttm); return 0; } EXPORT_SYMBOL_GPL(ttm_dma_populate); @@ -1076,7 +1076,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) /* shrink pool if necessary (only on !is_cached pools)*/ if (npages) ttm_dma_page_pool_free(pool, npages, false); - ttm->state = tt_unpopulated; + ttm_tt_set_unpopulated(ttm); } EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 67aa7fe39432d..ff3d953aa90ed 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -156,7 +156,7 @@ static int ttm_tt_set_caching(struct ttm_tt *ttm, if (ttm->caching_state == c_state) return 0; - if (ttm->state == tt_unpopulated) { + if (!ttm_tt_is_populated(ttm)) { /* Change caching but don't populate */ ttm->caching_state = c_state; return 0; @@ -214,8 +214,7 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) ttm_tt_unbind(bdev, ttm); - if (ttm->state == tt_unbound) - ttm_tt_unpopulate(bdev, ttm); + ttm_tt_unpopulate(bdev, ttm); if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && ttm->swap_storage) @@ -232,7 +231,7 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm, ttm->num_pages = bo->num_pages; ttm->caching_state = tt_cached; ttm->page_flags = page_flags; - ttm->state = tt_unpopulated; + ttm_tt_set_unpopulated(ttm); ttm->swap_storage = NULL; ttm->sg = bo->sg; } @@ -309,9 +308,9 @@ EXPORT_SYMBOL(ttm_dma_tt_fini); void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - if (ttm->state == tt_bound) { + if (ttm_tt_is_bound(ttm)) { bdev->driver->ttm_tt_unbind(bdev, ttm); - ttm->state = tt_unbound; + ttm_tt_set_unbound(ttm); } } @@ -324,7 +323,7 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, if (!ttm) return -EINVAL; - if (ttm->state == tt_bound) + if (ttm_tt_is_bound(ttm)) return 0; ret = ttm_tt_populate(bdev, ttm, ctx); @@ -335,7 +334,7 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, if (unlikely(ret != 0)) return ret; - ttm->state = tt_bound; + ttm_tt_set_bound(ttm); return 0; } @@ -393,7 +392,6 @@ int ttm_tt_swapout(struct ttm_bo_device *bdev, int i; int ret = -ENOMEM; - BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated); BUG_ON(ttm->caching_state != tt_cached); if (!persistent_swap_storage) { @@ -460,7 +458,7 @@ int ttm_tt_populate(struct ttm_bo_device *bdev, { int ret; - if (ttm->state != tt_unpopulated) + if (ttm_tt_is_populated(ttm)) return 0; if (bdev->driver->ttm_tt_populate) @@ -489,7 +487,7 @@ static void ttm_tt_clear_mapping(struct ttm_tt *ttm) void ttm_tt_unpopulate(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - if (ttm->state == tt_unpopulated) + if (!ttm_tt_is_populated(ttm)) return; ttm_tt_clear_mapping(ttm); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index 0cd21590ded9e..e8d66182cd7b5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -464,13 +464,13 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, if (!(src->mem.placement & TTM_PL_FLAG_NO_EVICT)) dma_resv_assert_held(src->base.resv); - if (dst->ttm->state == tt_unpopulated) { + if (!ttm_tt_is_populated(dst->ttm)) { ret = dst->bdev->driver->ttm_tt_populate(dst->bdev, dst->ttm, &ctx); if (ret) return ret; } - if (src->ttm->state == tt_unpopulated) { + if (!ttm_tt_is_populated(src->ttm)) { ret = src->bdev->driver->ttm_tt_populate(src->bdev, src->ttm, &ctx); if (ret) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 03aa0fc5e753c..3458c5c3531d6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -644,7 +644,7 @@ static int vmw_ttm_populate(struct ttm_bo_device *bdev, struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); int ret; - if (ttm->state != tt_unpopulated) + if (ttm_tt_is_populated(ttm)) return 0; if (dev_priv->map_mode == vmw_dma_alloc_coherent) { diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 146544ba1c100..86ae759ff0182 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -74,9 +74,39 @@ struct ttm_tt { tt_bound, tt_unbound, tt_unpopulated, - } state; + } _state; }; +static inline bool ttm_tt_is_populated(struct ttm_tt *tt) +{ + return tt->_state != tt_unpopulated; +} + +static inline bool ttm_tt_is_bound(struct ttm_tt *tt) +{ + return tt->_state == tt_bound; +} + +static inline void ttm_tt_set_unpopulated(struct ttm_tt *tt) +{ + tt->_state = tt_unpopulated; +} + +static inline void ttm_tt_set_populated(struct ttm_tt *tt) +{ + tt->_state = tt_unbound; +} + +static inline void ttm_tt_set_unbound(struct ttm_tt *tt) +{ + tt->_state = tt_unbound; +} + +static inline void ttm_tt_set_bound(struct ttm_tt *tt) +{ + tt->_state = tt_bound; +} + /** * struct ttm_dma_tt * -- GitLab From 2ff6e69c0449846197c52d7c591b983e23e3e3c9 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:02:12 +1000 Subject: [PATCH 1227/1494] drm/ttm: wrap tt destroy. (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All places this was called was using bo->ttm either direct or indirectly. v2: move to ttm_bo Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-3-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 15 +++++++++------ drivers/gpu/drm/ttm/ttm_bo_util.c | 18 ++++++------------ include/drm/ttm/ttm_bo_driver.h | 5 +++++ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index ee2632128d3c6..aea61017f03a1 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -301,10 +301,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, out_err: new_man = ttm_manager_type(bdev, bo->mem.mem_type); - if (!new_man->use_tt) { - ttm_tt_destroy(bdev, bo->ttm); - bo->ttm = NULL; - } + if (!new_man->use_tt) + ttm_bo_tt_destroy(bo); return ret; } @@ -322,8 +320,7 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) if (bo->bdev->driver->move_notify) bo->bdev->driver->move_notify(bo, false, NULL); - ttm_tt_destroy(bo->bdev, bo->ttm); - bo->ttm = NULL; + ttm_bo_tt_destroy(bo); ttm_resource_free(bo, &bo->mem); } @@ -1613,3 +1610,9 @@ void ttm_bo_swapout_all(void) while (ttm_bo_swapout(&ttm_bo_glob, &ctx) == 0); } EXPORT_SYMBOL(ttm_bo_swapout_all); + +void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) +{ + ttm_tt_destroy(bo->bdev, bo->ttm); + bo->ttm = NULL; +} diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 44b47ccdeaf7e..0d2f3bc5df92a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -297,10 +297,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, *old_mem = *new_mem; new_mem->mm_node = NULL; - if (!man->use_tt) { - ttm_tt_destroy(bdev, ttm); - bo->ttm = NULL; - } + if (!man->use_tt) + ttm_bo_tt_destroy(bo); out1: ttm_resource_iounmap(bdev, old_mem, new_iomap); @@ -542,10 +540,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (ret) return ret; - if (!man->use_tt) { - ttm_tt_destroy(bdev, bo->ttm); - bo->ttm = NULL; - } + if (!man->use_tt) + ttm_bo_tt_destroy(bo); ttm_bo_free_old_node(bo); } else { /** @@ -665,10 +661,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, if (ret) return ret; - if (!to->use_tt) { - ttm_tt_destroy(bdev, bo->ttm); - bo->ttm = NULL; - } + if (!to->use_tt) + ttm_bo_tt_destroy(bo); ttm_bo_free_old_node(bo); } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 0b7d18650dc53..70557e2de9be7 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -684,6 +684,11 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); */ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); +/** + * ttm_bo_tt_destroy. + */ +void ttm_bo_tt_destroy(struct ttm_buffer_object *bo); + /** * ttm_range_man_init * -- GitLab From 395a73f8ba6f00f0e188ac6daa43659520d75498 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:04:08 +1000 Subject: [PATCH 1228/1494] drm/ttm: tt destroy move null check to outer function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This just makes things easier later. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-4-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 2 ++ drivers/gpu/drm/ttm/ttm_bo_util.c | 1 + drivers/gpu/drm/ttm/ttm_tt.c | 3 --- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index aea61017f03a1..bca0d42a970a9 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1613,6 +1613,8 @@ EXPORT_SYMBOL(ttm_bo_swapout_all); void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) { + if (bo->ttm == NULL) + return; ttm_tt_destroy(bo->bdev, bo->ttm); bo->ttm = NULL; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 0d2f3bc5df92a..8389972a1ed6f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -696,3 +696,4 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) return 0; } + diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index ff3d953aa90ed..381face3cedb7 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -209,9 +209,6 @@ EXPORT_SYMBOL(ttm_tt_set_placement_caching); void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - if (ttm == NULL) - return; - ttm_tt_unbind(bdev, ttm); ttm_tt_unpopulate(bdev, ttm); -- GitLab From 2040ec970e94dde0b94e200ae9bb8f21a61c928f Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:16:53 +1000 Subject: [PATCH 1229/1494] drm/ttm: split populate out from binding. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers have to call populate themselves now before binding. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-5-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +++++- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +++++- drivers/gpu/drm/radeon/radeon_ttm.c | 7 ++++++- drivers/gpu/drm/ttm/ttm_bo.c | 6 +++++- drivers/gpu/drm/ttm/ttm_bo_util.c | 7 ++++++- drivers/gpu/drm/ttm/ttm_tt.c | 11 +++++------ include/drm/ttm/ttm_tt.h | 3 +-- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3e8376891ec82..9353e41cf6692 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -547,8 +547,12 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, goto out_cleanup; } + r = ttm_tt_populate(bo->bdev, bo->ttm, ctx); + if (unlikely(r)) + goto out_cleanup; + /* Bind the memory to the GTT space */ - r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, ctx); + r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 963bac0730dab..1088de50c14ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -920,7 +920,11 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) return ret; - ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg, &ctx); + ret = ttm_tt_populate(bo->bdev, bo->ttm, &ctx); + if (ret) + goto out; + + ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg); if (ret) goto out; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index b0e8c9337f547..2833028982010 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -233,7 +233,12 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, goto out_cleanup; } - r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem, &ctx); + r = ttm_tt_populate(bo->bdev, bo->ttm, &ctx); + if (unlikely(r)) { + goto out_cleanup; + } + + r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index bca0d42a970a9..654384c7aae11 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -260,7 +260,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, goto out_err; if (mem->mem_type != TTM_PL_SYSTEM) { - ret = ttm_tt_bind(bdev, bo->ttm, mem, ctx); + ret = ttm_tt_populate(bdev, bo->ttm, ctx); + if (ret) + goto out_err; + + ret = ttm_tt_bind(bdev, bo->ttm, mem); if (ret) goto out_err; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 8389972a1ed6f..2ce97760a0892 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -77,7 +77,12 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, return ret; if (new_mem->mem_type != TTM_PL_SYSTEM) { - ret = ttm_tt_bind(bo->bdev, ttm, new_mem, ctx); + + ret = ttm_tt_populate(bo->bdev, ttm, ctx); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_tt_bind(bo->bdev, ttm, new_mem); if (unlikely(ret != 0)) return ret; } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 381face3cedb7..93d65e5e4205a 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -312,8 +312,7 @@ void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) } int ttm_tt_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem, - struct ttm_operation_ctx *ctx) + struct ttm_tt *ttm, struct ttm_resource *bo_mem) { int ret = 0; @@ -323,10 +322,6 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, if (ttm_tt_is_bound(ttm)) return 0; - ret = ttm_tt_populate(bdev, ttm, ctx); - if (ret) - return ret; - ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem); if (unlikely(ret != 0)) return ret; @@ -455,6 +450,9 @@ int ttm_tt_populate(struct ttm_bo_device *bdev, { int ret; + if (!ttm) + return -EINVAL; + if (ttm_tt_is_populated(ttm)) return 0; @@ -466,6 +464,7 @@ int ttm_tt_populate(struct ttm_bo_device *bdev, ttm_tt_add_mapping(bdev, ttm); return ret; } +EXPORT_SYMBOL(ttm_tt_populate); static void ttm_tt_clear_mapping(struct ttm_tt *ttm) { diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 86ae759ff0182..8f57d86ee67b5 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -173,8 +173,7 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); * Bind the pages of @ttm to an aperture location identified by @bo_mem */ int ttm_tt_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem, - struct ttm_operation_ctx *ctx); + struct ttm_tt *ttm, struct ttm_resource *bo_mem); /** * ttm_ttm_destroy: -- GitLab From 9e9a153bdf2555a931fd37678a8e44d170a5d943 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:34:51 +1000 Subject: [PATCH 1230/1494] drm/ttm: move ttm binding/unbinding out of ttm_tt paths. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move these up to the bo level, moving ttm_tt to just being backing store. Next step is to move the bound flag out. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-6-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/radeon/radeon_mn.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 31 +++++++++++++++++++++- drivers/gpu/drm/ttm/ttm_bo_util.c | 5 ++-- drivers/gpu/drm/ttm/ttm_tt.c | 31 ---------------------- include/drm/ttm/ttm_bo_driver.h | 28 ++++++++++++++++++++ include/drm/ttm/ttm_tt.h | 35 ------------------------- 9 files changed, 64 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 9353e41cf6692..e86f8f6371c4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -552,7 +552,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, goto out_cleanup; /* Bind the memory to the GTT space */ - r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem); + r = ttm_bo_tt_bind(bo, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 1088de50c14ce..aea201d9c5137 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -924,7 +924,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg); + ret = ttm_bo_tt_bind(bo, &tmp_reg); if (ret) goto out; diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index b6293fb910300..eb46d22202365 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -53,7 +53,7 @@ static bool radeon_mn_invalidate(struct mmu_interval_notifier *mn, struct ttm_operation_ctx ctx = { false, false }; long r; - if (!bo->tbo.ttm || !ttm_tt_is_bound(bo->tbo.ttm)) + if (!bo->tbo.ttm || !ttm_bo_tt_is_bound(&bo->tbo)) return true; if (!mmu_notifier_range_blockable(range)) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 2833028982010..c6c1008fefd22 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -238,7 +238,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, goto out_cleanup; } - r = ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem); + r = ttm_bo_tt_bind(bo, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 654384c7aae11..17010e7d0ea97 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -264,7 +264,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, if (ret) goto out_err; - ret = ttm_tt_bind(bdev, bo->ttm, mem); + ret = ttm_bo_tt_bind(bo, mem); if (ret) goto out_err; } @@ -1619,6 +1619,35 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) { if (bo->ttm == NULL) return; + + ttm_bo_tt_unbind(bo); ttm_tt_destroy(bo->bdev, bo->ttm); bo->ttm = NULL; } + +int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem) +{ + int ret; + + if (!bo->ttm) + return -EINVAL; + + if (ttm_bo_tt_is_bound(bo)) + return 0; + + ret = bo->bdev->driver->ttm_tt_bind(bo->bdev, bo->ttm, mem); + if (unlikely(ret != 0)) + return ret; + + ttm_bo_tt_set_bound(bo); + return 0; +} +EXPORT_SYMBOL(ttm_bo_tt_bind); + +void ttm_bo_tt_unbind(struct ttm_buffer_object *bo) +{ + if (ttm_bo_tt_is_bound(bo)) { + bo->bdev->driver->ttm_tt_unbind(bo->bdev, bo->ttm); + ttm_bo_tt_set_unbound(bo); + } +} diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 2ce97760a0892..d6634a5caba24 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -67,7 +67,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, return ret; } - ttm_tt_unbind(bo->bdev, ttm); + ttm_bo_tt_unbind(bo); ttm_bo_free_old_node(bo); old_mem->mem_type = TTM_PL_SYSTEM; } @@ -82,7 +82,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, if (unlikely(ret != 0)) return ret; - ret = ttm_tt_bind(bo->bdev, ttm, new_mem); + ret = ttm_bo_tt_bind(bo, new_mem); if (unlikely(ret != 0)) return ret; } @@ -701,4 +701,3 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) return 0; } - diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 93d65e5e4205a..a4f0296effaca 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -209,8 +209,6 @@ EXPORT_SYMBOL(ttm_tt_set_placement_caching); void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { - ttm_tt_unbind(bdev, ttm); - ttm_tt_unpopulate(bdev, ttm); if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && @@ -303,35 +301,6 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma) } EXPORT_SYMBOL(ttm_dma_tt_fini); -void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) -{ - if (ttm_tt_is_bound(ttm)) { - bdev->driver->ttm_tt_unbind(bdev, ttm); - ttm_tt_set_unbound(ttm); - } -} - -int ttm_tt_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem) -{ - int ret = 0; - - if (!ttm) - return -EINVAL; - - if (ttm_tt_is_bound(ttm)) - return 0; - - ret = bdev->driver->ttm_tt_bind(bdev, ttm, bo_mem); - if (unlikely(ret != 0)) - return ret; - - ttm_tt_set_bound(ttm); - - return 0; -} -EXPORT_SYMBOL(ttm_tt_bind); - int ttm_tt_swapin(struct ttm_tt *ttm) { struct address_space *swap_space; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 70557e2de9be7..d2bea22f35ae0 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -684,6 +684,34 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); */ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); +/** + * ttm_bo_tt_bind + * + * Bind the object tt to a memory resource. + */ +int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem); + +/** + * ttm_bo_tt_bind + * + * Unbind the object tt from a memory resource. + */ +void ttm_bo_tt_unbind(struct ttm_buffer_object *bo); + +static inline bool ttm_bo_tt_is_bound(struct ttm_buffer_object *bo) +{ + return bo->ttm->_state == tt_bound; +} + +static inline void ttm_bo_tt_set_unbound(struct ttm_buffer_object *bo) +{ + bo->ttm->_state = tt_unbound; +} + +static inline void ttm_bo_tt_set_bound(struct ttm_buffer_object *bo) +{ + bo->ttm->_state = tt_bound; +} /** * ttm_bo_tt_destroy. */ diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 8f57d86ee67b5..1ac56730d9524 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -82,11 +82,6 @@ static inline bool ttm_tt_is_populated(struct ttm_tt *tt) return tt->_state != tt_unpopulated; } -static inline bool ttm_tt_is_bound(struct ttm_tt *tt) -{ - return tt->_state == tt_bound; -} - static inline void ttm_tt_set_unpopulated(struct ttm_tt *tt) { tt->_state = tt_unpopulated; @@ -97,16 +92,6 @@ static inline void ttm_tt_set_populated(struct ttm_tt *tt) tt->_state = tt_unbound; } -static inline void ttm_tt_set_unbound(struct ttm_tt *tt) -{ - tt->_state = tt_unbound; -} - -static inline void ttm_tt_set_bound(struct ttm_tt *tt) -{ - tt->_state = tt_bound; -} - /** * struct ttm_dma_tt * @@ -164,17 +149,6 @@ int ttm_sg_tt_init(struct ttm_dma_tt *ttm_dma, struct ttm_buffer_object *bo, void ttm_tt_fini(struct ttm_tt *ttm); void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); -/** - * ttm_ttm_bind: - * - * @ttm: The struct ttm_tt containing backing pages. - * @bo_mem: The struct ttm_resource identifying the binding location. - * - * Bind the pages of @ttm to an aperture location identified by @bo_mem - */ -int ttm_tt_bind(struct ttm_bo_device *bdev, - struct ttm_tt *ttm, struct ttm_resource *bo_mem); - /** * ttm_ttm_destroy: * @@ -184,15 +158,6 @@ int ttm_tt_bind(struct ttm_bo_device *bdev, */ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm); -/** - * ttm_ttm_unbind: - * - * @ttm: The struct ttm_tt. - * - * Unbind a struct ttm_tt. - */ -void ttm_tt_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm); - /** * ttm_tt_swapin: * -- GitLab From 3a4ab168a5df5c9532763ac26cde5c2ad06ca1e5 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:42:30 +1000 Subject: [PATCH 1231/1494] drm/ttm: split bound/populated flags. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move bound up into the bo object, and keep populated with the tt object. The ghost object handling needs to follow the flags at the bo level now instead of it being part of the ttm tt object. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-7-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_util.c | 15 +++++++++++---- include/drm/ttm/ttm_bo_api.h | 1 + include/drm/ttm/ttm_bo_driver.h | 6 +++--- include/drm/ttm/ttm_tt.h | 12 ++++-------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d6634a5caba24..980368049d689 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -572,10 +572,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * bo to be unbound and destroyed. */ - if (man->use_tt) + if (man->use_tt) { ghost_obj->ttm = NULL; - else + ttm_bo_tt_set_unbound(ghost_obj); + } else { bo->ttm = NULL; + ttm_bo_tt_set_unbound(bo); + } dma_resv_unlock(&ghost_obj->base._resv); ttm_bo_put(ghost_obj); @@ -628,10 +631,13 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, * bo to be unbound and destroyed. */ - if (to->use_tt) + if (to->use_tt) { ghost_obj->ttm = NULL; - else + ttm_bo_tt_set_unbound(ghost_obj); + } else { bo->ttm = NULL; + ttm_bo_tt_set_unbound(bo); + } dma_resv_unlock(&ghost_obj->base._resv); ttm_bo_put(ghost_obj); @@ -695,6 +701,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) memset(&bo->mem, 0, sizeof(bo->mem)); bo->mem.mem_type = TTM_PL_SYSTEM; bo->ttm = NULL; + ttm_bo_tt_set_unbound(bo); dma_resv_unlock(&ghost->base._resv); ttm_bo_put(ghost); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 36ff64e2736cd..1d20a7f15a7aa 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -141,6 +141,7 @@ struct ttm_buffer_object { struct ttm_resource mem; struct file *persistent_swap_storage; struct ttm_tt *ttm; + bool ttm_bound; bool evicted; bool deleted; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index d2bea22f35ae0..e66672f703a38 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -700,17 +700,17 @@ void ttm_bo_tt_unbind(struct ttm_buffer_object *bo); static inline bool ttm_bo_tt_is_bound(struct ttm_buffer_object *bo) { - return bo->ttm->_state == tt_bound; + return bo->ttm_bound; } static inline void ttm_bo_tt_set_unbound(struct ttm_buffer_object *bo) { - bo->ttm->_state = tt_unbound; + bo->ttm_bound = false; } static inline void ttm_bo_tt_set_bound(struct ttm_buffer_object *bo) { - bo->ttm->_state = tt_bound; + bo->ttm_bound = true; } /** * ttm_bo_tt_destroy. diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 1ac56730d9524..94e16238c93d9 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -70,26 +70,22 @@ struct ttm_tt { struct sg_table *sg; /* for SG objects via dma-buf */ struct file *swap_storage; enum ttm_caching_state caching_state; - enum { - tt_bound, - tt_unbound, - tt_unpopulated, - } _state; + bool populated; }; static inline bool ttm_tt_is_populated(struct ttm_tt *tt) { - return tt->_state != tt_unpopulated; + return tt->populated; } static inline void ttm_tt_set_unpopulated(struct ttm_tt *tt) { - tt->_state = tt_unpopulated; + tt->populated = false; } static inline void ttm_tt_set_populated(struct ttm_tt *tt) { - tt->_state = tt_unbound; + tt->populated = true; } /** -- GitLab From 3312be8f6fc8a8dc7cef01986dbd436eab7af0f7 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Tue, 15 Sep 2020 11:47:19 +1000 Subject: [PATCH 1232/1494] drm/ttm: move populated state into page flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just use the top bit of page flags to store the populated state. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915024007.67163-8-airlied@gmail.com --- include/drm/ttm/ttm_tt.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 94e16238c93d9..c777b72063db4 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -42,6 +42,8 @@ struct ttm_operation_ctx; #define TTM_PAGE_FLAG_SG (1 << 8) #define TTM_PAGE_FLAG_NO_RETRY (1 << 9) +#define TTM_PAGE_FLAG_PRIV_POPULATED (1 << 31) + enum ttm_caching_state { tt_uncached, tt_wc, @@ -70,22 +72,21 @@ struct ttm_tt { struct sg_table *sg; /* for SG objects via dma-buf */ struct file *swap_storage; enum ttm_caching_state caching_state; - bool populated; }; static inline bool ttm_tt_is_populated(struct ttm_tt *tt) { - return tt->populated; + return tt->page_flags & TTM_PAGE_FLAG_PRIV_POPULATED; } static inline void ttm_tt_set_unpopulated(struct ttm_tt *tt) { - tt->populated = false; + tt->page_flags &= ~TTM_PAGE_FLAG_PRIV_POPULATED; } static inline void ttm_tt_set_populated(struct ttm_tt *tt) { - tt->populated = true; + tt->page_flags |= TTM_PAGE_FLAG_PRIV_POPULATED; } /** -- GitLab From dd425545a8cc57ae99515e771e87a4465e2f43dc Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Fri, 11 Sep 2020 16:09:37 +0800 Subject: [PATCH 1233/1494] drm/vc4: Handing the return value of drm_universal_plane_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handing the return value of drm_universal_plane_init to fix the following W=1 kernel build warning(s): vc4_plane.c: In function ‘vc4_plane_init’: vc4_plane.c:1340:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/1599811777-34093-1-git-send-email-tiantao6@hisilicon.com --- drivers/gpu/drm/vc4/vc4_plane.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 89543fa8ca4de..6b39cc2ca18d0 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1361,6 +1361,8 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, &vc4_plane_funcs, formats, ARRAY_SIZE(formats), modifiers, type, NULL); + if (ret) + return ERR_PTR(ret); drm_plane_helper_add(plane, &vc4_plane_helper_funcs); -- GitLab From d5a0c816900419105a12e7471bf074319dfa34be Mon Sep 17 00:00:00 2001 From: Stefan Agner <stefan@agner.ch> Date: Tue, 8 Sep 2020 16:16:54 +0200 Subject: [PATCH 1234/1494] drm: mxsfb: check framebuffer pitch The lcdif IP does not support a framebuffer pitch (stride) other than framebuffer width. Check for equality and reject the framebuffer otherwise. This prevents a distorted picture when using 640x800 and running the Mesa graphics stack. Mesa tries to use a cache aligned stride, which leads at that particular resolution to width != stride. Currently Mesa has no fallback behavior, but rejecting this configuration allows userspace to handle the issue correctly. Fixes: 45d59d704080 ("drm: Add new driver for MXSFB controller") Signed-off-by: Stefan Agner <stefan@agner.ch> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200908141654.266836-1-stefan@agner.ch --- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 8c549c3931afa..35122aef037b4 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -21,6 +21,7 @@ #include <drm/drm_connector.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_irq.h> @@ -81,8 +82,26 @@ void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb) clk_disable_unprepare(mxsfb->clk_axi); } +static struct drm_framebuffer * +mxsfb_fb_create(struct drm_device *dev, struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + const struct drm_format_info *info; + + info = drm_get_format_info(dev, mode_cmd); + if (!info) + return ERR_PTR(-EINVAL); + + if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) { + dev_dbg(dev->dev, "Invalid pitch: fb width must match pitch\n"); + return ERR_PTR(-EINVAL); + } + + return drm_gem_fb_create(dev, file_priv, mode_cmd); +} + static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = { - .fb_create = drm_gem_fb_create, + .fb_create = mxsfb_fb_create, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, }; -- GitLab From 2e96af20c618a5112a19cfc64ec0eb522084df38 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Tue, 15 Sep 2020 09:17:08 +0200 Subject: [PATCH 1235/1494] MAINTAINERS: Add Thomas as reviewer for ast, mgag200 and udl I'm adding myself as reviewer for ast, mgag200 and udl. I've already been keeping these drivers in shape for a while. While at it I'm also setting the list and tree for ast and mgag200, and update each driver's status to Supported. Working on these drivers is part of my job. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915071708.4743-1-tzimmermann@suse.de --- MAINTAINERS | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c4e8bd1ab7616..2aba71a6706df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5419,7 +5419,10 @@ F: drivers/gpu/drm/aspeed/ DRM DRIVER FOR AST SERVER GRAPHICS CHIPS M: Dave Airlie <airlied@redhat.com> -S: Odd Fixes +R: Thomas Zimmermann <tzimmermann@suse.de> +L: dri-devel@lists.freedesktop.org +S: Supported +T: git git://anongit.freedesktop.org/drm/drm-misc F: drivers/gpu/drm/ast/ DRM DRIVER FOR BOCHS VIRTUAL GPU @@ -5507,7 +5510,10 @@ F: include/uapi/drm/mga_drm.h DRM DRIVER FOR MGA G200 GRAPHICS CHIPS M: Dave Airlie <airlied@redhat.com> -S: Odd Fixes +R: Thomas Zimmermann <tzimmermann@suse.de> +L: dri-devel@lists.freedesktop.org +S: Supported +T: git git://anongit.freedesktop.org/drm/drm-misc F: drivers/gpu/drm/mgag200/ DRM DRIVER FOR MI0283QT @@ -5652,8 +5658,9 @@ F: drivers/gpu/drm/panel/panel-tpo-tpg110.c DRM DRIVER FOR USB DISPLAYLINK VIDEO ADAPTERS M: Dave Airlie <airlied@redhat.com> R: Sean Paul <sean@poorly.run> +R: Thomas Zimmermann <tzimmermann@suse.de> L: dri-devel@lists.freedesktop.org -S: Odd Fixes +S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc F: drivers/gpu/drm/udl/ -- GitLab From 5638c82cdabd95c8e82672760a9799c2f2848ba9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 14 Sep 2020 09:22:33 +0200 Subject: [PATCH 1236/1494] drm/ast: Set format registers in primary plane's update The atomic modesetting code tried to distinguish format changes from full modesetting operations. But the implementation was buggy and the format registers were often updated even for simple pageflips. Fix this problem by handling format changes in the primary plane's update function. v3: * program format in primary plane's update function Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200914072236.19398-2-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 62fe682a7de63..2323fe0b71bde 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -562,13 +562,24 @@ ast_primary_plane_helper_atomic_update(struct drm_plane *plane, struct drm_plane_state *state = plane->state; struct drm_gem_vram_object *gbo; s64 gpu_addr; + struct drm_framebuffer *fb = state->fb; + struct drm_framebuffer *old_fb = old_state->fb; + + if (!old_fb || (fb->format != old_fb->format)) { + struct drm_crtc_state *crtc_state = state->crtc->state; + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); + struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info; + + ast_set_color_reg(ast, fb->format); + ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info); + } - gbo = drm_gem_vram_of_gem(state->fb->obj[0]); + gbo = drm_gem_vram_of_gem(fb->obj[0]); gpu_addr = drm_gem_vram_offset(gbo); if (drm_WARN_ON_ONCE(dev, gpu_addr < 0)) return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */ - ast_set_offset_reg(ast, state->fb); + ast_set_offset_reg(ast, fb); ast_set_start_address_crt1(ast, (u32)gpu_addr); ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00); @@ -733,6 +744,7 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { + struct drm_device *dev = crtc->dev; struct ast_crtc_state *ast_state; const struct drm_format_info *format; bool succ; @@ -743,8 +755,8 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, ast_state = to_ast_crtc_state(state); format = ast_state->format; - if (!format) - return 0; + if (drm_WARN_ON_ONCE(dev, !format)) + return -EINVAL; /* BUG: We didn't set format in primary check(). */ succ = ast_get_vbios_mode_info(format, &state->mode, &state->adjusted_mode, @@ -768,27 +780,15 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); - struct ast_crtc_state *ast_state; - const struct drm_format_info *format; - struct ast_vbios_mode_info *vbios_mode_info; - struct drm_display_mode *adjusted_mode; + struct drm_crtc_state *crtc_state = crtc->state; + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state); + struct ast_vbios_mode_info *vbios_mode_info = + &ast_crtc_state->vbios_mode_info; + struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; - ast_state = to_ast_crtc_state(crtc->state); - - format = ast_state->format; - if (!format) - return; - - vbios_mode_info = &ast_state->vbios_mode_info; - - ast_set_color_reg(ast, format); - ast_set_vbios_color_reg(ast, format, vbios_mode_info); - - if (!crtc->state->mode_changed) + if (!drm_atomic_crtc_needs_modeset(crtc_state)) return; - adjusted_mode = &crtc->state->adjusted_mode; - ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); -- GitLab From 39edb28780e8bf623565fbd2fd0ea091f315ceb3 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 14 Sep 2020 09:22:34 +0200 Subject: [PATCH 1237/1494] drm/ast: Disable planes while switching display modes The ast HW cursor requires the primary plane and CRTC to display at a valid mode and format. This is not the case while switching display modes, which can lead to the screen turing permanently dark. As a workaround, the ast driver now disables active planes while the mode or format switch takes place. It also synchronizes with the vertical refresh to give CRTC and planes some time to catch up on each other. The active planes planes (primary or cursor) will be re-enabled by each plane's atomic_update() function. v3: * move the logic into the CRTC's atomic_disable function v2: * move the logic into the commit-tail function Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200914072236.19398-3-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_drv.h | 2 ++ drivers/gpu/drm/ast/ast_mode.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index c1af6b7259339..467049ca8430a 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -177,6 +177,8 @@ struct ast_private *ast_device_create(struct drm_driver *drv, #define AST_IO_MM_OFFSET (0x380) +#define AST_IO_VGAIR1_VREFRESH BIT(3) + #define __ast_read(x) \ static inline u##x ast_read##x(struct ast_private *ast, u32 reg) { \ u##x val = 0;\ diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 2323fe0b71bde..5b45b57c3d172 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -514,6 +514,16 @@ static void ast_set_start_address_crt1(struct ast_private *ast, } +static void ast_wait_for_vretrace(struct ast_private *ast) +{ + unsigned long timeout = jiffies + HZ; + u8 vgair1; + + do { + vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ); + } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout)); +} + /* * Primary plane */ @@ -809,7 +819,28 @@ static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct drm_device *dev = crtc->dev; + struct ast_private *ast = to_ast_private(dev); + ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + + /* + * HW cursors require the underlying primary plane and CRTC to + * display a valid mode and image. This is not the case during + * full modeset operations. So we temporarily disable any active + * plane, including the HW cursor. Each plane's atomic_update() + * helper will re-enable it if necessary. + * + * We only do this during *full* modesets. It does not affect + * simple pageflips on the planes. + */ + drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); + + /* + * Ensure that no scanout takes place before reprogramming mode + * and format registers. + */ + ast_wait_for_vretrace(ast); } static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { -- GitLab From f3901b5fee41e0410ad22133926e3f328174ab20 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 14 Sep 2020 09:22:35 +0200 Subject: [PATCH 1238/1494] drm/ast: Program display mode in CRTC's atomic_enable() This change simplifies ast's modesetting code. The display mode is now programmed from within the CRTC's atomic_enable(), which only runs if we actually want to program the mode. Corresponding code in atomic_flush() is being removed. Also removed is atomic_begin(), which serves no purpose at all. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200914072236.19398-4-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 5b45b57c3d172..fd0127f48fb9b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -777,16 +777,9 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, return 0; } -static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ - struct ast_private *ast = to_ast_private(crtc->dev); - - ast_open_key(ast); -} - -static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) +static void +ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); @@ -796,9 +789,6 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, &ast_crtc_state->vbios_mode_info; struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; - if (!drm_atomic_crtc_needs_modeset(crtc_state)) - return; - ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info); ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06); ast_set_std_reg(ast, adjusted_mode, vbios_mode_info); @@ -806,12 +796,7 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info); ast_set_crtthd_reg(ast); ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info); -} -static void -ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) -{ ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON); } @@ -845,8 +830,6 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .atomic_check = ast_crtc_helper_atomic_check, - .atomic_begin = ast_crtc_helper_atomic_begin, - .atomic_flush = ast_crtc_helper_atomic_flush, .atomic_enable = ast_crtc_helper_atomic_enable, .atomic_disable = ast_crtc_helper_atomic_disable, }; -- GitLab From 2f0ddd89fe32f1534a17ca44ebccc939f8a74af4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann <tzimmermann@suse.de> Date: Mon, 14 Sep 2020 09:22:36 +0200 Subject: [PATCH 1239/1494] drm/ast: Enable CRTC before planes An active cursor plane requires a valid display mode. Change the commit_tail callback, so that it sets up the CRTC's mode before updating planes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200914072236.19398-5-tzimmermann@suse.de --- drivers/gpu/drm/ast/ast_mode.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index fd0127f48fb9b..834a156e3a750 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1068,6 +1068,11 @@ static int ast_connector_init(struct drm_device *dev) * Mode config */ +static const struct drm_mode_config_helper_funcs +ast_mode_config_helper_funcs = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +}; + static const struct drm_mode_config_funcs ast_mode_config_funcs = { .fb_create = drm_gem_fb_create, .mode_valid = drm_vram_helper_mode_valid, @@ -1107,6 +1112,8 @@ int ast_mode_config_init(struct ast_private *ast) dev->mode_config.max_height = 1200; } + dev->mode_config.helper_private = &ast_mode_config_helper_funcs; + memset(&ast->primary_plane, 0, sizeof(ast->primary_plane)); ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01, &ast_primary_plane_funcs, -- GitLab From b79ffa914ede785a721f42d8ee3ce7b8eeede2bb Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 16 Sep 2020 11:50:21 +0100 Subject: [PATCH 1240/1494] drm/i915: Initialise outparam for error return from wait_for_register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just in case the caller passes in 0 for both slow&fast timeouts, make sure we initialise the stack value returned. Add an assert so that we don't make the mistake of passing 0 timeouts for the wait. drivers/gpu/drm/i915/intel_uncore.c:2011 __intel_wait_for_register_fw() error: uninitialized symbol 'reg_value'. References: 3f649ab728cd ("treewide: Remove uninitialized_var() usage") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916105022.28316-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_uncore.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 8d5a933e6af60..263ffcb832b79 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1993,13 +1993,14 @@ int __intel_wait_for_register_fw(struct intel_uncore *uncore, unsigned int slow_timeout_ms, u32 *out_value) { - u32 reg_value; + u32 reg_value = 0; #define done (((reg_value = intel_uncore_read_fw(uncore, reg)) & mask) == value) int ret; /* Catch any overuse of this function */ might_sleep_if(slow_timeout_ms); GEM_BUG_ON(fast_timeout_us > 20000); + GEM_BUG_ON(!fast_timeout_us && !slow_timeout_ms); ret = -ETIMEDOUT; if (fast_timeout_us && fast_timeout_us <= 20000) -- GitLab From 9f9f4101fc98db56714e71676d5a1e2d27e01f7e Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 16 Sep 2020 11:50:22 +0100 Subject: [PATCH 1241/1494] drm/i915/selftests: Push the fake iommu device from the stack to data Since we store a pointer to the fake iommu device that is allocated on the stack, as soon as we leave the function it goes out of scope and any future dereference is undefined behaviour. Just in case we may need to look at the fake iommu device after initialiation, move the allocation from the stack into the data. Fixes: 01b9d4e21148 ("iommu/vt-d: Use dev_iommu_priv_get/set()") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916105022.28316-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index f127e633f7ca8..397c313a8b692 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -118,11 +118,11 @@ static struct dev_pm_domain pm_domain = { struct drm_i915_private *mock_gem_device(void) { - struct drm_i915_private *i915; - struct pci_dev *pdev; #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) - struct dev_iommu iommu; + static struct dev_iommu fake_iommu = { .priv = (void *)-1 }; #endif + struct drm_i915_private *i915; + struct pci_dev *pdev; int err; pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); @@ -141,10 +141,8 @@ struct drm_i915_private *mock_gem_device(void) dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) - /* HACK HACK HACK to disable iommu for the fake device; force identity mapping */ - memset(&iommu, 0, sizeof(iommu)); - iommu.priv = (void *)-1; - pdev->dev.iommu = &iommu; + /* HACK to disable iommu for the fake device; force identity mapping */ + pdev->dev.iommu = &fake_iommu; #endif pci_set_drvdata(pdev, i915); -- GitLab From 36183150e086977cadcffba84ecd84cbbeec9324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Tue, 15 Sep 2020 16:29:26 +0200 Subject: [PATCH 1242/1494] drm/ttm: some cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unexport ttm_check_under_lowerlimit. Make ttm_bo_acc_size static and unexport it. Remove ttm_get_kernel_zone_memory_size. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/390515/ --- drivers/gpu/drm/ttm/ttm_bo.c | 7 +++---- drivers/gpu/drm/ttm/ttm_memory.c | 7 ------- include/drm/ttm/ttm_bo_api.h | 12 ------------ include/drm/ttm/ttm_memory.h | 1 - 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 17010e7d0ea97..92d60585deb18 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1255,9 +1255,9 @@ int ttm_bo_init(struct ttm_bo_device *bdev, } EXPORT_SYMBOL(ttm_bo_init); -size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, - unsigned long bo_size, - unsigned struct_size) +static size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, + unsigned long bo_size, + unsigned struct_size) { unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT; size_t size = 0; @@ -1267,7 +1267,6 @@ size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, size += ttm_round_pot(sizeof(struct ttm_tt)); return size; } -EXPORT_SYMBOL(ttm_bo_acc_size); size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev, unsigned long bo_size, diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index acd63b70d8147..987aa32c48086 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -554,7 +554,6 @@ ttm_check_under_lowerlimit(struct ttm_mem_global *glob, return false; } -EXPORT_SYMBOL(ttm_check_under_lowerlimit); static int ttm_mem_global_reserve(struct ttm_mem_global *glob, struct ttm_mem_zone *single_zone, @@ -682,9 +681,3 @@ size_t ttm_round_pot(size_t size) return 0; } EXPORT_SYMBOL(ttm_round_pot); - -uint64_t ttm_get_kernel_zone_memory_size(struct ttm_mem_global *glob) -{ - return glob->zone_kernel->max_mem; -} -EXPORT_SYMBOL(ttm_get_kernel_zone_memory_size); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 1d20a7f15a7aa..89ad6f213fc0d 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -353,18 +353,6 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched); bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place); -/** - * ttm_bo_acc_size - * - * @bdev: Pointer to a ttm_bo_device struct. - * @bo_size: size of the buffer object in byte. - * @struct_size: size of the structure holding buffer object datas - * - * Returns size to account for a buffer object - */ -size_t ttm_bo_acc_size(struct ttm_bo_device *bdev, - unsigned long bo_size, - unsigned struct_size); size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev, unsigned long bo_size, unsigned struct_size); diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h index c78ea99c42cf3..2d468d7c94e66 100644 --- a/include/drm/ttm/ttm_memory.h +++ b/include/drm/ttm/ttm_memory.h @@ -91,7 +91,6 @@ extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, extern void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page, uint64_t size); extern size_t ttm_round_pot(size_t size); -extern uint64_t ttm_get_kernel_zone_memory_size(struct ttm_mem_global *glob); extern bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, uint64_t num_pages, struct ttm_operation_ctx *ctx); #endif -- GitLab From 2340dc15f05f595688ae10f6512cef5ad51476d3 Mon Sep 17 00:00:00 2001 From: Thierry Reding <treding@nvidia.com> Date: Wed, 8 Apr 2020 20:01:00 +0200 Subject: [PATCH 1243/1494] drm/tegra: Properly reference count the DDC I2C adapter Use the of_get_i2c_adapter_by_node(), which is similar to the existing call to of_find_i2c_adapter_by_node() except that it also takes a reference to the owner module of the I2C adapter. In order to properly balance this out, call i2c_put_adapter() to release the reference to the I2C adapter and its owner module. For the special case where the DDC comes from the DPAUX, care must be taken to perform the same steps (i.e. get_device() and module_get()) so that the reference counts are all balanced. Signed-off-by: Thierry Reding <treding@nvidia.com> --- drivers/gpu/drm/tegra/output.c | 4 ++-- drivers/gpu/drm/tegra/sor.c | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index e36e5e7c2f694..03382550f7d96 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -112,7 +112,7 @@ int tegra_output_probe(struct tegra_output *output) ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); if (ddc) { - output->ddc = of_find_i2c_adapter_by_node(ddc); + output->ddc = of_get_i2c_adapter_by_node(ddc); if (!output->ddc) { err = -EPROBE_DEFER; of_node_put(ddc); @@ -173,7 +173,7 @@ void tegra_output_remove(struct tegra_output *output) free_irq(output->hpd_irq, output); if (output->ddc) - put_device(&output->ddc->dev); + i2c_put_adapter(output->ddc); } int tegra_output_init(struct drm_device *drm, struct tegra_output *output) diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 45b5258c77a29..e88a17c2937f2 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -3728,7 +3728,12 @@ static int tegra_sor_probe(struct platform_device *pdev) if (!sor->aux) return -EPROBE_DEFER; - sor->output.ddc = &sor->aux->ddc; + if (get_device(&sor->aux->ddc.dev)) { + if (try_module_get(sor->aux->ddc.owner)) + sor->output.ddc = &sor->aux->ddc; + else + put_device(&sor->aux->ddc.dev); + } } if (!sor->aux) { -- GitLab From 3d2e7aec70130af53289eccd41696c15ce2c3e89 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 01:06:53 +0300 Subject: [PATCH 1244/1494] drm/tegra: output: Don't leak OF node on error The OF node should be put before returning error in tegra_output_probe(), otherwise node's refcount will be leaked. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com> --- drivers/gpu/drm/tegra/output.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 03382550f7d96..f050c8bac398d 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -102,10 +102,10 @@ int tegra_output_probe(struct tegra_output *output) panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); if (panel) { output->panel = of_drm_find_panel(panel); + of_node_put(panel); + if (IS_ERR(output->panel)) return PTR_ERR(output->panel); - - of_node_put(panel); } output->edid = of_get_property(output->of_node, "nvidia,edid", &size); @@ -113,13 +113,13 @@ int tegra_output_probe(struct tegra_output *output) ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); if (ddc) { output->ddc = of_get_i2c_adapter_by_node(ddc); + of_node_put(ddc); + if (!output->ddc) { err = -EPROBE_DEFER; of_node_put(ddc); return err; } - - of_node_put(ddc); } output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev, -- GitLab From f00b9dd579d0078123e33434c25f37d42747574d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 01:06:54 +0300 Subject: [PATCH 1245/1494] drm/tegra: output: Support DRM bridges Newer Tegra device-trees will specify a video output graph which involves a bridge. This patch adds initial support for the DRM bridges to the Tegra DRM output. Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com> --- drivers/gpu/drm/tegra/drm.h | 2 ++ drivers/gpu/drm/tegra/output.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index b25443255be6b..f38de08e0c951 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -12,6 +12,7 @@ #include <linux/gpio/consumer.h> #include <drm/drm_atomic.h> +#include <drm/drm_bridge.h> #include <drm/drm_edid.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> @@ -116,6 +117,7 @@ struct tegra_output { struct device_node *of_node; struct device *dev; + struct drm_bridge *bridge; struct drm_panel *panel; struct i2c_adapter *ddc; const struct edid *edid; diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index f050c8bac398d..925a9199a7106 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -5,6 +5,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_simple_kms_helper.h> @@ -99,8 +100,19 @@ int tegra_output_probe(struct tegra_output *output) if (!output->of_node) output->of_node = output->dev->of_node; + err = drm_of_find_panel_or_bridge(output->of_node, -1, -1, + &output->panel, &output->bridge); + if (err && err != -ENODEV) + return err; + panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); if (panel) { + /* + * Don't mix nvidia,panel phandle with the graph in a + * device-tree. + */ + WARN_ON(output->panel || output->bridge); + output->panel = of_drm_find_panel(panel); of_node_put(panel); -- GitLab From 29efdc2902027e6cc19f665441a3de87a674282a Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 01:06:55 +0300 Subject: [PATCH 1246/1494] drm/tegra: output: rgb: Support LVDS encoder bridge Newer Tegra device-trees will specify a video output graph, which involves LVDS encoder bridge. This patch adds support for the LVDS encoder bridge to the RGB output, allowing us to model the display hardware properly. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com> --- drivers/gpu/drm/tegra/rgb.c | 58 +++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 0562a7eb793f3..9a7024ec96bc3 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -7,6 +7,7 @@ #include <linux/clk.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_bridge_connector.h> #include <drm/drm_panel.h> #include <drm/drm_simple_kms_helper.h> @@ -267,24 +268,63 @@ int tegra_dc_rgb_remove(struct tegra_dc *dc) int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) { struct tegra_output *output = dc->rgb; + struct drm_connector *connector; int err; if (!dc->rgb) return -ENODEV; - drm_connector_init(drm, &output->connector, &tegra_rgb_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - drm_connector_helper_add(&output->connector, - &tegra_rgb_connector_helper_funcs); - output->connector.dpms = DRM_MODE_DPMS_OFF; - drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS); drm_encoder_helper_add(&output->encoder, &tegra_rgb_encoder_helper_funcs); - drm_connector_attach_encoder(&output->connector, - &output->encoder); - drm_connector_register(&output->connector); + /* + * Tegra devices that have LVDS panel utilize LVDS encoder bridge + * for converting up to 28 LCD LVTTL lanes into 5/4 LVDS lanes that + * go to display panel's receiver. + * + * Encoder usually have a power-down control which needs to be enabled + * in order to transmit data to the panel. Historically devices that + * use an older device-tree version didn't model the bridge, assuming + * that encoder is turned ON by default, while today's DRM allows us + * to model LVDS encoder properly. + * + * Newer device-trees utilize LVDS encoder bridge, which provides + * us with a connector and handles the display panel. + * + * For older device-trees we fall back to our own connector and use + * nvidia,panel phandle. + */ + if (output->bridge) { + err = drm_bridge_attach(&output->encoder, output->bridge, + NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (err) { + dev_err(output->dev, "failed to attach bridge: %d\n", + err); + return err; + } + + connector = drm_bridge_connector_init(drm, &output->encoder); + if (IS_ERR(connector)) { + dev_err(output->dev, + "failed to initialize bridge connector: %pe\n", + connector); + return PTR_ERR(connector); + } + + drm_connector_attach_encoder(connector, &output->encoder); + } else { + drm_connector_init(drm, &output->connector, + &tegra_rgb_connector_funcs, + DRM_MODE_CONNECTOR_LVDS); + drm_connector_helper_add(&output->connector, + &tegra_rgb_connector_helper_funcs); + output->connector.dpms = DRM_MODE_DPMS_OFF; + + drm_connector_attach_encoder(&output->connector, + &output->encoder); + drm_connector_register(&output->connector); + } err = tegra_output_init(drm, output); if (err < 0) { -- GitLab From d9f980ebcd01d90a2a76ea2383c925abf9223cab Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko <digetx@gmail.com> Date: Fri, 14 Aug 2020 01:06:56 +0300 Subject: [PATCH 1247/1494] drm/tegra: output: rgb: Wrap directly-connected panel into DRM bridge Currently Tegra DRM driver manually manages display panel, but this management could be moved out into DRM core if we'll wrap panel into DRM bridge. This patch wraps RGB panel into a DRM bridge and removes manual handling of the panel from the RGB output code. Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Signed-off-by: Thierry Reding <treding@nvidia.com> --- drivers/gpu/drm/tegra/rgb.c | 70 ++++++++++--------------------------- 1 file changed, 18 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c index 9a7024ec96bc3..4142a56ca7644 100644 --- a/drivers/gpu/drm/tegra/rgb.c +++ b/drivers/gpu/drm/tegra/rgb.c @@ -8,7 +8,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge_connector.h> -#include <drm/drm_panel.h> #include <drm/drm_simple_kms_helper.h> #include "drm.h" @@ -86,45 +85,13 @@ static void tegra_dc_write_regs(struct tegra_dc *dc, tegra_dc_writel(dc, table[i].value, table[i].offset); } -static const struct drm_connector_funcs tegra_rgb_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .detect = tegra_output_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = tegra_output_connector_destroy, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static enum drm_mode_status -tegra_rgb_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - /* - * FIXME: For now, always assume that the mode is okay. There are - * unresolved issues with clk_round_rate(), which doesn't always - * reliably report whether a frequency can be set or not. - */ - return MODE_OK; -} - -static const struct drm_connector_helper_funcs tegra_rgb_connector_helper_funcs = { - .get_modes = tegra_output_connector_get_modes, - .mode_valid = tegra_rgb_connector_mode_valid, -}; - static void tegra_rgb_encoder_disable(struct drm_encoder *encoder) { struct tegra_output *output = encoder_to_output(encoder); struct tegra_rgb *rgb = to_rgb(output); - if (output->panel) - drm_panel_disable(output->panel); - tegra_dc_write_regs(rgb->dc, rgb_disable, ARRAY_SIZE(rgb_disable)); tegra_dc_commit(rgb->dc); - - if (output->panel) - drm_panel_unprepare(output->panel); } static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) @@ -133,9 +100,6 @@ static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) struct tegra_rgb *rgb = to_rgb(output); u32 value; - if (output->panel) - drm_panel_prepare(output->panel); - tegra_dc_write_regs(rgb->dc, rgb_enable, ARRAY_SIZE(rgb_enable)); value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL; @@ -157,9 +121,6 @@ static void tegra_rgb_encoder_enable(struct drm_encoder *encoder) tegra_dc_writel(rgb->dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS); tegra_dc_commit(rgb->dc); - - if (output->panel) - drm_panel_enable(output->panel); } static int @@ -278,6 +239,23 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) drm_encoder_helper_add(&output->encoder, &tegra_rgb_encoder_helper_funcs); + /* + * Wrap directly-connected panel into DRM bridge in order to let + * DRM core to handle panel for us. + */ + if (output->panel) { + output->bridge = devm_drm_panel_bridge_add(output->dev, + output->panel); + if (IS_ERR(output->bridge)) { + dev_err(output->dev, + "failed to wrap panel into bridge: %pe\n", + output->bridge); + return PTR_ERR(output->bridge); + } + + output->panel = NULL; + } + /* * Tegra devices that have LVDS panel utilize LVDS encoder bridge * for converting up to 28 LCD LVTTL lanes into 5/4 LVDS lanes that @@ -292,8 +270,7 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) * Newer device-trees utilize LVDS encoder bridge, which provides * us with a connector and handles the display panel. * - * For older device-trees we fall back to our own connector and use - * nvidia,panel phandle. + * For older device-trees we wrapped panel into the panel-bridge. */ if (output->bridge) { err = drm_bridge_attach(&output->encoder, output->bridge, @@ -313,17 +290,6 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc) } drm_connector_attach_encoder(connector, &output->encoder); - } else { - drm_connector_init(drm, &output->connector, - &tegra_rgb_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - drm_connector_helper_add(&output->connector, - &tegra_rgb_connector_helper_funcs); - output->connector.dpms = DRM_MODE_DPMS_OFF; - - drm_connector_attach_encoder(&output->connector, - &output->encoder); - drm_connector_register(&output->connector); } err = tegra_output_init(drm, output); -- GitLab From b731e4ea1054f41115b0968038c2b118c7e7e5be Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn <lukas.bulwahn@gmail.com> Date: Sat, 12 Sep 2020 20:33:34 +0200 Subject: [PATCH 1248/1494] MAINTAINERS: make linux-aspeed list remarks consistent Commit f15a3ea80391 ("MAINTAINERS: Add ASPEED BMC GFX DRM driver entry") does not mention that linux-aspeed@lists.ozlabs.org is moderated for non-subscribers, but the other three entries for linux-aspeed@lists.ozlabs.org do. By 'majority vote' among entries, let us assume it was just missed here and adjust it to be consistent with others. Signed-off-by: Lukas Bulwahn <lukas.bulwahn@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200912183334.22683-1-lukas.bulwahn@gmail.com --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2aba71a6706df..10992f6541bd1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5411,7 +5411,7 @@ F: drivers/gpu/drm/panel/panel-arm-versatile.c DRM DRIVER FOR ASPEED BMC GFX M: Joel Stanley <joel@jms.id.au> -L: linux-aspeed@lists.ozlabs.org +L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers) S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/gpu/aspeed-gfx.txt -- GitLab From e5e1065f922380ced35e6b6ec3c58c28f57b74fd Mon Sep 17 00:00:00 2001 From: Wang Qing <wangqing@vivo.com> Date: Thu, 17 Sep 2020 10:04:32 +0800 Subject: [PATCH 1249/1494] drm: fix spelling error in comments Change the comment typo: "manger" -> "manager". Signed-off-by: Wang Qing <wangqing@vivo.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/1600308275-32094-1-git-send-email-wangqing@vivo.com --- include/drm/drm_mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index a01bc6fac83ce..9b4292f229c67 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -338,7 +338,7 @@ static inline u64 drm_mm_hole_node_end(const struct drm_mm_node *hole_node) /** * drm_mm_nodes - list of nodes under the drm_mm range manager - * @mm: the struct drm_mm range manger + * @mm: the struct drm_mm range manager * * As the drm_mm range manager hides its node_list deep with its * structure, extracting it looks painful and repetitive. This is -- GitLab From 7dd1b884f777beee4c0f3471a327697005118db8 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Tue, 28 Jul 2020 15:58:39 +0200 Subject: [PATCH 1250/1494] dma-resv: lockdep-prime address_space->i_mmap_rwsem for dma-resv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPU drivers need this in their shrinkers, to be able to throw out mmap'ed buffers. Note that we also need dma_resv_lock in shrinkers, but that loop is resolved by trylocking in shrinkers. So full hierarchy is now (ignore some of the other branches we already have primed): mmap_read_lock -> dma_resv -> shrinkers -> i_mmap_lock_write I hope that's not inconsistent with anything mm or fs does, adding relevant people. Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: Sumit Semwal <sumit.semwal@linaro.org> Cc: "Christian König" <christian.koenig@amd.com> Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Cc: Dave Chinner <david@fromorbit.com> Cc: Qian Cai <cai@lca.pw> Cc: linux-xfs@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: Thomas Hellström (Intel) <thomas_os@shipmail.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jason Gunthorpe <jgg@mellanox.com> Cc: linux-mm@kvack.org Cc: linux-rdma@vger.kernel.org Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200728135839.1035515-1-daniel.vetter@ffwll.ch --- drivers/dma-buf/dma-resv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 434a3314fb0ed..1c8f2581cb09a 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -98,12 +98,14 @@ static int __init dma_resv_lockdep(void) struct mm_struct *mm = mm_alloc(); struct ww_acquire_ctx ctx; struct dma_resv obj; + struct address_space mapping; int ret; if (!mm) return -ENOMEM; dma_resv_init(&obj); + address_space_init_once(&mapping); mmap_read_lock(mm); ww_acquire_init(&ctx, &reservation_ww_class); @@ -111,6 +113,9 @@ static int __init dma_resv_lockdep(void) if (ret == -EDEADLK) dma_resv_lock_slow(&obj, &ctx); fs_reclaim_acquire(GFP_KERNEL); + /* for unmap_mapping_range on trylocked buffer objects in shrinkers */ + i_mmap_lock_write(&mapping); + i_mmap_unlock_write(&mapping); #ifdef CONFIG_MMU_NOTIFIER lock_map_acquire(&__mmu_notifier_invalidate_range_start_map); __dma_fence_might_wait(); -- GitLab From 637f7240f602c078070cd2373845b7a80b59ae3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:37 +0300 Subject: [PATCH 1251/1494] drm/dp: Dump downstream facing port caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It helps when the logs have a dump of the DFP capabilities. v2: Move the dumping to the new helper Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-2-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 1e7c638873c82..c21bbfc3d7147 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -545,8 +545,13 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux, ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len); if (ret < 0) return ret; + if (ret != len) + return -EIO; + + DRM_DEBUG_KMS("%s: DPCD DFP: %*ph\n", + aux->name, len, downstream_ports); - return ret == len ? 0 : -EIO; + return 0; } EXPORT_SYMBOL(drm_dp_read_downstream_info); -- GitLab From f7af425dce9d572ad421b14dd94642457da40ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:38 +0300 Subject: [PATCH 1252/1494] drm/i915/lspcon: Do not send infoframes to non-HDMI sinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Non-HDMI sinks shouldn't be sent infoframes. Check for that when using LSPCON. FIXME: How do we turn off infoframes once enabled? Do we even have to? Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-3-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_ddi.c | 10 ++++------ drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index a73534d0a6423..1eb9191e49dd2 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3581,19 +3581,17 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state, intel_ddi_pre_enable_hdmi(state, encoder, crtc_state, conn_state); } else { - struct intel_lspcon *lspcon = - enc_to_intel_lspcon(encoder); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); intel_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); - if (lspcon->active) { - struct intel_digital_port *dig_port = - enc_to_dig_port(encoder); + /* FIXME precompute everything properly */ + /* FIXME how do we turn infoframes off again? */ + if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink) dig_port->set_infoframes(encoder, crtc_state->has_infoframe, crtc_state, conn_state); - } } } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b2d0edacc58c9..bd51855ddc842 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1279,6 +1279,7 @@ struct intel_dp { u8 sink_count; bool link_mst; bool link_trained; + bool has_hdmi_sink; bool has_audio; bool reset_link_params; u8 dpcd[DP_RECEIVER_CAP_SIZE]; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4bd10456ad188..684166dbc9a33 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6069,7 +6069,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp) edid = intel_dp_get_edid(intel_dp); intel_connector->detect_edid = edid; - intel_dp->has_audio = drm_detect_monitor_audio(edid); + if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { + intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); + intel_dp->has_audio = drm_detect_monitor_audio(edid); + } + drm_dp_cec_set_edid(&intel_dp->aux, edid); intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid); } @@ -6083,6 +6087,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) kfree(intel_connector->detect_edid); intel_connector->detect_edid = NULL; + intel_dp->has_hdmi_sink = false; intel_dp->has_audio = false; intel_dp->edid_quirks = 0; } -- GitLab From a77ed90da6bb4062e3d8bc6daaa200a5494c7b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:39 +0300 Subject: [PATCH 1253/1494] drm/dp: Define protocol converter DPCD registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DP 1.3 and 1.4 introduced some new registers for DP->HDMI protocol converters. Define those. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-4-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- include/drm/drm_dp_helper.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5c45195ced321..17d32d7632b6e 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -984,6 +984,16 @@ #define DP_CEC_TX_MESSAGE_BUFFER 0x3020 #define DP_CEC_MESSAGE_BUFFER_LENGTH 0x10 +#define DP_PROTOCOL_CONVERTER_CONTROL_0 0x3050 /* DP 1.3 */ +# define DP_HDMI_DVI_OUTPUT_CONFIG (1 << 0) /* DP 1.3 */ +#define DP_PROTOCOL_CONVERTER_CONTROL_1 0x3051 /* DP 1.3 */ +# define DP_CONVERSION_TO_YCBCR420_ENABLE (1 << 0) /* DP 1.3 */ +# define DP_HDMI_EDID_PROCESSING_DISABLE (1 << 1) /* DP 1.4 */ +# define DP_HDMI_AUTONOMOUS_SCRAMBLING_DISABLE (1 << 2) /* DP 1.4 */ +# define DP_HDMI_FORCE_SCRAMBLING (1 << 3) /* DP 1.4 */ +#define DP_PROTOCOL_CONVERTER_CONTROL_2 0x3052 /* DP 1.3 */ +# define DP_CONVERSION_TO_YCBCR422_ENABLE (1 << 0) /* DP 1.3 */ + #define DP_AUX_HDCP_BKSV 0x68000 #define DP_AUX_HDCP_RI_PRIME 0x68005 #define DP_AUX_HDCP_AKSV 0x68007 -- GitLab From 57d6a6851f05bf594d2918888c350347fb0c2eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:40 +0300 Subject: [PATCH 1254/1494] drm/dp: Define more downstream facing port caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our definitions for the DPCD DFP capabilities are lacking. Add the missing bits. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-5-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- include/drm/drm_dp_helper.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 17d32d7632b6e..86461a40066b2 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -386,12 +386,18 @@ # define DP_DS_PORT_TYPE_WIRELESS 6 # define DP_DS_PORT_HPD (1 << 3) /* offset 1 for VGA is maximum megapixels per second / 8 */ -/* offset 2 */ +/* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */ +/* offset 2 for VGA/DVI/HDMI */ # define DP_DS_MAX_BPC_MASK (3 << 0) # define DP_DS_8BPC 0 # define DP_DS_10BPC 1 # define DP_DS_12BPC 2 # define DP_DS_16BPC 3 +/* offset 3 for DVI */ +# define DP_DS_DVI_DUAL_LINK (1 << 1) +# define DP_DS_DVI_HIGH_COLOR_DEPTH (1 << 2) +/* offset 3 for HDMI */ +# define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0) #define DP_MAX_DOWNSTREAM_PORTS 0x10 -- GitLab From 530df3c031a65a57dae8f1ade0e8266b33530b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:41 +0300 Subject: [PATCH 1255/1494] drm/i915: Reworkd DFP max bpc handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stash the downstream facing port max bpc away during intel_dp_set_edid(). We'll soon need the EDID in there so we can't figure this out so easily during .compute_config() anymore. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-6-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- .../drm/i915/display/intel_display_types.h | 5 +++++ drivers/gpu/drm/i915/display/intel_dp.c | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index bd51855ddc842..5f1a6696d0a85 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1381,6 +1381,11 @@ struct intel_dp { /* Displayport compliance testing */ struct intel_dp_compliance compliance; + /* Downstream facing port caps */ + struct { + u8 max_bpc; + } dfp; + /* Display stream compression testing */ bool force_dsc_en; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 684166dbc9a33..5ecff6824a309 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1973,13 +1973,12 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_connector *intel_connector = intel_dp->attached_connector; - int bpp, bpc; + int bpp; bpp = pipe_config->pipe_bpp; - bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports); - if (bpc > 0) - bpp = min(bpp, 3*bpc); + if (intel_dp->dfp.max_bpc) + bpp = min(bpp, 3 * intel_dp->dfp.max_bpc); if (intel_dp_is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ @@ -6062,12 +6061,21 @@ intel_dp_get_edid(struct intel_dp *intel_dp) static void intel_dp_set_edid(struct intel_dp *intel_dp) { - struct intel_connector *intel_connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_connector *connector = intel_dp->attached_connector; struct edid *edid; intel_dp_unset_edid(intel_dp); edid = intel_dp_get_edid(intel_dp); - intel_connector->detect_edid = edid; + connector->detect_edid = edid; + + intel_dp->dfp.max_bpc = + drm_dp_downstream_max_bpc(intel_dp->dpcd, + intel_dp->downstream_ports); + + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n", + connector->base.base.id, connector->base.name, + intel_dp->dfp.max_bpc); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -6090,6 +6098,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->has_hdmi_sink = false; intel_dp->has_audio = false; intel_dp->edid_quirks = 0; + + intel_dp->dfp.max_bpc = 0; } static int -- GitLab From 38784f6f880580cbe168edbe7ba38c161dee3216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:42 +0300 Subject: [PATCH 1256/1494] drm/dp: Add helpers to identify downstream facing port types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a few helpers to let us better identify which kind of DFP we're dealing with. v2: Use Returns: for kdoc (Lyude) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-7-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 5 +++ 2 files changed, 65 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index c21bbfc3d7147..56a3ba1477133 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -363,6 +363,66 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_dpcd_read_link_status); +static bool is_edid_digital_input_dp(const struct edid *edid) +{ + return edid && edid->revision >= 4 && + edid->input & DRM_EDID_INPUT_DIGITAL && + (edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_DP; +} + +/** + * drm_dp_downstream_is_type() - is the downstream facing port of certain type? + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Caveat: Only works with DPCD 1.1+ port caps. + * + * Returns: whether the downstream facing port matches the type. + */ +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], u8 type) +{ + return drm_dp_is_branch(dpcd) && + dpcd[DP_DPCD_REV] >= 0x11 && + (port_cap[0] & DP_DS_PORT_TYPE_MASK) == type; +} +EXPORT_SYMBOL(drm_dp_downstream_is_type); + +/** + * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS? + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * @edid: EDID + * + * Returns: whether the downstream facing port is TMDS (HDMI/DVI). + */ +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid) +{ + if (dpcd[DP_DPCD_REV] < 0x11) { + switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) { + case DP_DWN_STRM_PORT_TYPE_TMDS: + return true; + default: + return false; + } + } + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_DP_DUALMODE: + if (is_edid_digital_input_dp(edid)) + return false; + fallthrough; + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + return true; + default: + return false; + } +} +EXPORT_SYMBOL(drm_dp_downstream_is_tmds); + /** * drm_dp_send_real_edid_checksum() - send back real edid checksum value * @aux: DisplayPort AUX channel diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 86461a40066b2..4f946826dfce3 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1638,6 +1638,11 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, int drm_dp_read_downstream_info(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE], u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]); +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], u8 type); +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], -- GitLab From 42f2562ca1b52810415107d919535c552196384e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:43 +0300 Subject: [PATCH 1257/1494] drm/dp: Pimp drm_dp_downstream_max_bpc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deal with more cases in drm_dp_downstream_max_bpc(): - DPCD 1.0 -> assume 8bpc for non-DP - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap - anything else -> assume 8bpc v2: Use Returns: for kdoc (Lyude) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-8-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 59 +++++++++++-------- .../drm/i915/display/intel_display_debugfs.c | 3 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- include/drm/drm_dp_helper.h | 10 +++- 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 56a3ba1477133..e1af400df65cf 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], EXPORT_SYMBOL(drm_dp_downstream_max_clock); /** - * drm_dp_downstream_max_bpc() - extract branch device max + * drm_dp_downstream_max_bpc() - extract downstream facing port max * bits per component * @dpcd: DisplayPort configuration data - * @port_cap: port capabilities - * - * See also: - * drm_dp_read_downstream_info() - * drm_dp_downstream_max_clock() + * @port_cap: downstream facing port capabilities + * @edid: EDID * * Returns: Max bpc on success or 0 if max bpc not defined */ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]) + const u8 port_cap[4], + const struct edid *edid) { - int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; - bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DETAILED_CAP_INFO_AVAILABLE; - int bpc; - - if (!detailed_cap_info) + if (!drm_dp_is_branch(dpcd)) return 0; - switch (type) { - case DP_DS_PORT_TYPE_VGA: - case DP_DS_PORT_TYPE_DVI: - case DP_DS_PORT_TYPE_HDMI: + if (dpcd[DP_DPCD_REV] < 0x11) { + switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) { + case DP_DWN_STRM_PORT_TYPE_DP: + return 0; + default: + return 8; + } + } + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_DP: + return 0; case DP_DS_PORT_TYPE_DP_DUALMODE: - bpc = port_cap[2] & DP_DS_MAX_BPC_MASK; + if (is_edid_digital_input_dp(edid)) + return 0; + fallthrough; + case DP_DS_PORT_TYPE_HDMI: + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_VGA: + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return 8; - switch (bpc) { + switch (port_cap[2] & DP_DS_MAX_BPC_MASK) { case DP_DS_8BPC: return 8; case DP_DS_10BPC: @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], return 12; case DP_DS_16BPC: return 16; + default: + return 8; } - fallthrough; + break; default: - return 0; + return 8; } } EXPORT_SYMBOL(drm_dp_downstream_max_bpc); @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id); * @m: pointer for debugfs file * @dpcd: DisplayPort configuration data * @port_cap: port capabilities + * @edid: EDID * @aux: DisplayPort AUX channel * */ void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4], struct drm_dp_aux *aux) + const u8 port_cap[4], + const struct edid *edid, + struct drm_dp_aux *aux) { bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE; @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m, seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk); } - bpc = drm_dp_downstream_max_bpc(dpcd, port_cap); + bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid); if (bpc > 0) seq_printf(m, "\t\tMax bpc: %d\n", bpc); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 53a0a3d9a22df..0bf31f9a8af56 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m, { struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector); struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder); + const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr; seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]); seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m, intel_panel_info(m, &intel_connector->panel); drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, - &intel_dp->aux); + edid ? edid->data : NULL, &intel_dp->aux); } static void intel_dp_mst_info(struct seq_file *m, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5ecff6824a309..027307f17823e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp) intel_dp->dfp.max_bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, - intel_dp->downstream_ports); + intel_dp->downstream_ports, edid); drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n", connector->base.base.id, connector->base.name, diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 4f946826dfce3..6218de1294c14 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]); + const u8 port_cap[4], + const struct edid *edid); int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); -void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4], struct drm_dp_aux *aux); +void drm_dp_downstream_debug(struct seq_file *m, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid, + struct drm_dp_aux *aux); enum drm_mode_subconnector drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); -- GitLab From 67d6a8b358eac488112a4775f77dc3dbf63bea88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> Date: Wed, 16 Sep 2020 15:31:28 +0200 Subject: [PATCH 1258/1494] drm/ttm: remove superflous extern attribute from funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extern is the default attribute for functions anyway. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/390972/ --- include/drm/ttm/ttm_execbuf_util.h | 19 ++++++++----------- include/drm/ttm/ttm_memory.h | 25 ++++++++++++------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index 5a19843bb80d6..a99d7fdf29643 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -58,9 +58,8 @@ struct ttm_validate_buffer { * Undoes all buffer validation reservations for bos pointed to by * the list entries. */ - -extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, - struct list_head *list); +void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, + struct list_head *list); /** * function ttm_eu_reserve_buffers @@ -96,10 +95,9 @@ extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, * ttm_eu_fence_buffer_objects() when command submission is complete or * has failed. */ - -extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, - struct list_head *list, bool intr, - struct list_head *dups); +int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, + struct list_head *list, bool intr, + struct list_head *dups); /** * function ttm_eu_fence_buffer_objects. @@ -113,9 +111,8 @@ extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, * It also unreserves all buffers, putting them on lru lists. * */ - -extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, - struct list_head *list, - struct dma_fence *fence); +void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, + struct list_head *list, + struct dma_fence *fence); #endif diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h index 2d468d7c94e66..c1f167881e335 100644 --- a/include/drm/ttm/ttm_memory.h +++ b/include/drm/ttm/ttm_memory.h @@ -79,18 +79,17 @@ extern struct ttm_mem_global { #endif } ttm_mem_glob; -extern int ttm_mem_global_init(struct ttm_mem_global *glob); -extern void ttm_mem_global_release(struct ttm_mem_global *glob); -extern int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, +int ttm_mem_global_init(struct ttm_mem_global *glob); +void ttm_mem_global_release(struct ttm_mem_global *glob); +int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, + struct ttm_operation_ctx *ctx); +void ttm_mem_global_free(struct ttm_mem_global *glob, uint64_t amount); +int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, + struct page *page, uint64_t size, + struct ttm_operation_ctx *ctx); +void ttm_mem_global_free_page(struct ttm_mem_global *glob, + struct page *page, uint64_t size); +size_t ttm_round_pot(size_t size); +bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, uint64_t num_pages, struct ttm_operation_ctx *ctx); -extern void ttm_mem_global_free(struct ttm_mem_global *glob, - uint64_t amount); -extern int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, - struct page *page, uint64_t size, - struct ttm_operation_ctx *ctx); -extern void ttm_mem_global_free_page(struct ttm_mem_global *glob, - struct page *page, uint64_t size); -extern size_t ttm_round_pot(size_t size); -extern bool ttm_check_under_lowerlimit(struct ttm_mem_global *glob, - uint64_t num_pages, struct ttm_operation_ctx *ctx); #endif -- GitLab From b770e84311451506d822574595631009267c7e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:44 +0300 Subject: [PATCH 1259/1494] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to differentiate between the DFP dotclock and TMDS clock limits. Let's convert the current thing to just give us the dotclock limit. v2: Use Returns: for kdoc (Lyude) Fix up nouveau code too Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-9-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 46 +++++++++---------------- drivers/gpu/drm/i915/display/intel_dp.c | 4 +-- drivers/gpu/drm/nouveau/nouveau_dp.c | 4 +-- include/drm/drm_dp_helper.h | 4 +-- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index e1af400df65cf..8767ad7f6690c 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -616,41 +616,32 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux, EXPORT_SYMBOL(drm_dp_read_downstream_info); /** - * drm_dp_downstream_max_clock() - extract branch device max - * pixel rate for legacy VGA - * converter or max TMDS clock - * rate for others + * drm_dp_downstream_max_dotclock() - extract downstream facing port max dot clock * @dpcd: DisplayPort configuration data * @port_cap: port capabilities * - * See also: - * drm_dp_read_downstream_info() - * drm_dp_downstream_max_bpc() - * - * Returns: Max clock in kHz on success or 0 if max clock not defined + * Returns: Downstream facing port max dot clock in kHz on success, + * or 0 if max clock not defined */ -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]) +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) { - int type = port_cap[0] & DP_DS_PORT_TYPE_MASK; - bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] & - DP_DETAILED_CAP_INFO_AVAILABLE; + if (!drm_dp_is_branch(dpcd)) + return 0; - if (!detailed_cap_info) + if (dpcd[DP_DPCD_REV] < 0x11) return 0; - switch (type) { + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { case DP_DS_PORT_TYPE_VGA: - return port_cap[1] * 8 * 1000; - case DP_DS_PORT_TYPE_DVI: - case DP_DS_PORT_TYPE_HDMI: - case DP_DS_PORT_TYPE_DP_DUALMODE: - return port_cap[1] * 2500; + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return 0; + return port_cap[1] * 8000; default: return 0; } } -EXPORT_SYMBOL(drm_dp_downstream_max_clock); +EXPORT_SYMBOL(drm_dp_downstream_max_dotclock); /** * drm_dp_downstream_max_bpc() - extract downstream facing port max @@ -793,14 +784,9 @@ void drm_dp_downstream_debug(struct seq_file *m, seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]); if (detailed_cap_info) { - clk = drm_dp_downstream_max_clock(dpcd, port_cap); - - if (clk > 0) { - if (type == DP_DS_PORT_TYPE_VGA) - seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk); - else - seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk); - } + clk = drm_dp_downstream_max_dotclock(dpcd, port_cap); + if (clk > 0) + seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk); bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 027307f17823e..c664e8e1bf346 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -261,8 +261,8 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) if (type != DP_DS_PORT_TYPE_VGA) return max_dotclk; - ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd, - intel_dp->downstream_ports); + ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd, + intel_dp->downstream_ports); if (ds_max_dotclk != 0) max_dotclk = min(max_dotclk, ds_max_dotclk); diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 810bf69565683..7b640e05bd4cd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -239,8 +239,8 @@ nv50_dp_mode_valid(struct drm_connector *connector, return MODE_NO_INTERLACE; max_clock = outp->dp.link_nr * outp->dp.link_bw; - ds_clock = drm_dp_downstream_max_clock(outp->dp.dpcd, - outp->dp.downstream_ports); + ds_clock = drm_dp_downstream_max_dotclock(outp->dp.dpcd, + outp->dp.downstream_ports); if (ds_clock) max_clock = min(max_clock, ds_clock); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 6218de1294c14..19bc04207788d 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1643,8 +1643,8 @@ bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE], bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], const struct edid *edid); -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], - const u8 port_cap[4]); +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], const struct edid *edid); -- GitLab From fe7cf496e5000b68275ee5898cbe1eeb722c134a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:45 +0300 Subject: [PATCH 1260/1494] drm/i915: Reworkd DP DFP clock handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the downstream facing port dotclock check into a new function (intel_dp_mode_valid_downstream()) so that we have a nice future place where we can collect other related checks. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-10-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 55 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5f1a6696d0a85..f9647809452be 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1383,6 +1383,7 @@ struct intel_dp { /* Downstream facing port caps */ struct { + int max_dotclock; u8 max_bpc; } dfp; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c664e8e1bf346..b68a27ab05f8f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -247,29 +247,6 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes) return max_link_clock * max_lanes; } -static int -intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct intel_encoder *encoder = &dig_port->base; - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - int max_dotclk = dev_priv->max_dotclk_freq; - int ds_max_dotclk; - - int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK; - - if (type != DP_DS_PORT_TYPE_VGA) - return max_dotclk; - - ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd, - intel_dp->downstream_ports); - - if (ds_max_dotclk != 0) - max_dotclk = min(max_dotclk, ds_max_dotclk); - - return max_dotclk; -} - static int cnl_max_source_rate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -634,6 +611,19 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv, return hdisplay == 4096 && !HAS_DDI(dev_priv); } +static enum drm_mode_status +intel_dp_mode_valid_downstream(struct intel_connector *connector, + int target_clock) +{ + struct intel_dp *intel_dp = intel_attached_dp(connector); + + if (intel_dp->dfp.max_dotclock && + target_clock > intel_dp->dfp.max_dotclock) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) @@ -644,15 +634,14 @@ intel_dp_mode_valid(struct drm_connector *connector, struct drm_i915_private *dev_priv = to_i915(connector->dev); int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk; + int max_dotclk = dev_priv->max_dotclk_freq; u16 dsc_max_output_bpp = 0; u8 dsc_slice_count = 0; + enum drm_mode_status status; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; - max_dotclk = intel_dp_downstream_max_dotclock(intel_dp); - if (intel_dp_is_edp(intel_dp) && fixed_mode) { if (mode->hdisplay > fixed_mode->hdisplay) return MODE_PANEL; @@ -708,6 +697,10 @@ intel_dp_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; + status = intel_dp_mode_valid_downstream(intel_connector, target_clock); + if (status != MODE_OK) + return status; + return intel_mode_valid_max_plane_size(dev_priv, mode); } @@ -6073,9 +6066,14 @@ intel_dp_set_edid(struct intel_dp *intel_dp) drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports, edid); - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n", + intel_dp->dfp.max_dotclock = + drm_dp_downstream_max_dotclock(intel_dp->dpcd, + intel_dp->downstream_ports); + + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n", connector->base.base.id, connector->base.name, - intel_dp->dfp.max_bpc); + intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -6100,6 +6098,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->edid_quirks = 0; intel_dp->dfp.max_bpc = 0; + intel_dp->dfp.max_dotclock = 0; } static int -- GitLab From 6509ca051abf4ff60d63732badcb2173a715f741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:46 +0300 Subject: [PATCH 1261/1494] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to get the TMDS clock limits for HDMI/DVI downstream facing ports. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-11-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 6 ++ 2 files changed, 122 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 8767ad7f6690c..5d8c9bd700c97 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_dotclock); +/** + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max TMDS clock + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * @edid: EDID + * + * Returns: HDMI/DVI downstream facing port max TMDS clock in kHz on success, + * or 0 if max TMDS clock not defined + */ +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid) +{ + if (!drm_dp_is_branch(dpcd)) + return 0; + + if (dpcd[DP_DPCD_REV] < 0x11) { + switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) { + case DP_DWN_STRM_PORT_TYPE_TMDS: + return 165000; + default: + return 0; + } + } + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_DP_DUALMODE: + if (is_edid_digital_input_dp(edid)) + return 0; + /* + * It's left up to the driver to check the + * DP dual mode adapter's max TMDS clock. + * + * Unfortunatley it looks like branch devices + * may not fordward that the DP dual mode i2c + * access so we just usually get i2c nak :( + */ + fallthrough; + case DP_DS_PORT_TYPE_HDMI: + /* + * We should perhaps assume 165 MHz when detailed cap + * info is not available. But looks like many typical + * branch devices fall into that category and so we'd + * probably end up with users complaining that they can't + * get high resolution modes with their favorite dongle. + * + * So let's limit to 300 MHz instead since DPCD 1.4 + * HDMI 2.0 DFPs are required to have the detailed cap + * info. So it's more likely we're dealing with a HDMI 1.4 + * compatible* device here. + */ + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return 300000; + return port_cap[1] * 2500; + case DP_DS_PORT_TYPE_DVI: + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return 165000; + /* FIXME what to do about DVI dual link? */ + return port_cap[1] * 2500; + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock); + +/** + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min TMDS clock + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * @edid: EDID + * + * Returns: HDMI/DVI downstream facing port min TMDS clock in kHz on success, + * or 0 if max TMDS clock not defined + */ +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid) +{ + if (!drm_dp_is_branch(dpcd)) + return 0; + + if (dpcd[DP_DPCD_REV] < 0x11) { + switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) { + case DP_DWN_STRM_PORT_TYPE_TMDS: + return 25000; + default: + return 0; + } + } + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_DP_DUALMODE: + if (is_edid_digital_input_dp(edid)) + return 0; + fallthrough; + case DP_DS_PORT_TYPE_DVI: + case DP_DS_PORT_TYPE_HDMI: + /* + * Unclear whether the protocol converter could + * utilize pixel replication. Assume it won't. + */ + return 25000; + default: + return 0; + } +} +EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock); + /** * drm_dp_downstream_max_bpc() - extract downstream facing port max * bits per component @@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m, if (clk > 0) seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk); + clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid); + if (clk > 0) + seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk); + + clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid); + if (clk > 0) + seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk); + bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid); if (bpc > 0) diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 19bc04207788d..6812a3e0de8dd 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const struct edid *edid); int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4], + const struct edid *edid); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], const struct edid *edid); -- GitLab From 3977cd1c1dcbfdc64138710d0470356a458f731c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:47 +0300 Subject: [PATCH 1262/1494] drm/i915: Deal with TMDS DFP clock limits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new helpers to extract the TMDS clock limits from the downstream facing port and check them in .mode_valid(). TODO: we should check these in .compute_config() too to eg. determine if we can do deep color on the HDMI side or not Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-12-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 36 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f9647809452be..3058f703d0119 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1383,6 +1383,7 @@ struct intel_dp { /* Downstream facing port caps */ struct { + int min_tmds_clock, max_tmds_clock; int max_dotclock; u8 max_bpc; } dfp; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index b68a27ab05f8f..1ec37b704f09a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -613,14 +613,29 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv, static enum drm_mode_status intel_dp_mode_valid_downstream(struct intel_connector *connector, + const struct drm_display_mode *mode, int target_clock) { struct intel_dp *intel_dp = intel_attached_dp(connector); + const struct drm_display_info *info = &connector->base.display_info; + int tmds_clock; if (intel_dp->dfp.max_dotclock && target_clock > intel_dp->dfp.max_dotclock) return MODE_CLOCK_HIGH; + /* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */ + tmds_clock = target_clock; + if (drm_mode_is_420_only(info, mode)) + tmds_clock /= 2; + + if (intel_dp->dfp.min_tmds_clock && + tmds_clock < intel_dp->dfp.min_tmds_clock) + return MODE_CLOCK_LOW; + if (intel_dp->dfp.max_tmds_clock && + tmds_clock > intel_dp->dfp.max_tmds_clock) + return MODE_CLOCK_HIGH; + return MODE_OK; } @@ -697,7 +712,8 @@ intel_dp_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; - status = intel_dp_mode_valid_downstream(intel_connector, target_clock); + status = intel_dp_mode_valid_downstream(intel_connector, + mode, target_clock); if (status != MODE_OK) return status; @@ -6070,10 +6086,22 @@ intel_dp_set_edid(struct intel_dp *intel_dp) drm_dp_downstream_max_dotclock(intel_dp->dpcd, intel_dp->downstream_ports); + intel_dp->dfp.min_tmds_clock = + drm_dp_downstream_min_tmds_clock(intel_dp->dpcd, + intel_dp->downstream_ports, + edid); + intel_dp->dfp.max_tmds_clock = + drm_dp_downstream_max_tmds_clock(intel_dp->dpcd, + intel_dp->downstream_ports, + edid); + drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n", + "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d, TMDS clock %d-%d\n", connector->base.base.id, connector->base.name, - intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock); + intel_dp->dfp.max_bpc, + intel_dp->dfp.max_dotclock, + intel_dp->dfp.min_tmds_clock, + intel_dp->dfp.max_tmds_clock); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -6099,6 +6127,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->dfp.max_bpc = 0; intel_dp->dfp.max_dotclock = 0; + intel_dp->dfp.min_tmds_clock = 0; + intel_dp->dfp.max_tmds_clock = 0; } static int -- GitLab From b7feffd584ba15de54ba465a3b32f775c70e1907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:48 +0300 Subject: [PATCH 1263/1494] drm/i915: Configure DP 1.3+ protocol converted HDMI mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DP 1.3 adds some extra control knobs for DP->HDMI protocol conversion. Let's use that to configure the "HDMI mode" (ie. infoframes vs. not) based on the capabilities of the sink. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-13-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_ddi.c | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.h | 1 + 3 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1eb9191e49dd2..4d06178cd76ce 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3470,6 +3470,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, intel_ddi_init_dp_buf_reg(encoder); if (!is_mst) intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + intel_dp_configure_protocol_converter(intel_dp); intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true); intel_dp_sink_set_fec_ready(intel_dp, crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 1ec37b704f09a..2538ffaa7463c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3792,6 +3792,28 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp, intel_de_posting_read(dev_priv, intel_dp->output_reg); } +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + u8 tmp; + + if (intel_dp->dpcd[DP_DPCD_REV] < 0x13) + return; + + if (!drm_dp_is_branch(intel_dp->dpcd)) + return; + + tmp = intel_dp->has_hdmi_sink ? + DP_HDMI_DVI_OUTPUT_CONFIG : 0; + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0) + drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n", + enableddisabled(intel_dp->has_hdmi_sink)); + + /* TODO: configure YCbCr 4:2:2/4:2:0 conversion */ +} + static void intel_enable_dp(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, @@ -3829,6 +3851,7 @@ static void intel_enable_dp(struct intel_atomic_state *state, } intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + intel_dp_configure_protocol_converter(intel_dp); intel_dp_start_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index ec5688a21f660..08a1c0aa8b94b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -51,6 +51,7 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, int intel_dp_retrain_link(struct intel_encoder *encoder, struct drm_modeset_acquire_ctx *ctx); void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp); void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, bool enable); -- GitLab From 7af655bce275f49b200b552921e55673624943c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:49 +0300 Subject: [PATCH 1264/1494] drm/dp: Add drm_dp_downstream_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The downstream facing port caps in the DPCD can give us a hint as to what kind of display mode the sink can use if it doesn't have an EDID. Use that information to pick a suitable mode. v2: Use Returns: for kdoc (Lyude) Add kdocs for drm_display_mode_from_cea_vic() (Lyude) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-14-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 54 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_edid.c | 28 +++++++++++++++++ include/drm/drm_dp_helper.h | 12 ++++++++ include/drm/drm_edid.h | 4 +++ 4 files changed, 98 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 5d8c9bd700c97..63ac94c54e959 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -808,6 +808,60 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_bpc); +/** + * drm_dp_downstream_mode() - return a mode for downstream facing port + * @dpcd: DisplayPort configuration data + * @port_cap: port capabilities + * + * Provides a suitable mode for downstream facing ports without EDID. + * + * Returns: A new drm_display_mode on success or NULL on failure + */ +struct drm_display_mode * +drm_dp_downstream_mode(struct drm_device *dev, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) + +{ + u8 vic; + + if (!drm_dp_is_branch(dpcd)) + return NULL; + + if (dpcd[DP_DPCD_REV] < 0x11) + return NULL; + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_NON_EDID: + switch (port_cap[0] & DP_DS_NON_EDID_MASK) { + case DP_DS_NON_EDID_720x480i_60: + vic = 6; + break; + case DP_DS_NON_EDID_720x480i_50: + vic = 21; + break; + case DP_DS_NON_EDID_1920x1080i_60: + vic = 5; + break; + case DP_DS_NON_EDID_1920x1080i_50: + vic = 20; + break; + case DP_DS_NON_EDID_1280x720_60: + vic = 4; + break; + case DP_DS_NON_EDID_1280x720_50: + vic = 19; + break; + default: + return NULL; + } + return drm_display_mode_from_cea_vic(dev, vic); + default: + return NULL; + } +} +EXPORT_SYMBOL(drm_dp_downstream_mode); + /** * drm_dp_downstream_id() - identify branch device * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6840f0530a389..a82f37d442582 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3738,6 +3738,34 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd) bitmap_set(hdmi->y420_cmdb_modes, vic, 1); } +/** + * drm_display_mode_from_cea_vic() - return a mode for CEA VIC + * @dev: DRM device + * @vic: CEA VIC of the mode + * + * Creates a new mode matching the specified CEA VIC. + * + * Returns: A new drm_display_mode on success or NULL on failure + */ +struct drm_display_mode * +drm_display_mode_from_cea_vic(struct drm_device *dev, + u8 video_code) +{ + const struct drm_display_mode *cea_mode; + struct drm_display_mode *newmode; + + cea_mode = cea_mode_for_vic(video_code); + if (!cea_mode) + return NULL; + + newmode = drm_mode_duplicate(dev, cea_mode); + if (!newmode) + return NULL; + + return newmode; +} +EXPORT_SYMBOL(drm_display_mode_from_cea_vic); + static int do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len) { diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 6812a3e0de8dd..fbba4a0f73665 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -28,6 +28,8 @@ #include <linux/types.h> #include <drm/drm_connector.h> +struct drm_device; + /* * Unless otherwise noted, all values are from the DP 1.1a spec. Note that * DP and DPCD versions are independent. Differences from 1.0 are not noted, @@ -385,6 +387,13 @@ # define DP_DS_PORT_TYPE_DP_DUALMODE 5 # define DP_DS_PORT_TYPE_WIRELESS 6 # define DP_DS_PORT_HPD (1 << 3) +# define DP_DS_NON_EDID_MASK (0xf << 4) +# define DP_DS_NON_EDID_720x480i_60 (1 << 4) +# define DP_DS_NON_EDID_720x480i_50 (2 << 4) +# define DP_DS_NON_EDID_1920x1080i_60 (3 << 4) +# define DP_DS_NON_EDID_1920x1080i_50 (4 << 4) +# define DP_DS_NON_EDID_1280x720_60 (5 << 4) +# define DP_DS_NON_EDID_1280x720_50 (7 << 4) /* offset 1 for VGA is maximum megapixels per second / 8 */ /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */ /* offset 2 for VGA/DVI/HDMI */ @@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], const struct edid *edid); +struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]); void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE], diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index cfa4f5af49afd..b27a0e2169c8f 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -517,4 +517,8 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name, struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, int hsize, int vsize, int fresh, bool rb); +struct drm_display_mode * +drm_display_mode_from_cea_vic(struct drm_device *dev, + u8 video_code); + #endif /* __DRM_EDID_H__ */ -- GitLab From 4b3bb839873f9e8c3c7f6297274d48d50388c16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:50 +0300 Subject: [PATCH 1265/1494] drm/i915: Handle downstream facing ports w/o EDID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use drm_dp_downstream_mode() to get a suitable mode for downstream facing ports which don't have an EDID. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-15-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_dp.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2538ffaa7463c..124b23e419a0f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6313,7 +6313,7 @@ static int intel_dp_get_modes(struct drm_connector *connector) } /* if eDP has no EDID, fall back to fixed mode */ - if (intel_dp_is_edp(intel_attached_dp(to_intel_connector(connector))) && + if (intel_dp_is_edp(intel_attached_dp(intel_connector)) && intel_connector->panel.fixed_mode) { struct drm_display_mode *mode; @@ -6325,6 +6325,19 @@ static int intel_dp_get_modes(struct drm_connector *connector) } } + if (!edid) { + struct intel_dp *intel_dp = intel_attached_dp(intel_connector); + struct drm_display_mode *mode; + + mode = drm_dp_downstream_mode(connector->dev, + intel_dp->dpcd, + intel_dp->downstream_ports); + if (mode) { + drm_mode_probed_add(connector, mode); + return 1; + } + } + return 0; } -- GitLab From 04e18e01b3c35dd4f598db4feccd51da643cdf1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:51 +0300 Subject: [PATCH 1266/1494] drm/i915: Extract intel_hdmi_has_audio() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the "do we want to enable audio?" computation into a small helper to make intel_hdmi_compute_config() less messy. Will make it easier to add more checks for this later (eg. we should actually be checking at the hblank is long enough for audio transmission). Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-16-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_hdmi.c | 28 +++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 40620c3d7a30c..528d1ae54cb49 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2465,6 +2465,23 @@ bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, } } +static bool intel_hdmi_has_audio(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + const struct intel_digital_connector_state *intel_conn_state = + to_intel_digital_connector_state(conn_state); + + if (!crtc_state->has_hdmi_sink) + return false; + + if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) + return intel_hdmi->has_audio; + else + return intel_conn_state->force_audio == HDMI_AUDIO_ON; +} + int intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) @@ -2474,8 +2491,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct drm_connector *connector = conn_state->connector; struct drm_scdc *scdc = &connector->display_info.hdmi.scdc; - struct intel_digital_connector_state *intel_conn_state = - to_intel_digital_connector_state(conn_state); int ret; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -2501,13 +2516,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv)) pipe_config->has_pch_encoder = true; - if (pipe_config->has_hdmi_sink) { - if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) - pipe_config->has_audio = intel_hdmi->has_audio; - else - pipe_config->has_audio = - intel_conn_state->force_audio == HDMI_AUDIO_ON; - } + pipe_config->has_audio = + intel_hdmi_has_audio(encoder, pipe_config, conn_state); ret = intel_hdmi_compute_clock(encoder, pipe_config); if (ret) -- GitLab From bc7ca6a647bf3c073a109d4ff0e8cad773a2f1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:52 +0300 Subject: [PATCH 1267/1494] drm/i915: DP->HDMI TMDS clock limits vs. deep color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Account for the TMDS clock limits declared by the DFP when determining what color depth we're going to use. v2: Drop the reference to DP++ dongle since it's not handled here Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-17-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/i915/display/intel_dp.c | 63 ++++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_hdmi.c | 50 ++++++++++-------- drivers/gpu/drm/i915/display/intel_hdmi.h | 2 + 3 files changed, 88 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 124b23e419a0f..bafac3b989c3b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1977,18 +1977,69 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp, drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd); } -static int intel_dp_compute_bpp(struct intel_dp *intel_dp, - struct intel_crtc_state *pipe_config) +static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420; +} + +static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state, int bpc) +{ + int clock = crtc_state->hw.adjusted_mode.crtc_clock * bpc / 8; + + if (intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) + clock /= 2; + + return clock; +} + +static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state, int bpc) +{ + int tmds_clock = intel_dp_hdmi_tmds_clock(intel_dp, crtc_state, bpc); + + if (intel_dp->dfp.min_tmds_clock && + tmds_clock < intel_dp->dfp.min_tmds_clock) + return false; + + if (intel_dp->dfp.max_tmds_clock && + tmds_clock > intel_dp->dfp.max_tmds_clock) + return false; + + return true; +} + +static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state, + int bpc) +{ + bool has_hdmi_sink = intel_dp->has_hdmi_sink; + + return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) && + intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc); +} + +static int intel_dp_max_bpp(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_connector *intel_connector = intel_dp->attached_connector; - int bpp; + int bpp, bpc; - bpp = pipe_config->pipe_bpp; + bpc = crtc_state->pipe_bpp / 3; if (intel_dp->dfp.max_bpc) - bpp = min(bpp, 3 * intel_dp->dfp.max_bpc); + bpc = min_t(int, bpc, intel_dp->dfp.max_bpc); + + if (intel_dp->dfp.min_tmds_clock) { + for (; bpc >= 10; bpc -= 2) { + if (intel_dp_hdmi_deep_color_possible(intel_dp, crtc_state, bpc)) + break; + } + } + bpp = bpc * 3; if (intel_dp_is_edp(intel_dp)) { /* Get bpp from vbt only for panels that dont have bpp in edid */ if (intel_connector->base.display_info.bpc == 0 && @@ -2310,7 +2361,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, limits.max_lane_count = intel_dp_max_lane_count(intel_dp); limits.min_bpp = intel_dp_min_bpp(pipe_config); - limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config); + limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config); if (intel_dp_is_edp(intel_dp)) { /* diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 528d1ae54cb49..1012b1d466015 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2277,35 +2277,18 @@ intel_hdmi_mode_valid(struct drm_connector *connector, return intel_mode_valid_max_plane_size(dev_priv, mode); } -static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, - int bpc) +bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, + int bpc, bool has_hdmi_sink) { - struct drm_i915_private *dev_priv = - to_i915(crtc_state->uapi.crtc->dev); struct drm_atomic_state *state = crtc_state->uapi.state; struct drm_connector_state *connector_state; struct drm_connector *connector; - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; int i; - if (HAS_GMCH(dev_priv)) - return false; - - if (bpc == 10 && INTEL_GEN(dev_priv) < 11) - return false; - if (crtc_state->pipe_bpp < bpc * 3) return false; - if (!crtc_state->has_hdmi_sink) - return false; - - /* - * HDMI deep color affects the clocks, so it's only possible - * when not cloning with other encoder types. - */ - if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI) + if (!has_hdmi_sink) return false; for_each_new_connector_in_state(state, connector, connector_state, i) { @@ -2333,6 +2316,30 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, } } + return true; +} + +static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, + int bpc) +{ + struct drm_i915_private *dev_priv = + to_i915(crtc_state->uapi.crtc->dev); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (HAS_GMCH(dev_priv)) + return false; + + if (bpc == 10 && INTEL_GEN(dev_priv) < 11) + return false; + + /* + * HDMI deep color affects the clocks, so it's only possible + * when not cloning with other encoder types. + */ + if (crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI)) + return false; + /* Display Wa_1405510057:icl,ehl */ if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 && bpc == 10 && IS_GEN(dev_priv, 11) && @@ -2340,7 +2347,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, adjusted_mode->crtc_hblank_start) % 8 == 2) return false; - return true; + return intel_hdmi_deep_color_possible(crtc_state, bpc, + crtc_state->has_hdmi_sink); } static int diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 5b348dcab77a0..c382930a992ee 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -48,5 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder, union hdmi_infoframe *frame); bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); +bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, + int bpc, bool has_hdmi_sink); #endif /* __INTEL_HDMI_H__ */ -- GitLab From 2ef8d0f7de0ec0bc30c48e5f544a6082eb03e9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:53 +0300 Subject: [PATCH 1268/1494] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helpers to determine whether the DFP supports YCbCr 4:2:0 passthrough or YCbCr 4:4:4->4:2:0 conversion. v2: Add kdocs (Lyude) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-18-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 8 +++++ 2 files changed, 68 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 63ac94c54e959..90807a6b415ca 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -808,6 +808,66 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], } EXPORT_SYMBOL(drm_dp_downstream_max_bpc); +/** + * drm_dp_downstream_420_passthrough() - determine downstream facing port + * YCbCr 4:2:0 pass-through capability + * @dpcd: DisplayPort configuration data + * @port_cap: downstream facing port capabilities + * + * Returns: whether the downstream facing port can pass through YCbCr 4:2:0 + */ +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + if (!drm_dp_is_branch(dpcd)) + return false; + + if (dpcd[DP_DPCD_REV] < 0x13) + return false; + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_DP: + return true; + case DP_DS_PORT_TYPE_HDMI: + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return false; + + return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH; + default: + return false; + } +} +EXPORT_SYMBOL(drm_dp_downstream_420_passthrough); + +/** + * drm_dp_downstream_444_to_420_conversion() - determine downstream facing port + * YCbCr 4:4:4->4:2:0 conversion capability + * @dpcd: DisplayPort configuration data + * @port_cap: downstream facing port capabilities + * + * Returns: whether the downstream facing port can convert YCbCr 4:4:4 to 4:2:0 + */ +bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]) +{ + if (!drm_dp_is_branch(dpcd)) + return false; + + if (dpcd[DP_DPCD_REV] < 0x13) + return false; + + switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) { + case DP_DS_PORT_TYPE_HDMI: + if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) + return false; + + return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV; + default: + return false; + } +} +EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion); + /** * drm_dp_downstream_mode() - return a mode for downstream facing port * @dpcd: DisplayPort configuration data diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index fbba4a0f73665..c9f2851904d0a 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -407,6 +407,10 @@ struct drm_device; # define DP_DS_DVI_HIGH_COLOR_DEPTH (1 << 2) /* offset 3 for HDMI */ # define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0) +# define DP_DS_HDMI_YCBCR422_PASS_THROUGH (1 << 1) +# define DP_DS_HDMI_YCBCR420_PASS_THROUGH (1 << 2) +# define DP_DS_HDMI_YCBCR444_TO_422_CONV (1 << 3) +# define DP_DS_HDMI_YCBCR444_TO_420_CONV (1 << 4) #define DP_MAX_DOWNSTREAM_PORTS 0x10 @@ -1663,6 +1667,10 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4], const struct edid *edid); +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); +bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const u8 port_cap[4]); struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); -- GitLab From 181567aa9f0d297804f1ea5d3ff4ba4518e05f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 4 Sep 2020 14:53:54 +0300 Subject: [PATCH 1269/1494] drm/i915: Do YCbCr 444->420 conversion via DP protocol converters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For platforms that can't do native 4:2:0 outout we may still be able to do it by getting the DP->HDMI protocol converter to perform the 4:4:4->4:2:0 downsamling for us. In this case we have to configure our hardware to output YCbCr 4:4:4, which we've already hooked up so all we need to do is flip the switch. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200904115354.25336-19-ville.syrjala@linux.intel.com Reviewed-by: Lyude Paul <lyude@redhat.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 121 +++++++++++++++--- drivers/gpu/drm/i915/display/intel_hdmi.c | 8 +- drivers/gpu/drm/i915/display/intel_hdmi.h | 4 +- 4 files changed, 109 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 3058f703d0119..fcf5d3f20945d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1386,6 +1386,7 @@ struct intel_dp { int min_tmds_clock, max_tmds_clock; int max_dotclock; u8 max_bpc; + bool ycbcr_444_to_420; } dfp; /* Display stream compression testing */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index bafac3b989c3b..bf1e9cf1c0f3f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1980,7 +1980,9 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp, static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { - return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420; + return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 || + (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 && + intel_dp->dfp.ycbcr_444_to_420); } static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp, @@ -2014,9 +2016,10 @@ static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state, int bpc) { - bool has_hdmi_sink = intel_dp->has_hdmi_sink; - return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) && + return intel_hdmi_deep_color_possible(crtc_state, bpc, + intel_dp->has_hdmi_sink, + intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) && intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc); } @@ -2436,11 +2439,17 @@ intel_dp_ycbcr420_config(struct intel_dp *intel_dp, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!drm_mode_is_420_only(info, adjusted_mode) || - !intel_dp_get_colorimetry_status(intel_dp) || - !connector->ycbcr_420_allowed) + if (!connector->ycbcr_420_allowed) return 0; + if (!drm_mode_is_420_only(info, adjusted_mode)) + return 0; + + if (intel_dp->dfp.ycbcr_444_to_420) { + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR444; + return 0; + } + crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420; return intel_pch_panel_fitting(crtc_state, conn_state); @@ -3858,11 +3867,26 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp) DP_HDMI_DVI_OUTPUT_CONFIG : 0; if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0) + DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1) drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n", enableddisabled(intel_dp->has_hdmi_sink)); - /* TODO: configure YCbCr 4:2:2/4:2:0 conversion */ + tmp = intel_dp->dfp.ycbcr_444_to_420 ? + DP_CONVERSION_TO_YCBCR420_ENABLE : 0; + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1) + drm_dbg_kms(&i915->drm, + "Failed to set protocol converter YCbCr 4:2:0 conversion mode to %s\n", + enableddisabled(intel_dp->dfp.ycbcr_444_to_420)); + + tmp = 0; + + if (drm_dp_dpcd_writeb(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_2, tmp) <= 0) + drm_dbg_kms(&i915->drm, + "Failed to set protocol converter YCbCr 4:2:2 conversion mode to %s\n", + enableddisabled(false)); } static void intel_enable_dp(struct intel_atomic_state *state, @@ -6142,15 +6166,11 @@ intel_dp_get_edid(struct intel_dp *intel_dp) } static void -intel_dp_set_edid(struct intel_dp *intel_dp) +intel_dp_update_dfp(struct intel_dp *intel_dp, + const struct edid *edid) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; - struct edid *edid; - - intel_dp_unset_edid(intel_dp); - edid = intel_dp_get_edid(intel_dp); - connector->detect_edid = edid; intel_dp->dfp.max_bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, @@ -6176,6 +6196,67 @@ intel_dp_set_edid(struct intel_dp *intel_dp) intel_dp->dfp.max_dotclock, intel_dp->dfp.min_tmds_clock, intel_dp->dfp.max_tmds_clock); +} + +static void +intel_dp_update_420(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_connector *connector = intel_dp->attached_connector; + bool is_branch, ycbcr_420_passthrough, ycbcr_444_to_420; + + /* No YCbCr output support on gmch platforms */ + if (HAS_GMCH(i915)) + return; + + /* + * ILK doesn't seem capable of DP YCbCr output. The + * displayed image is severly corrupted. SNB+ is fine. + */ + if (IS_GEN(i915, 5)) + return; + + is_branch = drm_dp_is_branch(intel_dp->dpcd); + ycbcr_420_passthrough = + drm_dp_downstream_420_passthrough(intel_dp->dpcd, + intel_dp->downstream_ports); + ycbcr_444_to_420 = + drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd, + intel_dp->downstream_ports); + + if (INTEL_GEN(i915) >= 11) { + /* Prefer 4:2:0 passthrough over 4:4:4->4:2:0 conversion */ + intel_dp->dfp.ycbcr_444_to_420 = + ycbcr_444_to_420 && !ycbcr_420_passthrough; + + connector->base.ycbcr_420_allowed = + !is_branch || ycbcr_444_to_420 || ycbcr_420_passthrough; + } else { + /* 4:4:4->4:2:0 conversion is the only way */ + intel_dp->dfp.ycbcr_444_to_420 = ycbcr_444_to_420; + + connector->base.ycbcr_420_allowed = ycbcr_444_to_420; + } + + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n", + connector->base.base.id, connector->base.name, + yesno(connector->base.ycbcr_420_allowed), + yesno(intel_dp->dfp.ycbcr_444_to_420)); +} + +static void +intel_dp_set_edid(struct intel_dp *intel_dp) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct edid *edid; + + intel_dp_unset_edid(intel_dp); + edid = intel_dp_get_edid(intel_dp); + connector->detect_edid = edid; + + intel_dp_update_dfp(intel_dp, edid); + intel_dp_update_420(intel_dp); if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid); @@ -6189,11 +6270,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp) static void intel_dp_unset_edid(struct intel_dp *intel_dp) { - struct intel_connector *intel_connector = intel_dp->attached_connector; + struct intel_connector *connector = intel_dp->attached_connector; drm_dp_cec_unset_edid(&intel_dp->aux); - kfree(intel_connector->detect_edid); - intel_connector->detect_edid = NULL; + kfree(connector->detect_edid); + connector->detect_edid = NULL; intel_dp->has_hdmi_sink = false; intel_dp->has_audio = false; @@ -6203,6 +6284,9 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->dfp.max_dotclock = 0; intel_dp->dfp.min_tmds_clock = 0; intel_dp->dfp.max_tmds_clock = 0; + + intel_dp->dfp.ycbcr_444_to_420 = false; + connector->base.ycbcr_420_allowed = false; } static int @@ -7729,9 +7813,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, connector->interlace_allowed = true; connector->doublescan_allowed = 0; - if (INTEL_GEN(dev_priv) >= 11) - connector->ycbcr_420_allowed = true; - intel_connector->polled = DRM_CONNECTOR_POLL_HPD; intel_dp_aux_init(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 1012b1d466015..3f2008d845c20 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -2278,7 +2278,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, } bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, - int bpc, bool has_hdmi_sink) + int bpc, bool has_hdmi_sink, bool ycbcr420_output) { struct drm_atomic_state *state = crtc_state->uapi.state; struct drm_connector_state *connector_state; @@ -2297,7 +2297,7 @@ bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, if (connector_state->crtc != crtc_state->uapi.crtc) continue; - if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { + if (ycbcr420_output) { const struct drm_hdmi_info *hdmi = &info->hdmi; if (bpc == 12 && !(hdmi->y420_dc_modes & @@ -2348,7 +2348,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, return false; return intel_hdmi_deep_color_possible(crtc_state, bpc, - crtc_state->has_hdmi_sink); + crtc_state->has_hdmi_sink, + crtc_state->output_format == + INTEL_OUTPUT_FORMAT_YCBCR420); } static int diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index c382930a992ee..15eb0ccde76e0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -48,7 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder, union hdmi_infoframe *frame); bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); -bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, - int bpc, bool has_hdmi_sink); +bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, int bpc, + bool has_hdmi_sink, bool ycbcr420_output); #endif /* __INTEL_HDMI_H__ */ -- GitLab From e161da331618e31b3f66d9d47d7f02d75ba815a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Wed, 2 Sep 2020 15:21:41 +0300 Subject: [PATCH 1270/1494] drm/i915: Remove the old global state stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the dbuf code mostly converted over to the new global state handling we can remove the leftovers of the old global state stuff. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200902122141.15181-1-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> --- drivers/gpu/drm/i915/display/intel_atomic.c | 39 ------------------- drivers/gpu/drm/i915/display/intel_atomic.h | 4 -- drivers/gpu/drm/i915/display/intel_display.c | 22 ----------- .../drm/i915/display/intel_display_types.h | 7 ---- 4 files changed, 72 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 630f49b7aa010..86be032bcf965 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -527,8 +527,6 @@ void intel_atomic_state_clear(struct drm_atomic_state *s) intel_atomic_clear_global_state(state); state->dpll_set = state->modeset = false; - state->global_state_changed = false; - state->active_pipes = 0; } struct intel_crtc_state * @@ -542,40 +540,3 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } - -int _intel_atomic_lock_global_state(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_crtc *crtc; - - state->global_state_changed = true; - - for_each_intel_crtc(&dev_priv->drm, crtc) { - int ret; - - ret = drm_modeset_lock(&crtc->base.mutex, - state->base.acquire_ctx); - if (ret) - return ret; - } - - return 0; -} - -int _intel_atomic_serialize_global_state(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_crtc *crtc; - - state->global_state_changed = true; - - for_each_intel_crtc(&dev_priv->drm, crtc) { - struct intel_crtc_state *crtc_state; - - crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - } - - return 0; -} diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h index 11146292b06f5..285de07011dcf 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.h +++ b/drivers/gpu/drm/i915/display/intel_atomic.h @@ -56,8 +56,4 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); -int _intel_atomic_lock_global_state(struct intel_atomic_state *state); - -int _intel_atomic_serialize_global_state(struct intel_atomic_state *state); - #endif /* __INTEL_ATOMIC_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 254fbeec56298..980f4050aedcb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14649,16 +14649,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state, static int intel_modeset_checks(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - int ret; state->modeset = true; - state->active_pipes = intel_calc_active_pipes(state, dev_priv->active_pipes); - - if (state->active_pipes != dev_priv->active_pipes) { - ret = _intel_atomic_lock_global_state(state); - if (ret) - return ret; - } if (IS_HASWELL(dev_priv)) return hsw_mode_set_planes_workaround(state); @@ -15770,14 +15762,6 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state) plane->frontbuffer_bit); } -static void assert_global_state_locked(struct drm_i915_private *dev_priv) -{ - struct intel_crtc *crtc; - - for_each_intel_crtc(&dev_priv->drm, crtc) - drm_modeset_lock_assert_held(&crtc->base.mutex); -} - static int intel_atomic_commit(struct drm_device *dev, struct drm_atomic_state *_state, bool nonblock) @@ -15853,12 +15837,6 @@ static int intel_atomic_commit(struct drm_device *dev, intel_shared_dpll_swap_state(state); intel_atomic_track_fbs(state); - if (state->global_state_changed) { - assert_global_state_locked(dev_priv); - - dev_priv->active_pipes = state->active_pipes; - } - drm_atomic_state_get(&state->base); INIT_WORK(&state->base.commit_work, intel_atomic_commit_work); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index fcf5d3f20945d..3d4bf9b6a0a2c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -483,8 +483,6 @@ struct intel_atomic_state { bool dpll_set, modeset; - u8 active_pipes; - struct intel_shared_dpll_state shared_dpll[I915_NUM_PLLS]; /* @@ -495,11 +493,6 @@ struct intel_atomic_state { bool rps_interactive; - /* - * active_pipes - */ - bool global_state_changed; - struct i915_sw_fence commit_ready; struct llist_node freed; -- GitLab From dc98f50fa5a05735c70ffe34fe5d2468fc20d44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Tue, 14 Jul 2020 18:26:26 +0300 Subject: [PATCH 1271/1494] drm/i915: Nuke force_min_cdclk_changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we now have proper old and new cdclk state we no longer need to keep this flag to indicate that the force min cdclk has changed. Instead just check if the old vs. new value are different. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> --- drivers/gpu/drm/i915/display/intel_audio.c | 5 ----- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- drivers/gpu/drm/i915/display/intel_cdclk.h | 1 - drivers/gpu/drm/i915/display/intel_display.c | 7 +++++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index ad4aa66fd6767..f7de557077460 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -958,13 +958,8 @@ static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, if (IS_ERR(cdclk_state)) return PTR_ERR(cdclk_state); - cdclk_state->force_min_cdclk_changed = true; cdclk_state->force_min_cdclk = enable ? 2 * 96000 : 0; - ret = intel_atomic_lock_global_state(&cdclk_state->base); - if (ret) - return ret; - return drm_atomic_commit(&state->base); } diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 577c4441f32df..cb93f6cf6d37b 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2426,7 +2426,6 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa if (!cdclk_state) return NULL; - cdclk_state->force_min_cdclk_changed = false; cdclk_state->pipe = INVALID_PIPE; return &cdclk_state->base; @@ -2501,6 +2500,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) if (ret) return ret; } else if (old_cdclk_state->active_pipes != new_cdclk_state->active_pipes || + old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk || intel_cdclk_changed(&old_cdclk_state->logical, &new_cdclk_state->logical)) { ret = intel_atomic_lock_global_state(&new_cdclk_state->base); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 6b31fde4be164..b34eb00fb3275 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -49,7 +49,6 @@ struct intel_cdclk_state { /* forced minimum cdclk for glk+ audio w/a */ int force_min_cdclk; - bool force_min_cdclk_changed; /* bitmask of active pipes */ u8 active_pipes; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 980f4050aedcb..efc1d0f33fd7e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14794,7 +14794,8 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state, bool *need_cdclk_calc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_cdclk_state *new_cdclk_state; + const struct intel_cdclk_state *old_cdclk_state; + const struct intel_cdclk_state *new_cdclk_state; struct intel_plane_state *plane_state; struct intel_bw_state *new_bw_state; struct intel_plane *plane; @@ -14813,9 +14814,11 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state, return ret; } + old_cdclk_state = intel_atomic_get_old_cdclk_state(state); new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed) + if (new_cdclk_state && + old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk) *need_cdclk_calc = true; ret = dev_priv->display.bw_calc_min_cdclk(state); -- GitLab From dc6798a5207b9f334c680b37e590b48b7d3099ea Mon Sep 17 00:00:00 2001 From: Swathi Dhanavanthri <swathi.dhanavanthri@intel.com> Date: Fri, 11 Sep 2020 15:11:58 -0700 Subject: [PATCH 1272/1494] drm/i915/tgl, rkl: Make Wa_1606700617/22010271021 permanent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This workaround applies to all TGL and RKL steppings. Signed-off-by: Swathi Dhanavanthri <swathi.dhanavanthri@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: José Roberto de Souza <jose.souza@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200911221158.4700-1-swathi.dhanavanthri@intel.com --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 39817c5a70583..6c580d0d9ea8f 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1729,10 +1729,11 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN6_RC_SLEEP_PSMI_CONTROL, GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | GEN8_RC_SEMA_IDLE_MSG_DISABLE); - } - if (IS_TGL_U(i915) || IS_TGL_Y(i915)) { - /* Wa_1606700617:tgl */ + /* + * Wa_1606700617:tgl + * Wa_22010271021:tgl,rkl + */ wa_masked_en(wal, GEN9_CS_DEBUG_MODE1, FF_DOP_CLOCK_GATE_DISABLE); -- GitLab From 0b988ca1c7c4c73983b4ea96ef7c2af2263c87eb Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 12:54:24 +1000 Subject: [PATCH 1273/1494] drm/ttm: protect against reentrant bind in the drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves the generic tracking into the drivers and protects against reentrancy in the drivers. It fixes up radeon and agp to be able to query the bound status as that is required. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 +++++++++ drivers/gpu/drm/nouveau/nouveau_bo.c | 5 +++- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 8 +++++- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_mn.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 31 ++++++++++++++++++++++ drivers/gpu/drm/ttm/ttm_agp_backend.c | 14 ++++++++++ drivers/gpu/drm/ttm/ttm_bo.c | 20 ++------------ drivers/gpu/drm/ttm/ttm_bo_util.c | 5 ---- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 22 ++++++++++++--- include/drm/ttm/ttm_bo_api.h | 1 - include/drm/ttm/ttm_bo_driver.h | 14 ---------- include/drm/ttm/ttm_tt.h | 1 + 13 files changed, 91 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e86f8f6371c4c..2851cf30091a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -813,6 +813,7 @@ struct amdgpu_ttm_tt { uint64_t userptr; struct task_struct *usertask; uint32_t userflags; + bool bound; #if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR) struct hmm_range *range; #endif @@ -1110,6 +1111,12 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, uint64_t flags; int r = 0; + if (!bo_mem) + return -EINVAL; + + if (gtt->bound) + return 0; + if (gtt->userptr) { r = amdgpu_ttm_tt_pin_userptr(bdev, ttm); if (r) { @@ -1143,6 +1150,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, if (r) DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", ttm->num_pages, gtt->offset); + gtt->bound = true; return r; } @@ -1236,6 +1244,9 @@ static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev, struct amdgpu_ttm_tt *gtt = (void *)ttm; int r; + if (!gtt->bound) + return; + /* if the pages have userptr pinning then clear that first */ if (gtt->userptr) amdgpu_ttm_tt_unpin_userptr(bdev, ttm); @@ -1248,6 +1259,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev, if (r) DRM_ERROR("failed to unbind %lu pages at 0x%08llX\n", gtt->ttm.ttm.num_pages, gtt->offset); + gtt->bound = false; } static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index aea201d9c5137..616d8844ba973 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -718,7 +718,10 @@ nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, { #if IS_ENABLED(CONFIG_AGP) struct nouveau_drm *drm = nouveau_bdev(bdev); - +#endif + if (!reg) + return -EINVAL; +#if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) return ttm_agp_bind(ttm, reg); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 05e542254e1f4..21fb92770ea20 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -33,6 +33,9 @@ nouveau_sgdma_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_re struct nouveau_mem *mem = nouveau_mem(reg); int ret; + if (nvbe->mem) + return 0; + ret = nouveau_mem_host(reg, &nvbe->ttm); if (ret) return ret; @@ -53,7 +56,10 @@ void nouveau_sgdma_unbind(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - nouveau_mem_fini(nvbe->mem); + if (nvbe->mem) { + nouveau_mem_fini(nvbe->mem); + nvbe->mem = NULL; + } } struct ttm_tt * diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index df6f0b49836b7..a6d8de01194ae 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2820,6 +2820,7 @@ extern int radeon_ttm_tt_set_userptr(struct radeon_device *rdev, uint32_t flags); extern bool radeon_ttm_tt_has_userptr(struct radeon_device *rdev, struct ttm_tt *ttm); extern bool radeon_ttm_tt_is_readonly(struct radeon_device *rdev, struct ttm_tt *ttm); +bool radeon_ttm_tt_is_bound(struct ttm_bo_device *bdev, struct ttm_tt *ttm); extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index eb46d22202365..97b9b6dd6dd3b 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -53,7 +53,7 @@ static bool radeon_mn_invalidate(struct mmu_interval_notifier *mn, struct ttm_operation_ctx ctx = { false, false }; long r; - if (!bo->tbo.ttm || !ttm_bo_tt_is_bound(&bo->tbo)) + if (!bo->tbo.ttm || !radeon_ttm_tt_is_bound(bo->tbo.bdev, bo->tbo.ttm)) return true; if (!mmu_notifier_range_blockable(range)) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index c6c1008fefd22..fc8bbca28b345 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -420,6 +420,7 @@ struct radeon_ttm_tt { uint64_t userptr; struct mm_struct *usermm; uint32_t userflags; + bool bound; }; /* prepare the sg table with the user pages */ @@ -513,6 +514,13 @@ static void radeon_ttm_tt_unpin_userptr(struct ttm_bo_device *bdev, struct ttm_t sg_free_table(ttm->sg); } +static bool radeon_ttm_backend_is_bound(struct ttm_tt *ttm) +{ + struct radeon_ttm_tt *gtt = (void*)ttm; + + return (gtt->bound); +} + static int radeon_ttm_backend_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem) @@ -523,6 +531,9 @@ static int radeon_ttm_backend_bind(struct ttm_bo_device *bdev, RADEON_GART_PAGE_WRITE; int r; + if (gtt->bound) + return 0; + if (gtt->userptr) { radeon_ttm_tt_pin_userptr(bdev, ttm); flags &= ~RADEON_GART_PAGE_WRITE; @@ -542,6 +553,7 @@ static int radeon_ttm_backend_bind(struct ttm_bo_device *bdev, ttm->num_pages, (unsigned)gtt->offset); return r; } + gtt->bound = true; return 0; } @@ -550,10 +562,14 @@ static void radeon_ttm_backend_unbind(struct ttm_bo_device *bdev, struct ttm_tt struct radeon_ttm_tt *gtt = (void *)ttm; struct radeon_device *rdev = radeon_get_rdev(bdev); + if (!gtt->bound) + return; + radeon_gart_unbind(rdev, gtt->offset, ttm->num_pages); if (gtt->userptr) radeon_ttm_tt_unpin_userptr(bdev, ttm); + gtt->bound = false; } static void radeon_ttm_backend_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) @@ -689,12 +705,27 @@ int radeon_ttm_tt_set_userptr(struct radeon_device *rdev, return 0; } +bool radeon_ttm_tt_is_bound(struct ttm_bo_device *bdev, + struct ttm_tt *ttm) +{ +#if IS_ENABLED(CONFIG_AGP) + struct radeon_device *rdev = radeon_get_rdev(bdev); + if (rdev->flags & RADEON_IS_AGP) + return ttm_agp_is_bound(ttm); +#endif + return radeon_ttm_backend_is_bound(ttm); +} + static int radeon_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem) { +#if IS_ENABLED(CONFIG_AGP) struct radeon_device *rdev = radeon_get_rdev(bdev); +#endif + if (!bo_mem) + return -EINVAL; #if IS_ENABLED(CONFIG_AGP) if (rdev->flags & RADEON_IS_AGP) return ttm_agp_bind(ttm, bo_mem); diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 7b36fdaab7667..a98fd795b7523 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -57,6 +57,9 @@ int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem) int ret, cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); unsigned i; + if (agp_be->mem) + return 0; + mem = agp_allocate_memory(agp_be->bridge, ttm->num_pages, AGP_USER_MEMORY); if (unlikely(mem == NULL)) return -ENOMEM; @@ -98,6 +101,17 @@ void ttm_agp_unbind(struct ttm_tt *ttm) } EXPORT_SYMBOL(ttm_agp_unbind); +bool ttm_agp_is_bound(struct ttm_tt *ttm) +{ + struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); + + if (!ttm) + return false; + + return (agp_be->mem != NULL); +} +EXPORT_SYMBOL(ttm_agp_is_bound); + void ttm_agp_destroy(struct ttm_tt *ttm) { struct ttm_agp_backend *agp_be = container_of(ttm, struct ttm_agp_backend, ttm); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 92d60585deb18..4741c73f6ea4d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1626,27 +1626,11 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem) { - int ret; - - if (!bo->ttm) - return -EINVAL; - - if (ttm_bo_tt_is_bound(bo)) - return 0; - - ret = bo->bdev->driver->ttm_tt_bind(bo->bdev, bo->ttm, mem); - if (unlikely(ret != 0)) - return ret; - - ttm_bo_tt_set_bound(bo); - return 0; + return bo->bdev->driver->ttm_tt_bind(bo->bdev, bo->ttm, mem); } EXPORT_SYMBOL(ttm_bo_tt_bind); void ttm_bo_tt_unbind(struct ttm_buffer_object *bo) { - if (ttm_bo_tt_is_bound(bo)) { - bo->bdev->driver->ttm_tt_unbind(bo->bdev, bo->ttm); - ttm_bo_tt_set_unbound(bo); - } + bo->bdev->driver->ttm_tt_unbind(bo->bdev, bo->ttm); } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 980368049d689..919489f6a5a33 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -574,10 +574,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (man->use_tt) { ghost_obj->ttm = NULL; - ttm_bo_tt_set_unbound(ghost_obj); } else { bo->ttm = NULL; - ttm_bo_tt_set_unbound(bo); } dma_resv_unlock(&ghost_obj->base._resv); @@ -633,10 +631,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, if (to->use_tt) { ghost_obj->ttm = NULL; - ttm_bo_tt_set_unbound(ghost_obj); } else { bo->ttm = NULL; - ttm_bo_tt_set_unbound(bo); } dma_resv_unlock(&ghost_obj->base._resv); @@ -701,7 +697,6 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) memset(&bo->mem, 0, sizeof(bo->mem)); bo->mem.mem_type = TTM_PL_SYSTEM; bo->ttm = NULL; - ttm_bo_tt_set_unbound(bo); dma_resv_unlock(&ghost->base._resv); ttm_bo_put(ghost); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 3458c5c3531d6..01146b27c9a1d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -267,6 +267,7 @@ struct vmw_ttm_tt { struct vmw_sg_table vsgt; uint64_t sg_alloc_size; bool mapped; + bool bound; }; const size_t vmw_tt_size = sizeof(struct vmw_ttm_tt); @@ -565,7 +566,13 @@ static int vmw_ttm_bind(struct ttm_bo_device *bdev, { struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); - int ret; + int ret = 0; + + if (!bo_mem) + return -EINVAL; + + if (vmw_be->bound) + return 0; ret = vmw_ttm_map_dma(vmw_be); if (unlikely(ret != 0)) @@ -576,8 +583,9 @@ static int vmw_ttm_bind(struct ttm_bo_device *bdev, switch (bo_mem->mem_type) { case VMW_PL_GMR: - return vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt, + ret = vmw_gmr_bind(vmw_be->dev_priv, &vmw_be->vsgt, ttm->num_pages, vmw_be->gmr_id); + break; case VMW_PL_MOB: if (unlikely(vmw_be->mob == NULL)) { vmw_be->mob = @@ -586,13 +594,15 @@ static int vmw_ttm_bind(struct ttm_bo_device *bdev, return -ENOMEM; } - return vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob, + ret = vmw_mob_bind(vmw_be->dev_priv, vmw_be->mob, &vmw_be->vsgt, ttm->num_pages, vmw_be->gmr_id); + break; default: BUG(); } - return 0; + vmw_be->bound = true; + return ret; } static void vmw_ttm_unbind(struct ttm_bo_device *bdev, @@ -601,6 +611,9 @@ static void vmw_ttm_unbind(struct ttm_bo_device *bdev, struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + if (!vmw_be->bound) + return; + switch (vmw_be->mem_type) { case VMW_PL_GMR: vmw_gmr_unbind(vmw_be->dev_priv, vmw_be->gmr_id); @@ -614,6 +627,7 @@ static void vmw_ttm_unbind(struct ttm_bo_device *bdev, if (vmw_be->dev_priv->map_mode == vmw_dma_map_bind) vmw_ttm_unmap_dma(vmw_be); + vmw_be->bound = false; } diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 89ad6f213fc0d..fd8d29f5f3704 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -141,7 +141,6 @@ struct ttm_buffer_object { struct ttm_resource mem; struct file *persistent_swap_storage; struct ttm_tt *ttm; - bool ttm_bound; bool evicted; bool deleted; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index e66672f703a38..7846dfa507f7f 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -698,20 +698,6 @@ int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem); */ void ttm_bo_tt_unbind(struct ttm_buffer_object *bo); -static inline bool ttm_bo_tt_is_bound(struct ttm_buffer_object *bo) -{ - return bo->ttm_bound; -} - -static inline void ttm_bo_tt_set_unbound(struct ttm_buffer_object *bo) -{ - bo->ttm_bound = false; -} - -static inline void ttm_bo_tt_set_bound(struct ttm_buffer_object *bo) -{ - bo->ttm_bound = true; -} /** * ttm_bo_tt_destroy. */ diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index c777b72063db4..4e906e32d08cc 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -219,6 +219,7 @@ struct ttm_tt *ttm_agp_tt_create(struct ttm_buffer_object *bo, int ttm_agp_bind(struct ttm_tt *ttm, struct ttm_resource *bo_mem); void ttm_agp_unbind(struct ttm_tt *ttm); void ttm_agp_destroy(struct ttm_tt *ttm); +bool ttm_agp_is_bound(struct ttm_tt *ttm); #endif #endif -- GitLab From 7626168fd132009c79a0457bccc58014abc738f5 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 13:20:48 +1000 Subject: [PATCH 1274/1494] drm/ttm: flip tt destroy ordering. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call the driver first and have it call the common code cleanup. This is useful later to fix unbind. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-3-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 + drivers/gpu/drm/drm_gem_vram_helper.c | 1 + drivers/gpu/drm/nouveau/nouveau_bo.c | 1 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 1 + drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_ttm.c | 3 +++ drivers/gpu/drm/ttm/ttm_tt.c | 7 ++++++- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 1 + include/drm/ttm/ttm_tt.h | 7 +++++++ 9 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 2851cf30091a8..dbe3f90a0cf60 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1267,6 +1267,7 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, { struct amdgpu_ttm_tt *gtt = (void *)ttm; + ttm_tt_destroy_common(bdev, ttm); if (gtt->usertask) put_task_struct(gtt->usertask); diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index f96321509d7eb..50cad0e4a92e3 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -922,6 +922,7 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { static void bo_driver_ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *tt) { + ttm_tt_destroy_common(bdev, tt); ttm_tt_fini(tt); kfree(tt); } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 616d8844ba973..b239381498c3f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1372,6 +1372,7 @@ nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) struct nouveau_drm *drm = nouveau_bdev(bdev); if (drm->agp.bridge) { + ttm_tt_destroy_common(bdev, ttm); ttm_agp_destroy(ttm); return; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 21fb92770ea20..0dfaa6fb536ec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -20,6 +20,7 @@ nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; if (ttm) { + ttm_tt_destroy_common(bdev, ttm); ttm_dma_tt_fini(&nvbe->ttm); kfree(nvbe); } diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index bf3b091d0e2ae..fd691fff8394b 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -130,6 +130,7 @@ static void qxl_ttm_backend_destroy(struct ttm_bo_device *bdev, { struct qxl_ttm_tt *gtt = (void *)ttm; + ttm_tt_destroy_common(bdev, ttm); ttm_tt_fini(>t->ttm); kfree(gtt); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index fc8bbca28b345..76e24c6058fff 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -576,6 +576,8 @@ static void radeon_ttm_backend_destroy(struct ttm_bo_device *bdev, struct ttm_tt { struct radeon_ttm_tt *gtt = (void *)ttm; + ttm_tt_destroy_common(bdev, ttm); + ttm_dma_tt_fini(>t->ttm); kfree(gtt); } @@ -755,6 +757,7 @@ static void radeon_ttm_tt_destroy(struct ttm_bo_device *bdev, struct radeon_device *rdev = radeon_get_rdev(bdev); if (rdev->flags & RADEON_IS_AGP) { + ttm_tt_destroy_common(bdev, ttm); ttm_agp_destroy(ttm); return; } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index a4f0296effaca..f43fa69a1e650 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -207,7 +207,7 @@ int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement) } EXPORT_SYMBOL(ttm_tt_set_placement_caching); -void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) +void ttm_tt_destroy_common(struct ttm_bo_device *bdev, struct ttm_tt *ttm) { ttm_tt_unpopulate(bdev, ttm); @@ -216,6 +216,11 @@ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) fput(ttm->swap_storage); ttm->swap_storage = NULL; +} +EXPORT_SYMBOL(ttm_tt_destroy_common); + +void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) +{ bdev->driver->ttm_tt_destroy(bdev, ttm); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 01146b27c9a1d..d46426164577c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -636,6 +636,7 @@ static void vmw_ttm_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + ttm_tt_destroy_common(bdev, ttm); vmw_ttm_unmap_dma(vmw_be); if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) ttm_dma_tt_fini(&vmw_be->dma_ttm); diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h index 4e906e32d08cc..75208c0a0cac0 100644 --- a/include/drm/ttm/ttm_tt.h +++ b/include/drm/ttm/ttm_tt.h @@ -155,6 +155,13 @@ void ttm_dma_tt_fini(struct ttm_dma_tt *ttm_dma); */ void ttm_tt_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm); +/** + * ttm_tt_destroy_common: + * + * Called from driver to destroy common path. + */ +void ttm_tt_destroy_common(struct ttm_bo_device *bdev, struct ttm_tt *ttm); + /** * ttm_tt_swapin: * -- GitLab From 37bff6542c4e140a11657406c1bab50a40329cc1 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 13:24:50 +1000 Subject: [PATCH 1275/1494] drm/ttm: move unbind into the tt destroy. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves unbind into the driver side on destroy paths. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-4-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 + drivers/gpu/drm/nouveau/nouveau_bo.c | 1 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 1 + drivers/gpu/drm/radeon/radeon_ttm.c | 2 ++ drivers/gpu/drm/ttm/ttm_bo.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dbe3f90a0cf60..2028b9e4c25cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1267,6 +1267,7 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, { struct amdgpu_ttm_tt *gtt = (void *)ttm; + amdgpu_ttm_backend_unbind(bdev, ttm); ttm_tt_destroy_common(bdev, ttm); if (gtt->usertask) put_task_struct(gtt->usertask); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index b239381498c3f..4a020a3da3ddf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1372,6 +1372,7 @@ nouveau_ttm_tt_destroy(struct ttm_bo_device *bdev, #if IS_ENABLED(CONFIG_AGP) struct nouveau_drm *drm = nouveau_bdev(bdev); if (drm->agp.bridge) { + ttm_agp_unbind(ttm); ttm_tt_destroy_common(bdev, ttm); ttm_agp_destroy(ttm); return; diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 0dfaa6fb536ec..806d9ec310f55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -20,6 +20,7 @@ nouveau_sgdma_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; if (ttm) { + nouveau_sgdma_unbind(bdev, ttm); ttm_tt_destroy_common(bdev, ttm); ttm_dma_tt_fini(&nvbe->ttm); kfree(nvbe); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 76e24c6058fff..03e5ae4e3bf66 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -576,6 +576,7 @@ static void radeon_ttm_backend_destroy(struct ttm_bo_device *bdev, struct ttm_tt { struct radeon_ttm_tt *gtt = (void *)ttm; + radeon_ttm_backend_unbind(bdev, ttm); ttm_tt_destroy_common(bdev, ttm); ttm_dma_tt_fini(>t->ttm); @@ -757,6 +758,7 @@ static void radeon_ttm_tt_destroy(struct ttm_bo_device *bdev, struct radeon_device *rdev = radeon_get_rdev(bdev); if (rdev->flags & RADEON_IS_AGP) { + ttm_agp_unbind(ttm); ttm_tt_destroy_common(bdev, ttm); ttm_agp_destroy(ttm); return; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4741c73f6ea4d..b814d0c9bc8a8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1619,7 +1619,6 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) if (bo->ttm == NULL) return; - ttm_bo_tt_unbind(bo); ttm_tt_destroy(bo->bdev, bo->ttm); bo->ttm = NULL; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index d46426164577c..7454f797d37b1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -636,6 +636,7 @@ static void vmw_ttm_destroy(struct ttm_bo_device *bdev, struct ttm_tt *ttm) struct vmw_ttm_tt *vmw_be = container_of(ttm, struct vmw_ttm_tt, dma_ttm.ttm); + vmw_ttm_unbind(bdev, ttm); ttm_tt_destroy_common(bdev, ttm); vmw_ttm_unmap_dma(vmw_be); if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) -- GitLab From cae515f4a5d9e17eb1f0db1eef9028601ab2decf Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 13:48:59 +1000 Subject: [PATCH 1276/1494] drm/ttm/drivers: call the bind function directly. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now the bind functions have all the protection explicitly the drivers can just call them directly, and the api can be unexported Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-5-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +++++- drivers/gpu/drm/nouveau/nouveau_bo.c | 5 ++++- drivers/gpu/drm/radeon/radeon_ttm.c | 6 +++++- drivers/gpu/drm/ttm/ttm_bo.c | 1 - 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 2028b9e4c25cf..a57aaf6663403 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -63,6 +63,10 @@ #define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128 +static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_resource *bo_mem); + static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, unsigned int type, uint64_t size) @@ -552,7 +556,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, goto out_cleanup; /* Bind the memory to the GTT space */ - r = ttm_bo_tt_bind(bo, &tmp_mem); + r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 4a020a3da3ddf..56f974c28eb51 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -44,6 +44,9 @@ #include <nvif/if500b.h> #include <nvif/if900b.h> +static int nouveau_ttm_tt_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, + struct ttm_resource *reg); + /* * NV10-NV40 tiling helpers */ @@ -927,7 +930,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = ttm_bo_tt_bind(bo, &tmp_reg); + ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_reg); if (ret) goto out; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 03e5ae4e3bf66..99d9ca1087b77 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -56,6 +56,10 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev); static void radeon_ttm_debugfs_fini(struct radeon_device *rdev); +static int radeon_ttm_tt_bind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm, + struct ttm_resource *bo_mem); + struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) { struct radeon_mman *mman; @@ -238,7 +242,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo, goto out_cleanup; } - r = ttm_bo_tt_bind(bo, &tmp_mem); + r = radeon_ttm_tt_bind(bo->bdev, bo->ttm, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b814d0c9bc8a8..323c3c9647829 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1627,7 +1627,6 @@ int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem) { return bo->bdev->driver->ttm_tt_bind(bo->bdev, bo->ttm, mem); } -EXPORT_SYMBOL(ttm_bo_tt_bind); void ttm_bo_tt_unbind(struct ttm_buffer_object *bo) { -- GitLab From 2ee476f77ffe5a7ecbd4e1e20fa0859cb541530d Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 14:03:46 +1000 Subject: [PATCH 1277/1494] drm/ttm: add a simple assign mem to bo wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pattern is called in a few places, just clean it up. Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-6-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_util.c | 18 ++++++------------ include/drm/ttm/ttm_bo_driver.h | 10 ++++++++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 919489f6a5a33..5a8d77ef504f2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -87,9 +87,7 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo, return ret; } - *old_mem = *new_mem; - new_mem->mm_node = NULL; - + ttm_bo_assign_mem(bo, new_mem); return 0; } EXPORT_SYMBOL(ttm_bo_move_ttm); @@ -299,8 +297,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, mb(); out2: old_copy = *old_mem; - *old_mem = *new_mem; - new_mem->mm_node = NULL; + + ttm_bo_assign_mem(bo, new_mem); if (!man->use_tt) ttm_bo_tt_destroy(bo); @@ -535,7 +533,6 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, { struct ttm_bo_device *bdev = bo->bdev; struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); - struct ttm_resource *old_mem = &bo->mem; int ret; struct ttm_buffer_object *ghost_obj; @@ -582,8 +579,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, ttm_bo_put(ghost_obj); } - *old_mem = *new_mem; - new_mem->mm_node = NULL; + ttm_bo_assign_mem(bo, new_mem); return 0; } @@ -594,9 +590,8 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, struct ttm_resource *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_resource *old_mem = &bo->mem; - struct ttm_resource_manager *from = ttm_manager_type(bdev, old_mem->mem_type); + struct ttm_resource_manager *from = ttm_manager_type(bdev, bo->mem.mem_type); struct ttm_resource_manager *to = ttm_manager_type(bdev, new_mem->mem_type); int ret; @@ -673,8 +668,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, ttm_bo_free_old_node(bo); } - *old_mem = *new_mem; - new_mem->mm_node = NULL; + ttm_bo_assign_mem(bo, new_mem); return 0; } diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 7846dfa507f7f..25cc932d63f1d 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -539,6 +539,13 @@ static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo spin_unlock(&ttm_bo_glob.lru_lock); } +static inline void ttm_bo_assign_mem(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + bo->mem = *new_mem; + new_mem->mm_node = NULL; +} + /** * ttm_bo_move_null = assign memory for a buffer object. * @bo: The bo to assign the memory to @@ -552,8 +559,7 @@ static inline void ttm_bo_move_null(struct ttm_buffer_object *bo, struct ttm_resource *old_mem = &bo->mem; WARN_ON(old_mem->mm_node != NULL); - *old_mem = *new_mem; - new_mem->mm_node = NULL; + ttm_bo_assign_mem(bo, new_mem); } /** -- GitLab From 13a8f46d8030e519939bfb674f7aa541109f6ce2 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 14:08:29 +1000 Subject: [PATCH 1278/1494] drm/ttm: move ghost object creation to a common function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both accel cleanup and pipeline move had the same code, make a single function for it. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-7-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_util.c | 104 ++++++++++++------------------ 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 5a8d77ef504f2..8a6841454ce78 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -526,6 +526,46 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) } EXPORT_SYMBOL(ttm_bo_kunmap); +static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo, + struct dma_fence *fence, + bool dst_use_tt) +{ + struct ttm_buffer_object *ghost_obj; + int ret; + + /** + * This should help pipeline ordinary buffer moves. + * + * Hang old buffer memory on a new buffer object, + * and leave it to be released when the GPU + * operation has completed. + */ + + dma_fence_put(bo->moving); + bo->moving = dma_fence_get(fence); + + ret = ttm_buffer_object_transfer(bo, &ghost_obj); + if (ret) + return ret; + + dma_resv_add_excl_fence(&ghost_obj->base._resv, fence); + + /** + * If we're not moving to fixed memory, the TTM object + * needs to stay alive. Otherwhise hang it on the ghost + * bo to be unbound and destroyed. + */ + + if (dst_use_tt) + ghost_obj->ttm = NULL; + else + bo->ttm = NULL; + + dma_resv_unlock(&ghost_obj->base._resv); + ttm_bo_put(ghost_obj); + return 0; +} + int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, @@ -534,7 +574,6 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct ttm_bo_device *bdev = bo->bdev; struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); int ret; - struct ttm_buffer_object *ghost_obj; dma_resv_add_excl_fence(bo->base.resv, fence); if (evict) { @@ -546,37 +585,9 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, ttm_bo_tt_destroy(bo); ttm_bo_free_old_node(bo); } else { - /** - * This should help pipeline ordinary buffer moves. - * - * Hang old buffer memory on a new buffer object, - * and leave it to be released when the GPU - * operation has completed. - */ - - dma_fence_put(bo->moving); - bo->moving = dma_fence_get(fence); - - ret = ttm_buffer_object_transfer(bo, &ghost_obj); + ret = ttm_bo_move_to_ghost(bo, fence, man->use_tt); if (ret) return ret; - - dma_resv_add_excl_fence(&ghost_obj->base._resv, fence); - - /** - * If we're not moving to fixed memory, the TTM object - * needs to stay alive. Otherwhise hang it on the ghost - * bo to be unbound and destroyed. - */ - - if (man->use_tt) { - ghost_obj->ttm = NULL; - } else { - bo->ttm = NULL; - } - - dma_resv_unlock(&ghost_obj->base._resv); - ttm_bo_put(ghost_obj); } ttm_bo_assign_mem(bo, new_mem); @@ -599,40 +610,9 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, dma_resv_add_excl_fence(bo->base.resv, fence); if (!evict) { - struct ttm_buffer_object *ghost_obj; - - /** - * This should help pipeline ordinary buffer moves. - * - * Hang old buffer memory on a new buffer object, - * and leave it to be released when the GPU - * operation has completed. - */ - - dma_fence_put(bo->moving); - bo->moving = dma_fence_get(fence); - - ret = ttm_buffer_object_transfer(bo, &ghost_obj); + ret = ttm_bo_move_to_ghost(bo, fence, to->use_tt); if (ret) return ret; - - dma_resv_add_excl_fence(&ghost_obj->base._resv, fence); - - /** - * If we're not moving to fixed memory, the TTM object - * needs to stay alive. Otherwhise hang it on the ghost - * bo to be unbound and destroyed. - */ - - if (to->use_tt) { - ghost_obj->ttm = NULL; - } else { - bo->ttm = NULL; - } - - dma_resv_unlock(&ghost_obj->base._resv); - ttm_bo_put(ghost_obj); - } else if (!from->use_tt) { /** -- GitLab From 92afce9095300cb652ea74a617c6679c4c4d4429 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 14:13:06 +1000 Subject: [PATCH 1279/1494] drm/ttm: make common function for wait/free node path. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pipeline and accel cleansups has similiar paths here. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917043040.146575-8-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo_util.c | 38 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 8a6841454ce78..ee4484ccbd1e5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -526,6 +526,20 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) } EXPORT_SYMBOL(ttm_bo_kunmap); +static int ttm_bo_wait_free_node(struct ttm_buffer_object *bo, + bool dst_use_tt) +{ + int ret; + ret = ttm_bo_wait(bo, false, false); + if (ret) + return ret; + + if (!dst_use_tt) + ttm_bo_tt_destroy(bo); + ttm_bo_free_old_node(bo); + return 0; +} + static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo, struct dma_fence *fence, bool dst_use_tt) @@ -576,19 +590,12 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, int ret; dma_resv_add_excl_fence(bo->base.resv, fence); - if (evict) { - ret = ttm_bo_wait(bo, false, false); - if (ret) - return ret; - - if (!man->use_tt) - ttm_bo_tt_destroy(bo); - ttm_bo_free_old_node(bo); - } else { + if (evict) + ret = ttm_bo_wait_free_node(bo, man->use_tt); + else ret = ttm_bo_move_to_ghost(bo, fence, man->use_tt); - if (ret) - return ret; - } + if (ret) + return ret; ttm_bo_assign_mem(bo, new_mem); @@ -638,14 +645,9 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, * * Should never happen in pratice. */ - - ret = ttm_bo_wait(bo, false, false); + ret = ttm_bo_wait_free_node(bo, to->use_tt); if (ret) return ret; - - if (!to->use_tt) - ttm_bo_tt_destroy(bo); - ttm_bo_free_old_node(bo); } ttm_bo_assign_mem(bo, new_mem); -- GitLab From e46f468fef953dea30e7a7c69ad7e0370af26855 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 16:36:14 +1000 Subject: [PATCH 1280/1494] drm/ttm: drop special pipeline accel cleanup function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two accel cleanup paths were mostly the same once refactored. Just pass a bool to say if the evictions are to be pipelined. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917064132.148521-2-airlied@gmail.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo_util.c | 89 +++++++++---------------- include/drm/ttm/ttm_bo_driver.h | 17 +---- 5 files changed, 38 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a57aaf6663403..e7b67dc330a4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -500,9 +500,9 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, /* Always block for VM page tables before committing the new location */ if (bo->type == ttm_bo_type_kernel) - r = ttm_bo_move_accel_cleanup(bo, fence, true, new_mem); + r = ttm_bo_move_accel_cleanup(bo, fence, true, false, new_mem); else - r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); + r = ttm_bo_move_accel_cleanup(bo, fence, evict, true, new_mem); dma_fence_put(fence); return r; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 56f974c28eb51..2ee75646ad6fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -824,7 +824,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, if (ret == 0) { ret = ttm_bo_move_accel_cleanup(bo, &fence->base, - evict, + evict, false, new_reg); nouveau_fence_unref(&fence); } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 99d9ca1087b77..36150b7f31a90 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -200,7 +200,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, if (IS_ERR(fence)) return PTR_ERR(fence); - r = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, new_mem); + r = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false, new_mem); radeon_fence_unref(&fence); return r; } diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index ee4484ccbd1e5..fb2a25f8408fc 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -580,81 +580,56 @@ static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo, return 0; } -int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - struct dma_fence *fence, - bool evict, - struct ttm_resource *new_mem) +static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo, + struct dma_fence *fence) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); - int ret; + struct ttm_resource_manager *from = ttm_manager_type(bdev, bo->mem.mem_type); - dma_resv_add_excl_fence(bo->base.resv, fence); - if (evict) - ret = ttm_bo_wait_free_node(bo, man->use_tt); - else - ret = ttm_bo_move_to_ghost(bo, fence, man->use_tt); - if (ret) - return ret; + /** + * BO doesn't have a TTM we need to bind/unbind. Just remember + * this eviction and free up the allocation + */ + spin_lock(&from->move_lock); + if (!from->move || dma_fence_is_later(fence, from->move)) { + dma_fence_put(from->move); + from->move = dma_fence_get(fence); + } + spin_unlock(&from->move_lock); - ttm_bo_assign_mem(bo, new_mem); + ttm_bo_free_old_node(bo); - return 0; + dma_fence_put(bo->moving); + bo->moving = dma_fence_get(fence); } -EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); -int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct dma_fence *fence, bool evict, - struct ttm_resource *new_mem) +int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, + struct dma_fence *fence, + bool evict, + bool pipeline, + struct ttm_resource *new_mem) { struct ttm_bo_device *bdev = bo->bdev; - struct ttm_resource_manager *from = ttm_manager_type(bdev, bo->mem.mem_type); - struct ttm_resource_manager *to = ttm_manager_type(bdev, new_mem->mem_type); - - int ret; + struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); + int ret = 0; dma_resv_add_excl_fence(bo->base.resv, fence); + if (!evict) + ret = ttm_bo_move_to_ghost(bo, fence, man->use_tt); + else if (!from->use_tt && pipeline) + ttm_bo_move_pipeline_evict(bo, fence); + else + ret = ttm_bo_wait_free_node(bo, man->use_tt); - if (!evict) { - ret = ttm_bo_move_to_ghost(bo, fence, to->use_tt); - if (ret) - return ret; - } else if (!from->use_tt) { - - /** - * BO doesn't have a TTM we need to bind/unbind. Just remember - * this eviction and free up the allocation - */ - - spin_lock(&from->move_lock); - if (!from->move || dma_fence_is_later(fence, from->move)) { - dma_fence_put(from->move); - from->move = dma_fence_get(fence); - } - spin_unlock(&from->move_lock); - - ttm_bo_free_old_node(bo); - - dma_fence_put(bo->moving); - bo->moving = dma_fence_get(fence); - - } else { - /** - * Last resort, wait for the move to be completed. - * - * Should never happen in pratice. - */ - ret = ttm_bo_wait_free_node(bo, to->use_tt); - if (ret) - return ret; - } + if (ret) + return ret; ttm_bo_assign_mem(bo, new_mem); return 0; } -EXPORT_SYMBOL(ttm_bo_pipeline_move); +EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) { diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 25cc932d63f1d..864afa8f6f18f 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -642,6 +642,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); * @bo: A pointer to a struct ttm_buffer_object. * @fence: A fence object that signals when moving is complete. * @evict: This is an evict move. Don't return until the buffer is idle. + * @pipeline: evictions are to be pipelined. * @new_mem: struct ttm_resource indicating where to move. * * Accelerated move function to be called when an accelerated move @@ -653,23 +654,9 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo); */ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, + bool pipeline, struct ttm_resource *new_mem); -/** - * ttm_bo_pipeline_move. - * - * @bo: A pointer to a struct ttm_buffer_object. - * @fence: A fence object that signals when moving is complete. - * @evict: This is an evict move. Don't return until the buffer is idle. - * @new_mem: struct ttm_resource indicating where to move. - * - * Function for pipelining accelerated moves. Either free the memory - * immediately or hang it on a temporary buffer object. - */ -int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct dma_fence *fence, bool evict, - struct ttm_resource *new_mem); - /** * ttm_bo_pipeline_gutting. * -- GitLab From 4856e5aa0ef1d4c62f6f30bf273a778735507837 Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 17 Sep 2020 16:13:03 +1000 Subject: [PATCH 1281/1494] drm/ttm: drop evicted from ttm_bo. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was unused. Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917064132.148521-3-airlied@gmail.com --- drivers/gpu/drm/ttm/ttm_bo.c | 4 ---- include/drm/ttm/ttm_bo_api.h | 1 - 2 files changed, 5 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 323c3c9647829..70b3bee27850d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -298,8 +298,6 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, } moved: - bo->evicted = false; - ctx->bytes_moved += bo->num_pages << PAGE_SHIFT; return 0; @@ -638,9 +636,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, if (ret != -ERESTARTSYS) pr_err("Buffer eviction failed\n"); ttm_resource_free(bo, &evict_mem); - goto out; } - bo->evicted = true; out: return ret; } diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index fd8d29f5f3704..0f7cd21d6d748 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -141,7 +141,6 @@ struct ttm_buffer_object { struct ttm_resource mem; struct file *persistent_swap_storage; struct ttm_tt *ttm; - bool evicted; bool deleted; /** -- GitLab From 8fea92536e3efff14fa4cde7ed37c595b40a52b5 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi <rodrigo.vivi@intel.com> Date: Thu, 17 Sep 2020 16:43:57 -0400 Subject: [PATCH 1282/1494] drm/i915: Update DRIVER_DATE to 20200917 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8c62b5c41d058..72a9449b674ed 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -108,8 +108,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20200914" -#define DRIVER_TIMESTAMP 1600112063 +#define DRIVER_DATE "20200917" +#define DRIVER_TIMESTAMP 1600375437 struct drm_i915_gem_object; -- GitLab From 4bdd4d25ed0d31e50e77ca2b37d4b97c0d5a9a2f Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 1 Sep 2020 10:23:34 +0800 Subject: [PATCH 1283/1494] drm/amd/pm: wrapper for postponing some setup job after DAL initializatioa(V2) So that ASIC specific actions can be added. V2: better namings Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 6 ++++++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index d22a759b6b435..4acc3c4c4737c 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -600,6 +600,7 @@ struct pptable_funcs { int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); int (*deep_sleep_control)(struct smu_context *smu, bool enablement); int (*get_fan_parameters)(struct smu_context *smu); + int (*post_init)(struct smu_context *smu); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7618f9972b8c3..e8c2fa637a614 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -473,6 +473,12 @@ static int smu_late_init(void *handle) if (!smu->pm_enabled) return 0; + ret = smu_post_init(smu); + if (ret) { + dev_err(adev->dev, "Failed to post smu init!\n"); + return ret; + } + ret = smu_set_default_od_settings(smu); if (ret) { dev_err(adev->dev, "Failed to setup default OD settings!\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 38c10177ed212..db903889f6a76 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -95,6 +95,7 @@ #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) #define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement) #define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu) +#define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu) #endif #endif -- GitLab From 10144762e2c37093fed8e2fcac7fbe2bcbb87e54 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 1 Sep 2020 11:02:31 +0800 Subject: [PATCH 1284/1494] drm/amd/pm: postpone SOCCLK/UCLK enablement after DAL initialization(V2) This is needed for Navi1X only. And it may help for display missing or hang issue seen on some high resolution monitors. V2: no UCLK DPM enablement for Navi10 A0 secure SKU Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 60 ++++++++++++------- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 6 +- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 4 ++ 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 42d53cca73600..8180b7f999916 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -279,9 +279,6 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, | FEATURE_MASK(FEATURE_FW_CTF_BIT) | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT); - if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); - if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); @@ -291,11 +288,6 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT); - if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); - if (adev->pm.pp_feature & PP_ULV_MASK) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT); @@ -320,19 +312,12 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, if (smu->dc_controlled_by_gpio) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT); - /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ - if (is_asic_secure(smu)) { - /* only for navi10 A0 */ - if ((adev->asic_type == CHIP_NAVI10) && - (adev->rev_id == 0)) { - *(uint64_t *)feature_mask &= - ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT)); - *(uint64_t *)feature_mask &= - ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); - } - } + /* DS SOCCLK enablement should be skipped for navi10 A0 secure board */ + if (is_asic_secure(smu) && + (adev->asic_type == CHIP_NAVI10) && + (adev->rev_id == 0)) + *(uint64_t *)feature_mask &= + ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); return 0; } @@ -2578,6 +2563,38 @@ static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) NULL); } +static int navi10_post_smu_init(struct smu_context *smu) +{ + struct smu_feature *feature = &smu->smu_feature; + struct amdgpu_device *adev = smu->adev; + uint64_t feature_mask = 0; + + /* For Naiv1x, enable these features only after DAL initialization */ + if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) + feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + /* DPM UCLK enablement should be skipped for navi10 A0 secure board */ + if (!(is_asic_secure(smu) && + (adev->asic_type == CHIP_NAVI10) && + (adev->rev_id == 0)) && + (adev->pm.pp_feature & PP_MCLK_DPM_MASK)) + feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) + | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) + | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); + + if (!feature_mask) + return 0; + + bitmap_or(feature->allowed, + feature->allowed, + (unsigned long *)(&feature_mask), + SMU_FEATURE_MAX); + + return smu_cmn_feature_update_enable_state(smu, + feature_mask, + true); +} + static const struct pptable_funcs navi10_ppt_funcs = { .get_allowed_feature_mask = navi10_get_allowed_feature_mask, .set_default_dpm_table = navi10_set_default_dpm_table, @@ -2661,6 +2678,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, .get_fan_parameters = navi10_get_fan_parameters, + .post_init = navi10_post_smu_init, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 97aa72a946312..c30d3338825fa 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -346,9 +346,9 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, return ret; } -static int smu_cmn_feature_update_enable_state(struct smu_context *smu, - uint64_t feature_mask, - bool enabled) +int smu_cmn_feature_update_enable_state(struct smu_context *smu, + uint64_t feature_mask, + bool enabled) { struct smu_feature *feature = &smu->smu_feature; int ret = 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 6d00ad740c278..ab577be23c15b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -52,6 +52,10 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); +int smu_cmn_feature_update_enable_state(struct smu_context *smu, + uint64_t feature_mask, + bool enabled); + int smu_cmn_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask, bool enable); -- GitLab From 82cac71c1b646e581bd4f5c054982fcaf5b9f70f Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Tue, 1 Sep 2020 11:33:53 +0800 Subject: [PATCH 1285/1494] drm/amd/pm: put Navi1X umc cdr workaround in post_smu_init That's where the uclk dpm get enabled and then the uclk cdr workaround can be applied. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 6 ------ .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 18 ++++++++++++++---- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 - 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 4acc3c4c4737c..701a94d4b9f6d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -590,7 +590,6 @@ struct pptable_funcs { int (*mode2_reset)(struct smu_context *smu); int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max); int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max); - int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu); int (*set_power_source)(struct smu_context *smu, enum smu_power_src_type power_src); void (*log_thermal_throttling_event)(struct smu_context *smu); size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index e8c2fa637a614..d068142719776 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -975,12 +975,6 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - ret = smu_disable_umc_cdr_12gbps_workaround(smu); - if (ret) { - dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n"); - return ret; - } - /* * For Navi1X, manually switch it to AC mode as PMFW * may boot it with DC mode. diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 8180b7f999916..6674f3abd4575 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2568,6 +2568,7 @@ static int navi10_post_smu_init(struct smu_context *smu) struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; uint64_t feature_mask = 0; + int ret = 0; /* For Naiv1x, enable these features only after DAL initialization */ if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) @@ -2590,9 +2591,19 @@ static int navi10_post_smu_init(struct smu_context *smu) (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - return smu_cmn_feature_update_enable_state(smu, - feature_mask, - true); + ret = smu_cmn_feature_update_enable_state(smu, + feature_mask, + true); + if (ret) { + dev_err(adev->dev, "Failed to post uclk/socclk dpm enablement!\n"); + return ret; + } + + ret = navi10_disable_umc_cdr_12gbps_workaround(smu); + if (ret) + dev_err(adev->dev, "Failed to apply umc cdr workaround!\n"); + + return ret; } static const struct pptable_funcs navi10_ppt_funcs = { @@ -2669,7 +2680,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_default_od_settings = navi10_set_default_od_settings, .od_edit_dpm_table = navi10_od_edit_dpm_table, .run_btc = navi10_run_btc, - .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround, .set_power_source = smu_v11_0_set_power_source, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index db903889f6a76..521b805c920e5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -83,7 +83,6 @@ #define smu_asic_set_performance_level(smu, level) smu_ppt_funcs(set_performance_level, -EINVAL, smu, level) #define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) #define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) -#define smu_disable_umc_cdr_12gbps_workaround(smu) smu_ppt_funcs(disable_umc_cdr_12gbps_workaround, 0, smu) #define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) #define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control) #define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) -- GitLab From 3646c00e74b26b90043353b8cc7475670a625fae Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 16:50:30 +0800 Subject: [PATCH 1286/1494] drm/amd/pm: revise the umc hybrid cdr workaround Drop the unused message(SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE). And do not apply this workaround when the max uclk frequency is greater than 750Mhz. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 6674f3abd4575..79cd17d6bfaa4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2181,18 +2181,6 @@ static int navi10_run_btc(struct smu_context *smu) return ret; } -static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable) -{ - int result = 0; - - if (!enable) - result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); - else - result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); - - return result; -} - static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev) { if (adev->asic_type != CHIP_NAVI10) @@ -2208,32 +2196,32 @@ static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *a return false; } -static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) +static int navi10_umc_hybrid_cdr_workaround(struct smu_context *smu) { uint32_t uclk_count, uclk_min, uclk_max; - uint32_t smu_version; int ret = 0; - if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) - return 0; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) - return ret; - - /* This workaround is available only for 42.50 or later SMC firmwares */ - if (smu_version < 0x2A3200) + /* This workaround can be applied only with uclk dpm enabled */ + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) return 0; ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); if (ret) return ret; - ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); if (ret) return ret; - ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); + /* + * The NAVI10_UMC_HYBRID_CDR_WORKAROUND_UCLK_THRESHOLD is 750Mhz. + * This workaround is needed only when the max uclk frequency + * not greater than that. + */ + if (uclk_max > 0x2EE) + return 0; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); if (ret) return ret; @@ -2250,8 +2238,27 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) /* * In this case, SMU already disabled dummy pstate during enablement * of UCLK DPM, we have to re-enabled it. - * */ - return navi10_dummy_pstate_control(smu, true); + */ + return smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); +} + +static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) +{ + uint32_t smu_version; + int ret = 0; + + if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) + return 0; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) + return ret; + + /* This workaround is available only for 42.50 or later SMC firmwares */ + if (smu_version < 0x2A3200) + return 0; + + return navi10_umc_hybrid_cdr_workaround(smu); } static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, -- GitLab From 2379be2faf09b3e270796bb6a43941634d39c626 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 16:10:29 +0800 Subject: [PATCH 1287/1494] drm/amd/pm: allocate a new buffer for pstate dummy reading This dummy reading buffer will be used for the new Navi1x UMC CDR workaround. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 45 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 701a94d4b9f6d..29e041d86ae5d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -270,6 +270,7 @@ struct smu_table_context */ struct smu_table driver_table; struct smu_table memory_pool; + struct smu_table dummy_read_1_table; uint8_t thermal_controller_type; void *overdrive_table; diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index d068142719776..bce723a1badaf 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -663,6 +663,45 @@ static int smu_free_memory_pool(struct smu_context *smu) return 0; } +static int smu_alloc_dummy_read_table(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *dummy_read_1_table = + &smu_table->dummy_read_1_table; + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + dummy_read_1_table->size = 0x40000; + dummy_read_1_table->align = PAGE_SIZE; + dummy_read_1_table->domain = AMDGPU_GEM_DOMAIN_VRAM; + + ret = amdgpu_bo_create_kernel(adev, + dummy_read_1_table->size, + dummy_read_1_table->align, + dummy_read_1_table->domain, + &dummy_read_1_table->bo, + &dummy_read_1_table->mc_address, + &dummy_read_1_table->cpu_addr); + if (ret) + dev_err(adev->dev, "VRAM allocation for dummy read table failed!\n"); + + return ret; +} + +static void smu_free_dummy_read_table(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *dummy_read_1_table = + &smu_table->dummy_read_1_table; + + + amdgpu_bo_free_kernel(&dummy_read_1_table->bo, + &dummy_read_1_table->mc_address, + &dummy_read_1_table->cpu_addr); + + memset(dummy_read_1_table, 0, sizeof(struct smu_table)); +} + static int smu_smc_table_sw_init(struct smu_context *smu) { int ret; @@ -698,6 +737,10 @@ static int smu_smc_table_sw_init(struct smu_context *smu) if (ret) return ret; + ret = smu_alloc_dummy_read_table(smu); + if (ret) + return ret; + ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); if (ret) return ret; @@ -711,6 +754,8 @@ static int smu_smc_table_sw_fini(struct smu_context *smu) smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + smu_free_dummy_read_table(smu); + ret = smu_free_memory_pool(smu); if (ret) return ret; -- GitLab From 665945eb49d559588633ca8653d4e9e437161df8 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 17:58:29 +0800 Subject: [PATCH 1288/1494] drm/amd/pm: implement a new umc cdr workaround By uploading dummy pstate tables. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h | 194 ++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/smu_types.h | 2 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h | 5 +- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 34 +++ 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h b/drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h new file mode 100644 index 0000000000000..beab6d7b28b70 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h @@ -0,0 +1,194 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + +#ifndef SMU_11_0_CDR_TABLE +#define SMU_11_0_CDR_TABLE + + +#pragma pack(push, 1) + +/// CDR table : PRBS sequence for DQ toggles + +/*static unsigned int NoDbiPrbs7[] = +{ +//256 bytes, 256 byte aligned +0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, +0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, +0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, +0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, +}; + + +static unsigned int DbiPrbs7[] = +{ +// 256 bytes, 256 byte aligned +0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, +0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, +0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, +0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, +}; +*/ + + +//4096 bytes, 256 byte aligned +static unsigned int NoDbiPrbs7[] = +{ + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, + 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0x0f0f0f0f, 0x0f0f0f0f, 0xf0f0f0f0, 0xf0f00f0f, + 0x0f0f0f0f, 0xf0f00f0f, 0x0f0ff0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0xf0f00f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0x0f0ff0f0, 0xf0f00f0f, + 0xf0f00f0f, 0x0f0ff0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0ff0f0, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f0f0f0, 0x0f0f0f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f00f0f, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0f0f0, 0xf0f0ffff, +}; + +// 4096 bytes, 256 byte aligned +static unsigned int DbiPrbs7[] = +{ + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x0000ffff, 0x0000ffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0x00000000, 0xffffffff, 0x00000000, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x00000000, 0x0000ffff, + 0xffffffff, 0x0000ffff, 0xffff0000, 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x0000ffff, 0x00000000, 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000, 0xffffffff, 0xffff0000, 0x0000ffff, + 0x0000ffff, 0xffff0000, 0xffff0000, 0x00000000, 0xffff0000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff, +}; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h index 7b585e205a5a0..4a8655a20ef6b 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h @@ -173,6 +173,8 @@ __SMU_DUMMY_MAP(GmiPwrDnControl), \ __SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE), \ __SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \ + __SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH), \ + __SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW), \ __SMU_DUMMY_MAP(Mode1Reset), \ #undef __SMU_DUMMY_MAP diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h index fa0174dc7e0ea..fc8594e9b2bd1 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h @@ -125,7 +125,10 @@ #define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x4C -#define PPSMC_Message_Count 0x4D +#define PPSMC_MSG_SetDriverDummyTableDramAddrHigh 0x4E +#define PPSMC_MSG_SetDriverDummyTableDramAddrLow 0x4F + +#define PPSMC_Message_Count 0x50 typedef uint32_t PPSMC_Result; typedef uint32_t PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 79cd17d6bfaa4..061eee1a4c328 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -45,6 +45,7 @@ #include "asic_reg/mp/mp_11_0_sh_mask.h" #include "smu_cmn.h" +#include "smu_11_0_cdr_table.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -139,6 +140,8 @@ static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), + MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH, PPSMC_MSG_SetDriverDummyTableDramAddrHigh, 0), + MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW, PPSMC_MSG_SetDriverDummyTableDramAddrLow, 0), }; static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { @@ -2242,6 +2245,37 @@ static int navi10_umc_hybrid_cdr_workaround(struct smu_context *smu) return smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); } +static int navi10_set_dummy_pstates_table_location(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *dummy_read_table = + &smu_table->dummy_read_1_table; + char *dummy_table = dummy_read_table->cpu_addr; + int ret = 0; + uint32_t i; + + for (i = 0; i < 0x40000; i += 0x1000 * 2) { + memcpy(dummy_table, &NoDbiPrbs7[0], 0x1000); + dummy_table += 0x1000; + memcpy(dummy_table, &DbiPrbs7[0], 0x1000); + dummy_table += 0x1000; + } + + amdgpu_asic_flush_hdp(smu->adev, NULL); + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH, + upper_32_bits(dummy_read_table->mc_address), + NULL); + if (ret) + return ret; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW, + lower_32_bits(dummy_read_table->mc_address), + NULL); +} + static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) { uint32_t smu_version; -- GitLab From bb7257b5a8b0182019df3b9819417301978d7538 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 18:19:28 +0800 Subject: [PATCH 1289/1494] drm/amd/pm: apply the CDR workarounds only with some specific UMC firmwares(V2) And different workaround will be applied based on hybrid cdr bit. V2: add pmfw version guard to make sure the new workaround applied only with pmfw >= 42.53.0 Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_types.h | 1 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h | 4 +- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 53 ++++++++++++++++--- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h index 4a8655a20ef6b..35fc46d3c9c03 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h @@ -175,6 +175,7 @@ __SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \ __SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH), \ __SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW), \ + __SMU_DUMMY_MAP(GET_UMC_FW_WA), \ __SMU_DUMMY_MAP(Mode1Reset), \ #undef __SMU_DUMMY_MAP diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h index fc8594e9b2bd1..26181b679098a 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h @@ -128,7 +128,9 @@ #define PPSMC_MSG_SetDriverDummyTableDramAddrHigh 0x4E #define PPSMC_MSG_SetDriverDummyTableDramAddrLow 0x4F -#define PPSMC_Message_Count 0x50 +#define PPSMC_MSG_GetUMCFWWA 0x50 + +#define PPSMC_Message_Count 0x51 typedef uint32_t PPSMC_Result; typedef uint32_t PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 061eee1a4c328..5c6243dd7dd46 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -142,6 +142,7 @@ static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH, PPSMC_MSG_SetDriverDummyTableDramAddrHigh, 0), MSG_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW, PPSMC_MSG_SetDriverDummyTableDramAddrLow, 0), + MSG_MAP(GET_UMC_FW_WA, PPSMC_MSG_GetUMCFWWA, 0), }; static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { @@ -2278,21 +2279,57 @@ static int navi10_set_dummy_pstates_table_location(struct smu_context *smu) static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) { - uint32_t smu_version; + struct amdgpu_device *adev = smu->adev; + uint8_t umc_fw_greater_than_v136 = false; + uint8_t umc_fw_disable_cdr = false; + uint32_t pmfw_version; + uint32_t param; int ret = 0; - if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) + if (!navi10_need_umc_cdr_12gbps_workaround(adev)) return 0; - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) + ret = smu_cmn_get_smc_version(smu, NULL, &pmfw_version); + if (ret) { + dev_err(adev->dev, "Failed to get smu version!\n"); return ret; + } - /* This workaround is available only for 42.50 or later SMC firmwares */ - if (smu_version < 0x2A3200) - return 0; + /* + * The messages below are only supported by 42.53.0 and later + * PMFWs. + * - PPSMC_MSG_SetDriverDummyTableDramAddrHigh + * - PPSMC_MSG_SetDriverDummyTableDramAddrLow + * - PPSMC_MSG_GetUMCFWWA + */ + if (pmfw_version >= 0x2a3500) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GET_UMC_FW_WA, + 0, + ¶m); + if (ret) + return ret; + + /* First bit indicates if the UMC f/w is above v137 */ + umc_fw_greater_than_v136 = param & 0x1; + + /* Second bit indicates if hybrid-cdr is disabled */ + umc_fw_disable_cdr = param & 0x2; - return navi10_umc_hybrid_cdr_workaround(smu); + /* w/a only allowed if UMC f/w is <= 136 */ + if (umc_fw_greater_than_v136) + return 0; + + if (umc_fw_disable_cdr && adev->asic_type == CHIP_NAVI10) + return navi10_umc_hybrid_cdr_workaround(smu); + else + return navi10_set_dummy_pstates_table_location(smu); + } else { + if (adev->asic_type == CHIP_NAVI10) + return navi10_umc_hybrid_cdr_workaround(smu); + } + + return 0; } static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, -- GitLab From eb5f69e7660f2b2ff23a362f1b33a74e078e1508 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 18:27:09 +0800 Subject: [PATCH 1290/1494] drm/amd/pm: correct the requirement for umc cdr workaround The workaround can be applied only with UCLK DPM enabled. And expand the workaround to more Navi10 SKUs and also Navi14. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 5c6243dd7dd46..64166b25bd131 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2185,19 +2185,18 @@ static int navi10_run_btc(struct smu_context *smu) return ret; } -static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev) +static bool navi10_need_umc_cdr_12gbps_workaround(struct smu_context *smu) { - if (adev->asic_type != CHIP_NAVI10) + struct amdgpu_device *adev = smu->adev; + + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) return false; - if (adev->pdev->device == 0x731f && - (adev->pdev->revision == 0xc2 || - adev->pdev->revision == 0xc3 || - adev->pdev->revision == 0xca || - adev->pdev->revision == 0xcb)) + if (adev->asic_type == CHIP_NAVI10 || + adev->asic_type == CHIP_NAVI14) return true; - else - return false; + + return false; } static int navi10_umc_hybrid_cdr_workaround(struct smu_context *smu) @@ -2286,7 +2285,7 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) uint32_t param; int ret = 0; - if (!navi10_need_umc_cdr_12gbps_workaround(adev)) + if (!navi10_need_umc_cdr_12gbps_workaround(smu)) return 0; ret = smu_cmn_get_smc_version(smu, NULL, &pmfw_version); -- GitLab From 12f04120d393102b56bbbfdcfec47aa839dfc69f Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 26 Aug 2020 18:37:00 +0800 Subject: [PATCH 1291/1494] drm/amd/pm: make namings and comments more readable And to fit more accurately what the cod does. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 64166b25bd131..3559ba05a59cc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2185,7 +2185,7 @@ static int navi10_run_btc(struct smu_context *smu) return ret; } -static bool navi10_need_umc_cdr_12gbps_workaround(struct smu_context *smu) +static bool navi10_need_umc_cdr_workaround(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -2276,7 +2276,7 @@ static int navi10_set_dummy_pstates_table_location(struct smu_context *smu) NULL); } -static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) +static int navi10_run_umc_cdr_workaround(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint8_t umc_fw_greater_than_v136 = false; @@ -2285,7 +2285,7 @@ static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) uint32_t param; int ret = 0; - if (!navi10_need_umc_cdr_12gbps_workaround(smu)) + if (!navi10_need_umc_cdr_workaround(smu)) return 0; ret = smu_cmn_get_smc_version(smu, NULL, &pmfw_version); @@ -2676,7 +2676,7 @@ static int navi10_post_smu_init(struct smu_context *smu) return ret; } - ret = navi10_disable_umc_cdr_12gbps_workaround(smu); + ret = navi10_run_umc_cdr_workaround(smu); if (ret) dev_err(adev->dev, "Failed to apply umc cdr workaround!\n"); -- GitLab From b66effb18a55eaf81fcb9147b7454151b0655f23 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 24 Aug 2020 15:11:47 +0800 Subject: [PATCH 1292/1494] drm/amd/pm: drop unnecessary feature->mutex lock protections(V2) As these operations are performed in hardware setup and there is actually no race conditions during this period considering: 1. the hardware setup is serial and cannot be in parallel 2. all other operations can be performed only after hardware setup complete. V2: rich the commit log description Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 ---- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 2 -- 2 files changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index bce723a1badaf..b98decaa06460 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -361,20 +361,16 @@ static int smu_get_driver_allowed_feature_mask(struct smu_context *smu) int ret = 0; uint32_t allowed_feature_mask[SMU_FEATURE_MAX/32]; - mutex_lock(&feature->mutex); bitmap_zero(feature->allowed, SMU_FEATURE_MAX); - mutex_unlock(&feature->mutex); ret = smu_get_allowed_feature_mask(smu, allowed_feature_mask, SMU_FEATURE_MAX/32); if (ret) return ret; - mutex_lock(&feature->mutex); bitmap_or(feature->allowed, feature->allowed, (unsigned long *)allowed_feature_mask, feature->feature_num); - mutex_unlock(&feature->mutex); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index f5aeb0b5cf977..48987f3c4d123 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -721,7 +721,6 @@ int smu_v11_0_set_allowed_mask(struct smu_context *smu) int ret = 0; uint32_t feature_mask[2]; - mutex_lock(&feature->mutex); if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || feature->feature_num < 64) goto failed; @@ -738,7 +737,6 @@ int smu_v11_0_set_allowed_mask(struct smu_context *smu) goto failed; failed: - mutex_unlock(&feature->mutex); return ret; } -- GitLab From 7ee98e1b3415963b7fc211743bee35554e2ec42b Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 24 Aug 2020 15:18:00 +0800 Subject: [PATCH 1293/1494] drm/amd/pm: drop unnecessary smu_baco->mutex lock protections(V2) As these operations are performed in hardware setup and there is actually no race conditions during this period considering: 1. the hardware setup is serial and cannot be in parallel 2. all other operations can be performed only after hardware setup complete. V2: rich the commit log description Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 7 +------ 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 2ce6ad9c66094..d298fa65274df 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -386,11 +386,9 @@ static int arcturus_check_powerplay_table(struct smu_context *smu) table_context->power_play_table; struct smu_baco_context *smu_baco = &smu->smu_baco; - mutex_lock(&smu_baco->mutex); if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); table_context->thermal_controller_type = powerplay_table->thermal_controller_type; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 3559ba05a59cc..7e1d6c278b34c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -336,11 +336,9 @@ static int navi10_check_powerplay_table(struct smu_context *smu) if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) smu->dc_controlled_by_gpio = true; - mutex_lock(&smu_baco->mutex); if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); table_context->thermal_controller_type = powerplay_table->thermal_controller_type; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 9cf4e9aef1170..be9cd0371064f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -298,11 +298,9 @@ static int sienna_cichlid_check_powerplay_table(struct smu_context *smu) table_context->power_play_table; struct smu_baco_context *smu_baco = &smu->smu_baco; - mutex_lock(&smu_baco->mutex); if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO || powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); table_context->thermal_controller_type = powerplay_table->thermal_controller_type; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 48987f3c4d123..4aa257c07ac6f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1426,13 +1426,8 @@ static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v bool smu_v11_0_baco_is_support(struct smu_context *smu) { struct smu_baco_context *smu_baco = &smu->smu_baco; - bool baco_support; - mutex_lock(&smu_baco->mutex); - baco_support = smu_baco->platform_support; - mutex_unlock(&smu_baco->mutex); - - if (!baco_support) + if (!smu_baco->platform_support) return false; /* Arcturus does not support this bit mask */ -- GitLab From 38d11e024963c41c373d0207286b36dc218d0c50 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 24 Aug 2020 15:21:30 +0800 Subject: [PATCH 1294/1494] drm/amd/pm: drop unnecessary table existence and dpm enablement check Either this was already performed in parent API. Or the table is confirmed to exist. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 16 ---------------- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 19 ++++--------------- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 4 files changed, 5 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 29e041d86ae5d..3aefc5f9ba21f 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -704,7 +704,6 @@ int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed); int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk); -int smu_set_active_display_count(struct smu_context *smu, uint32_t count); int smu_get_clock_by_type(struct smu_context *smu, enum amd_pp_clock_type type, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index b98decaa06460..ac94aa780f07b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -580,9 +580,6 @@ static int smu_fini_fb_allocations(struct smu_context *smu) struct smu_table *tables = smu_table->tables; struct smu_table *driver_table = &(smu_table->driver_table); - if (!tables) - return 0; - if (tables[SMU_TABLE_PMSTATUSLOG].mc_address) amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo, &tables[SMU_TABLE_PMSTATUSLOG].mc_address, @@ -2316,19 +2313,6 @@ int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk) return ret; } -int smu_set_active_display_count(struct smu_context *smu, uint32_t count) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (smu->ppt_funcs->set_active_display_count) - ret = smu->ppt_funcs->set_active_display_count(smu, count); - - return ret; -} - int smu_get_clock_by_type(struct smu_context *smu, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 4aa257c07ac6f..a8f2ea18080ee 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -453,9 +453,6 @@ int smu_v11_0_init_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (smu_power->power_context || smu_power->power_context_size != 0) - return -EINVAL; - smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context), GFP_KERNEL); if (!smu_power->power_context) @@ -469,9 +466,6 @@ int smu_v11_0_fini_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - if (!smu_power->power_context || smu_power->power_context_size == 0) - return -EINVAL; - kfree(smu_power->power_context); smu_power->power_context = NULL; smu_power->power_context_size = 0; @@ -700,18 +694,16 @@ int smu_v11_0_set_tool_table_location(struct smu_context *smu) int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) { - int ret = 0; struct amdgpu_device *adev = smu->adev; /* Navy_Flounder do not support to change display num currently */ if (adev->asic_type == CHIP_NAVY_FLOUNDER) return 0; - if (!smu->pm_enabled) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, count, NULL); - return ret; + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_NumOfDisplays, + count, + NULL); } @@ -773,9 +765,6 @@ int smu_v11_0_notify_display_change(struct smu_context *smu) { int ret = 0; - if (!smu->pm_enabled) - return ret; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && smu->adev->gmc.vram_type == AMDGPU_VRAM_TYPE_HBM) ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1, NULL); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 521b805c920e5..c5adbe46ba0d5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -42,6 +42,7 @@ #define smu_check_fw_version(smu) smu_ppt_funcs(check_fw_version, 0, smu) #define smu_write_pptable(smu) smu_ppt_funcs(write_pptable, 0, smu) #define smu_set_min_dcef_deep_sleep(smu, clk) smu_ppt_funcs(set_min_dcef_deep_sleep, 0, smu, clk) +#define smu_set_active_display_count(smu, count) smu_ppt_funcs(set_active_display_count, 0, smu, count) #define smu_set_driver_table_location(smu) smu_ppt_funcs(set_driver_table_location, 0, smu) #define smu_set_tool_table_location(smu) smu_ppt_funcs(set_tool_table_location, 0, smu) #define smu_notify_memory_pool_location(smu) smu_ppt_funcs(notify_memory_pool_location, 0, smu) -- GitLab From 6c20f1573c28f96191485853dc97d01ff9f6a878 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 24 Aug 2020 15:25:28 +0800 Subject: [PATCH 1295/1494] drm/amd/pm: minor cleanups Drop unneeded "ret". Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index a8f2ea18080ee..5d7faf15cd6b5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1164,12 +1164,10 @@ int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu, int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, uint32_t pstate) { - int ret = 0; - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetXgmiMode, - pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetXgmiMode, + pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, NULL); - return ret; } static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, @@ -1400,11 +1398,7 @@ int smu_v11_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu) { - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); - - return ret; + return smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); } static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v11_0_baco_seq baco_seq) @@ -1503,13 +1497,7 @@ int smu_v11_0_baco_enter(struct smu_context *smu) int smu_v11_0_baco_exit(struct smu_context *smu) { - int ret = 0; - - ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT); - if (ret) - return ret; - - return ret; + return smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT); } int smu_v11_0_mode1_reset(struct smu_context *smu) -- GitLab From 12684c665f7ab0adbc2d1734aa141f31de0452b6 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 3 Sep 2020 14:41:47 +0800 Subject: [PATCH 1296/1494] drm/amd/pm: drop dead code Raven never goes to swsmu path. So "adev->smu.ppt_funcs" will be always false. Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Changfeng Zhu <Changfeng.Zhu@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 6a28fdd50e05f..cdf8ac9667f5b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -592,9 +592,6 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp, if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, &wm_with_clock_ranges); - else if (adev->smu.ppt_funcs) - smu_set_watermarks_for_clock_ranges(&adev->smu, - &wm_with_clock_ranges); } void pp_rv_set_pme_wa_enable(struct pp_smu *pp) -- GitLab From 7b9c7e30ab50c1b2f6814509b14fb0d04a697529 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 3 Sep 2020 15:02:37 +0800 Subject: [PATCH 1297/1494] drm/amd/pm: drop unnecessary wrappers around watermark setting The convertion to "struct dm_pp_clock_range_for_mcif_wm_set_soc15" is totally unnecessary and can be dropped. Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Changfeng Zhu <Changfeng.Zhu@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 97 +------------------ drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 4 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 68 ++++++------- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 69 ++++++------- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 44 ++++----- 6 files changed, 78 insertions(+), 206 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index cdf8ac9667f5b..6e575ffe34d04 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -664,49 +664,8 @@ static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges; - struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = - wm_with_clock_ranges.wm_dmif_clocks_ranges; - struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = - wm_with_clock_ranges.wm_mcif_clocks_ranges; - int32_t i; - - wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; - wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; - for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { - if (ranges->reader_wm_sets[i].wm_inst > 3) - wm_dce_clocks[i].wm_set_id = WM_SET_A; - else - wm_dce_clocks[i].wm_set_id = - ranges->reader_wm_sets[i].wm_inst; - wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz = - ranges->reader_wm_sets[i].max_drain_clk_mhz * 1000; - wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz = - ranges->reader_wm_sets[i].min_drain_clk_mhz * 1000; - wm_dce_clocks[i].wm_max_mem_clk_in_khz = - ranges->reader_wm_sets[i].max_fill_clk_mhz * 1000; - wm_dce_clocks[i].wm_min_mem_clk_in_khz = - ranges->reader_wm_sets[i].min_fill_clk_mhz * 1000; - } - - for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) { - if (ranges->writer_wm_sets[i].wm_inst > 3) - wm_soc_clocks[i].wm_set_id = WM_SET_A; - else - wm_soc_clocks[i].wm_set_id = - ranges->writer_wm_sets[i].wm_inst; - wm_soc_clocks[i].wm_max_socclk_clk_in_khz = - ranges->writer_wm_sets[i].max_fill_clk_mhz * 1000; - wm_soc_clocks[i].wm_min_socclk_clk_in_khz = - ranges->writer_wm_sets[i].min_fill_clk_mhz * 1000; - wm_soc_clocks[i].wm_max_mem_clk_in_khz = - ranges->writer_wm_sets[i].max_drain_clk_mhz * 1000; - wm_soc_clocks[i].wm_min_mem_clk_in_khz = - ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000; - } - - smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges); + smu_set_watermarks_for_clock_ranges(&adev->smu, ranges); return PP_SMU_RESULT_OK; } @@ -917,60 +876,8 @@ static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - struct smu_context *smu = &adev->smu; - struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges; - struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = - wm_with_clock_ranges.wm_dmif_clocks_ranges; - struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = - wm_with_clock_ranges.wm_mcif_clocks_ranges; - int32_t i; - - if (!smu->ppt_funcs) - return PP_SMU_RESULT_UNSUPPORTED; - - wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; - wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; - - for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { - if (ranges->reader_wm_sets[i].wm_inst > 3) - wm_dce_clocks[i].wm_set_id = WM_SET_A; - else - wm_dce_clocks[i].wm_set_id = - ranges->reader_wm_sets[i].wm_inst; - - wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz = - ranges->reader_wm_sets[i].min_drain_clk_mhz; - - wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz = - ranges->reader_wm_sets[i].max_drain_clk_mhz; - - wm_dce_clocks[i].wm_min_mem_clk_in_khz = - ranges->reader_wm_sets[i].min_fill_clk_mhz; - - wm_dce_clocks[i].wm_max_mem_clk_in_khz = - ranges->reader_wm_sets[i].max_fill_clk_mhz; - } - - for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) { - if (ranges->writer_wm_sets[i].wm_inst > 3) - wm_soc_clocks[i].wm_set_id = WM_SET_A; - else - wm_soc_clocks[i].wm_set_id = - ranges->writer_wm_sets[i].wm_inst; - wm_soc_clocks[i].wm_min_socclk_clk_in_khz = - ranges->writer_wm_sets[i].min_fill_clk_mhz; - - wm_soc_clocks[i].wm_max_socclk_clk_in_khz = - ranges->writer_wm_sets[i].max_fill_clk_mhz; - - wm_soc_clocks[i].wm_min_mem_clk_in_khz = - ranges->writer_wm_sets[i].min_drain_clk_mhz; - - wm_soc_clocks[i].wm_max_mem_clk_in_khz = - ranges->writer_wm_sets[i].max_drain_clk_mhz; - } - smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges); + smu_set_watermarks_for_clock_ranges(&adev->smu, ranges); return PP_SMU_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 3aefc5f9ba21f..85c5e8627e3be 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -501,7 +501,7 @@ struct pptable_funcs { bool (*is_dpm_running)(struct smu_context *smu); int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); int (*set_watermarks_table)(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); + struct pp_smu_wm_range_sets *clock_ranges); int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); int (*set_default_od_settings)(struct smu_context *smu); @@ -755,7 +755,7 @@ enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu); int smu_write_watermarks_table(struct smu_context *smu); int smu_set_watermarks_for_clock_ranges( struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); + struct pp_smu_wm_range_sets *clock_ranges); /* smu to display interface */ extern int smu_display_configuration_change(struct smu_context *smu, const diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index ac94aa780f07b..3655db2d4a259 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1828,7 +1828,7 @@ int smu_write_watermarks_table(struct smu_context *smu) } int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) + struct pp_smu_wm_range_sets *clock_ranges) { int ret = 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 7e1d6c278b34c..8b91786923059 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1589,57 +1589,43 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) } static int navi10_set_watermarks_table(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) + struct pp_smu_wm_range_sets *clock_ranges) { Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; int i; if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) + if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || + clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) return -EINVAL; - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { + table->WatermarkRow[WM_DCEFCLK][i].MinClock = + clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MaxClock = + clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MinUclk = + clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MaxUclk = + clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; + + table->WatermarkRow[WM_DCEFCLK][i].WmSetting = + clock_ranges->reader_wm_sets[i].wm_inst; } - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { + table->WatermarkRow[WM_SOCCLK][i].MinClock = + clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MaxClock = + clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MinUclk = + clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MaxUclk = + clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; + + table->WatermarkRow[WM_SOCCLK][i].WmSetting = + clock_ranges->writer_wm_sets[i].wm_inst; } smu->watermarks_bitmap |= WATERMARKS_EXIST; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index be9cd0371064f..a2cb831ce8aae 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1407,58 +1407,43 @@ static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) } static int sienna_cichlid_set_watermarks_table(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 - *clock_ranges) + struct pp_smu_wm_range_sets *clock_ranges) { Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; int i; if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) + if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || + clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) return -EINVAL; - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { + table->WatermarkRow[WM_DCEFCLK][i].MinClock = + clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MaxClock = + clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MinUclk = + clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; + table->WatermarkRow[WM_DCEFCLK][i].MaxUclk = + clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; + + table->WatermarkRow[WM_DCEFCLK][i].WmSetting = + clock_ranges->reader_wm_sets[i].wm_inst; } - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { + table->WatermarkRow[WM_SOCCLK][i].MinClock = + clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MaxClock = + clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MinUclk = + clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; + table->WatermarkRow[WM_SOCCLK][i].MaxUclk = + clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; + + table->WatermarkRow[WM_SOCCLK][i].WmSetting = + clock_ranges->writer_wm_sets[i].wm_inst; } smu->watermarks_bitmap |= WATERMARKS_EXIST; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 3b9ac72c7571d..53d8beffc74e5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -863,50 +863,44 @@ static int renoir_set_performance_level(struct smu_context *smu, */ static int renoir_set_watermarks_table( struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) + struct pp_smu_wm_range_sets *clock_ranges) { Watermarks_t *table = smu->smu_table.watermarks_table; int ret = 0; int i; if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) + if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES || + clock_ranges->num_writer_wm_sets > NUM_WM_RANGES) return -EINVAL; /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) { table->WatermarkRow[WM_DCFCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz)); + clock_ranges->reader_wm_sets[i].min_drain_clk_mhz; table->WatermarkRow[WM_DCFCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz)); + clock_ranges->reader_wm_sets[i].max_drain_clk_mhz; table->WatermarkRow[WM_DCFCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + clock_ranges->reader_wm_sets[i].min_fill_clk_mhz; table->WatermarkRow[WM_DCFCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + clock_ranges->reader_wm_sets[i].max_fill_clk_mhz; + + table->WatermarkRow[WM_DCFCLK][i].WmSetting = + clock_ranges->reader_wm_sets[i].wm_inst; } - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { table->WatermarkRow[WM_SOCCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz)); + clock_ranges->writer_wm_sets[i].min_fill_clk_mhz; table->WatermarkRow[WM_SOCCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz)); + clock_ranges->writer_wm_sets[i].max_fill_clk_mhz; table->WatermarkRow[WM_SOCCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + clock_ranges->writer_wm_sets[i].min_drain_clk_mhz; table->WatermarkRow[WM_SOCCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + clock_ranges->writer_wm_sets[i].max_drain_clk_mhz; + + table->WatermarkRow[WM_SOCCLK][i].WmSetting = + clock_ranges->writer_wm_sets[i].wm_inst; } smu->watermarks_bitmap |= WATERMARKS_EXIST; -- GitLab From ce2c00061b2810ff0523e34ab392893556e17bbf Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 3 Sep 2020 15:13:09 +0800 Subject: [PATCH 1298/1494] drm/amd/pm: add Renoir watermark WmType setting Which tells it's a normal pstate change or memory retraining. Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Changfeng Zhu <Changfeng.Zhu@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 53d8beffc74e5..63c72e33222e4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -887,6 +887,8 @@ static int renoir_set_watermarks_table( table->WatermarkRow[WM_DCFCLK][i].WmSetting = clock_ranges->reader_wm_sets[i].wm_inst; + table->WatermarkRow[WM_DCFCLK][i].WmType = + clock_ranges->reader_wm_sets[i].wm_type; } for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) { @@ -901,6 +903,8 @@ static int renoir_set_watermarks_table( table->WatermarkRow[WM_SOCCLK][i].WmSetting = clock_ranges->writer_wm_sets[i].wm_inst; + table->WatermarkRow[WM_SOCCLK][i].WmType = + clock_ranges->writer_wm_sets[i].wm_type; } smu->watermarks_bitmap |= WATERMARKS_EXIST; -- GitLab From 911779e3fc282cbdcae96c70131e3fe89cd5c1bc Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 3 Sep 2020 15:42:59 +0800 Subject: [PATCH 1299/1494] drm/amd/pm: add Raven2 watermark WmType setting Which tells it's a normal pstate change or memory retraining. Signed-off-by: Evan Quan <evan.quan@amd.com> Tested-by: Changfeng Zhu <Changfeng.Zhu@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h | 3 ++- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h index dea8fe93da638..c498158771cc4 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h +++ b/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h @@ -54,7 +54,8 @@ typedef struct { uint16_t MaxMclk; uint8_t WmSetting; - uint8_t Padding[3]; + uint8_t WmType; + uint8_t Padding[2]; } WatermarkRowGeneric_t; #define NUM_WM_RANGES 4 diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index 9ee8cf8267c88..88792dba17599 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -1181,8 +1181,19 @@ static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, struct smu10_hwmgr *data = hwmgr->backend; struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; Watermarks_t *table = &(data->water_marks_table); + struct amdgpu_device *adev = hwmgr->adev; + int i; smu_set_watermarks_for_clocks_ranges(table,wm_with_clock_ranges); + + if (adev->apu_flags & AMD_APU_IS_RAVEN2) { + for (i = 0; i < NUM_WM_RANGES; i++) + table->WatermarkRow[WM_DCFCLK][i].WmType = (uint8_t)0; + + for (i = 0; i < NUM_WM_RANGES; i++) + table->WatermarkRow[WM_SOCCLK][i].WmType = (uint8_t)0; + } + smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false); data->water_marks_exist = true; return 0; -- GitLab From 71f9404f19af1da2a4cc583e2d6db448f25a5e1a Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 4 Sep 2020 14:41:07 +0800 Subject: [PATCH 1300/1494] drm/amd/pm: process pending AC/DC switch interrupt Process any pending interrupt that occured before driver register for interrupt from GPIO/SMU. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 5d7faf15cd6b5..b53872eb43983 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -934,12 +934,39 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) return 0; } +static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg(smu, + SMU_MSG_ReenableAcDcInterrupt, + NULL); +} + +static int smu_v11_0_process_pending_interrupt(struct smu_context *smu) +{ + int ret = 0; + + if (smu->dc_controlled_by_gpio && + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_ACDC_BIT)) + ret = smu_v11_0_ack_ac_dc_interrupt(smu); + + return ret; +} + int smu_v11_0_enable_thermal_alert(struct smu_context *smu) { - if (smu->smu_table.thermal_controller_type) - return amdgpu_irq_get(smu->adev, &smu->irq_source, 0); + int ret = 0; - return 0; + if (smu->smu_table.thermal_controller_type) { + ret = amdgpu_irq_get(smu->adev, &smu->irq_source, 0); + if (ret) + return ret; + } + + /* + * After init there might have been missed interrupts triggered + * before driver registers for interrupt (Ex. AC/DC). + */ + return smu_v11_0_process_pending_interrupt(smu); } int smu_v11_0_disable_thermal_alert(struct smu_context *smu) @@ -1235,13 +1262,6 @@ static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, return 0; } -static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu) -{ - return smu_cmn_send_smc_msg(smu, - SMU_MSG_ReenableAcDcInterrupt, - NULL); -} - #define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ #define THM_11_0__SRCID__THM_DIG_THERM_H2L 1 /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL */ -- GitLab From 236b156f738886d12336215434c605cbc4da7b89 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 4 Sep 2020 14:55:43 +0800 Subject: [PATCH 1301/1494] drm/amd/pm: apply no power source workaround if dc reported by gpio If dc reported by gpio is supported, the power source switching will be performed by pmfw automatically. Thus the power source setting workaround for Navi1x will be not needed. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3655db2d4a259..b3f35f08efa0b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1013,16 +1013,18 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - /* - * For Navi1X, manually switch it to AC mode as PMFW - * may boot it with DC mode. - */ - ret = smu_set_power_source(smu, - adev->pm.ac_power ? SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) { - dev_err(adev->dev, "Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); - return ret; + if (!smu->dc_controlled_by_gpio) { + /* + * For Navi1X, manually switch it to AC mode as PMFW + * may boot it with DC mode. + */ + ret = smu_set_power_source(smu, + adev->pm.ac_power ? SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) { + dev_err(adev->dev, "Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); + return ret; + } } ret = smu_notify_display_change(smu); -- GitLab From 1653a179c822278cf4a7cb97d4d6d3534ce82dbe Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 4 Sep 2020 15:05:55 +0800 Subject: [PATCH 1302/1494] drm/amd/pm: move NAVI1X power mode switching workaround to post_init Since that should be the correct place to put ASIC specific workarounds. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 14 ------------- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 20 ++++++++++++++++++- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index b3f35f08efa0b..5c4b74f964fca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1013,20 +1013,6 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - if (!smu->dc_controlled_by_gpio) { - /* - * For Navi1X, manually switch it to AC mode as PMFW - * may boot it with DC mode. - */ - ret = smu_set_power_source(smu, - adev->pm.ac_power ? SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) { - dev_err(adev->dev, "Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); - return ret; - } - } - ret = smu_notify_display_change(smu); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 8b91786923059..a027c7fdad56f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2661,8 +2661,26 @@ static int navi10_post_smu_init(struct smu_context *smu) } ret = navi10_run_umc_cdr_workaround(smu); - if (ret) + if (ret) { dev_err(adev->dev, "Failed to apply umc cdr workaround!\n"); + return ret; + } + + if (!smu->dc_controlled_by_gpio) { + /* + * For Navi1X, manually switch it to AC mode as PMFW + * may boot it with DC mode. + */ + ret = smu_v11_0_set_power_source(smu, + adev->pm.ac_power ? + SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) { + dev_err(adev->dev, "Failed to switch to %s mode!\n", + adev->pm.ac_power ? "AC" : "DC"); + return ret; + } + } return ret; } -- GitLab From abf6b7c78ed4ffd40b7240f8b0fd403da30a3284 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 4 Sep 2020 15:49:08 +0800 Subject: [PATCH 1303/1494] drm/amd/pm: lower Raven UMD Stable Pstate VCN values SMU FCLK,SOCCLK have dependency on VCN CLKs. Lower VCN values so that FCLK, SOCCLK reflect values set by UMD Stable Pstate. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 4 ++-- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index 88792dba17599..a5d1a32ab160f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -648,7 +648,7 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinVcn, - SMU10_UMD_PSTATE_VCE, + SMU10_UMD_PSTATE_PROFILE_VCE, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, @@ -665,7 +665,7 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMaxVcn, - SMU10_UMD_PSTATE_VCE, + SMU10_UMD_PSTATE_PROFILE_VCE, NULL); break; case AMD_DPM_FORCED_LEVEL_AUTO: diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h index 0f969de10fabc..ee0c9591620b1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h @@ -310,6 +310,7 @@ int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); #define SMU10_UMD_PSTATE_SOCCLK 626 #define SMU10_UMD_PSTATE_FCLK 933 #define SMU10_UMD_PSTATE_VCE 0x03C00320 +#define SMU10_UMD_PSTATE_PROFILE_VCE 0x02AD0229 #define SMU10_UMD_PSTATE_PEAK_SOCCLK 757 #define SMU10_UMD_PSTATE_PEAK_FCLK 1200 -- GitLab From 92e005936e8a34b16d6e40be114ad263cded49bc Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 4 Sep 2020 16:08:15 +0800 Subject: [PATCH 1304/1494] drm/amd/pm: correct Renoir UMD Stable Pstate settings Update the UMD stable Pstate settings with correct clocks. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 52 ++++++++++++++++++- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 63c72e33222e4..55a254be5ac24 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -832,9 +832,59 @@ static int renoir_set_performance_level(struct smu_context *smu, ret = renoir_force_dpm_limit_value(smu, false); break; case AMD_DPM_FORCED_LEVEL_AUTO: - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: ret = renoir_unforce_dpm_levels(smu); break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetHardMinGfxClk, + RENOIR_UMD_PSTATE_GFXCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetHardMinFclkByFreq, + RENOIR_UMD_PSTATE_FCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetHardMinSocclkByFreq, + RENOIR_UMD_PSTATE_SOCCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetHardMinVcn, + RENOIR_UMD_PSTATE_VCNCLK, + NULL); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSoftMaxGfxClk, + RENOIR_UMD_PSTATE_GFXCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSoftMaxFclkByFreq, + RENOIR_UMD_PSTATE_FCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSoftMaxSocclkByFreq, + RENOIR_UMD_PSTATE_SOCCLK, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSoftMaxVcn, + RENOIR_UMD_PSTATE_VCNCLK, + NULL); + if (ret) + return ret; + break; case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: ret = renoir_get_profiling_clk_mask(smu, level, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h index 8c3f004cdf8dc..11c3c22fecbe9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h @@ -29,5 +29,6 @@ extern void renoir_set_ppt_funcs(struct smu_context *smu); #define RENOIR_UMD_PSTATE_GFXCLK 700 #define RENOIR_UMD_PSTATE_SOCCLK 678 #define RENOIR_UMD_PSTATE_FCLK 800 +#define RENOIR_UMD_PSTATE_VCNCLK 0x022D01D8 #endif -- GitLab From 0eaa80124271966c595322ec0ac4b9c54f6aa7ee Mon Sep 17 00:00:00 2001 From: Shirish S <shirish.s@amd.com> Date: Mon, 14 Sep 2020 10:11:23 +0530 Subject: [PATCH 1305/1494] amdgpu/gmc_v9: Warn if SDPIF_MMIO_CNTRL_0 is not set With IOMMU enabled, if SDPIF_MMIO_CNTRL_0 is not set appropriately the system hangs without any trace during S3. To ease debug and to ensure that the failure, if any, was caused by a race conditions that disabled write access to SDPIF_MMIO_CNTRL_0 register, warn the user about it. Signed-off-by: Shirish S <shirish.s@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c605a1885374b..5400cac020876 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1545,8 +1545,11 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) */ void gmc_v9_0_restore_registers(struct amdgpu_device *adev) { - if (adev->asic_type == CHIP_RAVEN) + if (adev->asic_type == CHIP_RAVEN) { WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); + WARN_ON(adev->gmc.sdpif_register != + RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0)); + } } /** -- GitLab From 24b763d0fb05e8c3b565a3813baafc53b973dba7 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 16 Sep 2020 19:17:20 +0800 Subject: [PATCH 1306/1494] drm/amdgpu: declare ta firmware for navy_flounder The firmware provided via MODULE_FIRMWARE appears in the module information. External tools(eg. dracut) may use the list of fw files to include them as appropriate in an initramfs, thus missing declaration will lead to request firmware failure in boot time. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tianci Yin <tianci.yin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index e16874f30d5dc..6c5d9612abcb6 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -58,7 +58,7 @@ MODULE_FIRMWARE("amdgpu/arcturus_ta.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_sos.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_ta.bin"); MODULE_FIRMWARE("amdgpu/navy_flounder_sos.bin"); -MODULE_FIRMWARE("amdgpu/navy_flounder_asd.bin"); +MODULE_FIRMWARE("amdgpu/navy_flounder_ta.bin"); /* address block */ #define smnMP1_FIRMWARE_FLAGS 0x3010024 -- GitLab From 5aea5327ea2ddf544cbeff096f45fc2319b0714e Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Wed, 16 Sep 2020 13:03:50 -0400 Subject: [PATCH 1307/1494] drm/amdgpu: No sysfs, not an error condition Not being able to create amdgpu sysfs attributes is not a fatal error warranting not to continue to try to bring up the display. Thus, if we get an error trying to create amdgpu sysfs attrs, report it and continue on to try to bring up a display. Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Acked-by: Slava Abramov <slava.abramov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d633e5448476f..53b9d86da596a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3400,10 +3400,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, flush_delayed_work(&adev->delayed_init_work); r = sysfs_create_files(&adev->dev->kobj, amdgpu_dev_attributes); - if (r) { + if (r) dev_err(adev->dev, "Could not create amdgpu device attr\n"); - return r; - } if (IS_ENABLED(CONFIG_PERF_EVENTS)) r = amdgpu_pmu_init(adev); -- GitLab From c8e74b17c156db32190cc782ff1a471715155e9e Mon Sep 17 00:00:00 2001 From: Philip Yang <Philip.Yang@amd.com> Date: Tue, 15 Sep 2020 17:07:35 -0400 Subject: [PATCH 1308/1494] drm/amdgpu: prevent double kfree ttm->sg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set ttm->sg to NULL after kfree, to avoid memory corruption backtrace: [ 420.932812] kernel BUG at /build/linux-do9eLF/linux-4.15.0/mm/slub.c:295! [ 420.934182] invalid opcode: 0000 [#1] SMP NOPTI [ 420.935445] Modules linked in: xt_conntrack ipt_MASQUERADE [ 420.951332] Hardware name: Dell Inc. PowerEdge R7525/0PYVT1, BIOS 1.5.4 07/09/2020 [ 420.952887] RIP: 0010:__slab_free+0x180/0x2d0 [ 420.954419] RSP: 0018:ffffbe426291fa60 EFLAGS: 00010246 [ 420.955963] RAX: ffff9e29263e9c30 RBX: ffff9e29263e9c30 RCX: 000000018100004b [ 420.957512] RDX: ffff9e29263e9c30 RSI: fffff3d33e98fa40 RDI: ffff9e297e407a80 [ 420.959055] RBP: ffffbe426291fb00 R08: 0000000000000001 R09: ffffffffc0d39ade [ 420.960587] R10: ffffbe426291fb20 R11: ffff9e49ffdd4000 R12: ffff9e297e407a80 [ 420.962105] R13: fffff3d33e98fa40 R14: ffff9e29263e9c30 R15: ffff9e2954464fd8 [ 420.963611] FS: 00007fa2ea097780(0000) GS:ffff9e297e840000(0000) knlGS:0000000000000000 [ 420.965144] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 420.966663] CR2: 00007f16bfffefb8 CR3: 0000001ff0c62000 CR4: 0000000000340ee0 [ 420.968193] Call Trace: [ 420.969703] ? __page_cache_release+0x3c/0x220 [ 420.971294] ? amdgpu_ttm_tt_unpopulate+0x5e/0x80 [amdgpu] [ 420.972789] kfree+0x168/0x180 [ 420.974353] ? amdgpu_ttm_tt_set_user_pages+0x64/0xc0 [amdgpu] [ 420.975850] ? kfree+0x168/0x180 [ 420.977403] amdgpu_ttm_tt_unpopulate+0x5e/0x80 [amdgpu] [ 420.978888] ttm_tt_unpopulate.part.10+0x53/0x60 [amdttm] [ 420.980357] ttm_tt_destroy.part.11+0x4f/0x60 [amdttm] [ 420.981814] ttm_tt_destroy+0x13/0x20 [amdttm] [ 420.983273] ttm_bo_cleanup_memtype_use+0x36/0x80 [amdttm] [ 420.984725] ttm_bo_release+0x1c9/0x360 [amdttm] [ 420.986167] amdttm_bo_put+0x24/0x30 [amdttm] [ 420.987663] amdgpu_bo_unref+0x1e/0x30 [amdgpu] [ 420.989165] amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu+0x9ca/0xb10 [amdgpu] [ 420.990666] kfd_ioctl_alloc_memory_of_gpu+0xef/0x2c0 [amdgpu] Signed-off-by: Philip Yang <Philip.Yang@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 257a1bab01473..4a85f8cedd77c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1021,6 +1021,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) release_sg: kfree(ttm->sg); + ttm->sg = NULL; return r; } -- GitLab From 143678d12b6d5eb883366b335b22236e6a8e34de Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Tue, 15 Sep 2020 17:26:29 -0400 Subject: [PATCH 1309/1494] drm/amd/display: Don't log hdcp module warnings in dmesg [Why] DTM topology updates happens by default now. This results in DTM warnings when hdcp is not even being enabled. This spams the dmesg and doesn't effect normal display functionality so it is better to log it using DRM_DEBUG_KMS() [How] Change the DRM_WARN() to DRM_DEBUG_KMS() Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h index d3192b9d0c3d8..47f8ee2832ff0 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h @@ -27,7 +27,7 @@ #define MOD_HDCP_LOG_H_ #ifdef CONFIG_DRM_AMD_DC_HDCP -#define HDCP_LOG_ERR(hdcp, ...) DRM_WARN(__VA_ARGS__) +#define HDCP_LOG_ERR(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__) -- GitLab From d5c0af5732798e09857a5a8f1a57cfc69c85a4f3 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Date: Wed, 16 Sep 2020 12:44:46 -0400 Subject: [PATCH 1310/1494] drm/amd/display: Add missing "Copy GSL groups when committing a new context" [Why] "Copy GSL groups when committing a new context" patch was accidentally removed during a refactor Patch: 21ffcc94d5b ("drm/amd/display: Copy GSL groups when committing a new context") [How] Re add it Fixes: b6e881c9474 ("drm/amd/display: update navi to use new surface programming behaviour") Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 5720b6e5d321b..01530e686f437 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1642,6 +1642,17 @@ void dcn20_program_front_end_for_ctx( struct dce_hwseq *hws = dc->hwseq; DC_LOGGER_INIT(dc->ctx->logger); + /* Carry over GSL groups in case the context is changing. */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe_ctx = + &dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->stream == old_pipe_ctx->stream) + pipe_ctx->stream_res.gsl_group = + old_pipe_ctx->stream_res.gsl_group; + } + if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -- GitLab From b6c91dadaffee8bf253b0b5ac26a2638c388c6c6 Mon Sep 17 00:00:00 2001 From: Tom St Denis <tom.stdenis@amd.com> Date: Wed, 16 Sep 2020 12:17:04 -0400 Subject: [PATCH 1311/1494] drm/amd/amdgpu: add mmUVD_FW_STATUS register to uvd700 This register was requested for umr debugging support. Signed-off-by: Tom St Denis <tom.stdenis@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../amd/include/asic_reg/uvd/uvd_7_0_offset.h | 3 +++ .../include/asic_reg/uvd/uvd_7_0_sh_mask.h | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_offset.h index 07aceffb108a7..524ba4421c170 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_offset.h @@ -151,6 +151,8 @@ #define mmUVD_LMI_CTRL2_BASE_IDX 1 #define mmUVD_MASTINT_EN 0x0540 #define mmUVD_MASTINT_EN_BASE_IDX 1 +#define mmUVD_FW_STATUS 0x0557 +#define mmUVD_FW_STATUS_BASE_IDX 1 #define mmJPEG_CGC_CTRL 0x0565 #define mmJPEG_CGC_CTRL_BASE_IDX 1 #define mmUVD_LMI_CTRL 0x0566 @@ -219,4 +221,5 @@ #define mmUVD_CONTEXT_ID2_BASE_IDX 1 + #endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_sh_mask.h index b427f73bd5363..919be1842bd53 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_7_0_sh_mask.h @@ -807,5 +807,25 @@ #define UVD_CONTEXT_ID2__CONTEXT_ID2__SHIFT 0x0 #define UVD_CONTEXT_ID2__CONTEXT_ID2_MASK 0xFFFFFFFFL +//UVD_FW_STATUS +#define UVD_FW_STATUS__BUSY__SHIFT 0x0 +#define UVD_FW_STATUS__ACTIVE__SHIFT 0x1 +#define UVD_FW_STATUS__SEND_EFUSE_REQ__SHIFT 0x2 +#define UVD_FW_STATUS__DONE__SHIFT 0x8 +#define UVD_FW_STATUS__PASS__SHIFT 0x10 +#define UVD_FW_STATUS__FAIL__SHIFT 0x11 +#define UVD_FW_STATUS__INVALID_LEN__SHIFT 0x12 +#define UVD_FW_STATUS__INVALID_0_PADDING__SHIFT 0x13 +#define UVD_FW_STATUS__INVALID_NONCE__SHIFT 0x14 +#define UVD_FW_STATUS__BUSY_MASK 0x00000001L +#define UVD_FW_STATUS__ACTIVE_MASK 0x00000002L +#define UVD_FW_STATUS__SEND_EFUSE_REQ_MASK 0x00000004L +#define UVD_FW_STATUS__DONE_MASK 0x00000100L +#define UVD_FW_STATUS__PASS_MASK 0x00010000L +#define UVD_FW_STATUS__FAIL_MASK 0x00020000L +#define UVD_FW_STATUS__INVALID_LEN_MASK 0x00040000L +#define UVD_FW_STATUS__INVALID_0_PADDING_MASK 0x00080000L +#define UVD_FW_STATUS__INVALID_NONCE_MASK 0x00100000L + #endif -- GitLab From 4192f7b5768912ceda82be2f83c87ea7181f9980 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 16 Sep 2020 10:28:55 -0400 Subject: [PATCH 1312/1494] drm/amdgpu: unmap register bar on device init failure We never unmapped the regiser BAR on failure. Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Reviewed-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 53b9d86da596a..2ff43a3d52fc2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3209,13 +3209,13 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_device_get_job_timeout_settings(adev); if (r) { dev_err(adev->dev, "invalid lockup_timeout parameter syntax\n"); - return r; + goto failed_unmap; } /* early init functions */ r = amdgpu_device_ip_early_init(adev); if (r) - return r; + goto failed_unmap; /* doorbell bar mapping and doorbell index init*/ amdgpu_device_doorbell_init(adev); @@ -3419,6 +3419,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (boco) vga_switcheroo_fini_domain_pm_ops(adev->dev); +failed_unmap: + iounmap(adev->rmmio); + adev->rmmio = NULL; + return r; } -- GitLab From 8906e5bcf951d9a624cb35b3ecd291330413a5d5 Mon Sep 17 00:00:00 2001 From: Ye Bin <yebin10@huawei.com> Date: Wed, 16 Sep 2020 09:08:58 +0800 Subject: [PATCH 1313/1494] drm/amd/display: Remove set but used 'temp' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the following gcc warning with "make W=1": In file included from drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../dmub_srv.h:67:0, from drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn21.c:26: drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../inc/dmub_cmd.h: In function ‘dmub_rb_flush_pending’: drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../inc/dmub_cmd.h:795:12: warning: variable ‘temp’ set but not used [-Wunused-but-set-variable] uint64_t temp; ^ In file included from drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../dmub_srv.h:67:0, from drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn30.c:26: drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../inc/dmub_cmd.h: In function ‘dmub_rb_flush_pending’: drivers/gpu/drm/amd/amdgpu/../display/dmub/src/../inc/dmub_cmd.h:795:12: warning: variable ‘temp’ set but not used [-Wunused-but-set-variable] uint64_t temp; Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Ye Bin <yebin10@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index a0bd502dc7d7e..f74c7fabd0a95 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -792,12 +792,10 @@ static inline void dmub_rb_flush_pending(const struct dmub_rb *rb) while (rptr != wptr) { uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t); - //uint64_t volatile *p = (uint64_t volatile *)data; - uint64_t temp; int i; for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++) - temp = *data++; + *data++; rptr += DMUB_RB_CMD_SIZE; if (rptr >= rb->capacity) -- GitLab From 7663edc13ed0a5390944e49038815ee0a8e7ae05 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Fri, 1 May 2020 16:42:56 -0400 Subject: [PATCH 1314/1494] drm/amdgpu: add the GC 10.3 VRS registers Add the VRS registers. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../include/asic_reg/gc/gc_10_3_0_default.h | 2 + .../include/asic_reg/gc/gc_10_3_0_offset.h | 4 ++ .../include/asic_reg/gc/gc_10_3_0_sh_mask.h | 50 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_default.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_default.h index 1116779252e65..e245e912535e5 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_default.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_default.h @@ -2727,6 +2727,7 @@ #define mmDB_STENCIL_WRITE_BASE_DEFAULT 0x00000000 #define mmDB_RESERVED_REG_1_DEFAULT 0x00000000 #define mmDB_RESERVED_REG_3_DEFAULT 0x00000000 +#define mmDB_VRS_OVERRIDE_CNTL_DEFAULT 0x00000000 #define mmDB_Z_READ_BASE_HI_DEFAULT 0x00000000 #define mmDB_STENCIL_READ_BASE_HI_DEFAULT 0x00000000 #define mmDB_Z_WRITE_BASE_HI_DEFAULT 0x00000000 @@ -3062,6 +3063,7 @@ #define mmPA_SU_OVER_RASTERIZATION_CNTL_DEFAULT 0x00000000 #define mmPA_STEREO_CNTL_DEFAULT 0x00000000 #define mmPA_STATE_STEREO_X_DEFAULT 0x00000000 +#define mmPA_CL_VRS_CNTL_DEFAULT 0x00000000 #define mmPA_SU_POINT_SIZE_DEFAULT 0x00000000 #define mmPA_SU_POINT_MINMAX_DEFAULT 0x00000000 #define mmPA_SU_LINE_CNTL_DEFAULT 0x00000000 diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h index cbaad7d831943..66a4151fa6768 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h @@ -5379,6 +5379,8 @@ #define mmDB_RESERVED_REG_1_BASE_IDX 1 #define mmDB_RESERVED_REG_3 0x0017 #define mmDB_RESERVED_REG_3_BASE_IDX 1 +#define mmDB_VRS_OVERRIDE_CNTL 0x0019 +#define mmDB_VRS_OVERRIDE_CNTL_BASE_IDX 1 #define mmDB_Z_READ_BASE_HI 0x001a #define mmDB_Z_READ_BASE_HI_BASE_IDX 1 #define mmDB_STENCIL_READ_BASE_HI 0x001b @@ -6049,6 +6051,8 @@ #define mmPA_STEREO_CNTL_BASE_IDX 1 #define mmPA_STATE_STEREO_X 0x0211 #define mmPA_STATE_STEREO_X_BASE_IDX 1 +#define mmPA_CL_VRS_CNTL 0x0212 +#define mmPA_CL_VRS_CNTL_BASE_IDX 1 #define mmPA_SU_POINT_SIZE 0x0280 #define mmPA_SU_POINT_SIZE_BASE_IDX 1 #define mmPA_SU_POINT_MINMAX 0x0281 diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h index c2d035ef3e94e..aed799d9a0e8b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h @@ -9777,6 +9777,7 @@ #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_HTILE__SHIFT 0x3 #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_QUAD__SHIFT 0x4 #define DB_EXCEPTION_CONTROL__FORCE_SUMMARIZE__SHIFT 0x8 +#define DB_EXCEPTION_CONTROL__FORCE_VRS_RATE_FINE__SHIFT 0x10 #define DB_EXCEPTION_CONTROL__DTAG_WATERMARK__SHIFT 0x18 #define DB_EXCEPTION_CONTROL__EARLY_Z_PANIC_DISABLE_MASK 0x00000001L #define DB_EXCEPTION_CONTROL__LATE_Z_PANIC_DISABLE_MASK 0x00000002L @@ -9784,6 +9785,7 @@ #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_HTILE_MASK 0x00000008L #define DB_EXCEPTION_CONTROL__AUTO_FLUSH_QUAD_MASK 0x00000010L #define DB_EXCEPTION_CONTROL__FORCE_SUMMARIZE_MASK 0x00000F00L +#define DB_EXCEPTION_CONTROL__FORCE_VRS_RATE_FINE_MASK 0x00FF0000L #define DB_EXCEPTION_CONTROL__DTAG_WATERMARK_MASK 0x7F000000L //DB_DFSM_CONFIG #define DB_DFSM_CONFIG__BYPASS_DFSM__SHIFT 0x0 @@ -10076,6 +10078,7 @@ #define CB_HW_CONTROL_3__DISABLE_NACK_PROCESSING_CM__SHIFT 0x18 #define CB_HW_CONTROL_3__DISABLE_NACK_COLOR_RD_WR_OPT__SHIFT 0x19 #define CB_HW_CONTROL_3__DISABLE_BLENDER_CLOCK_GATING__SHIFT 0x1a +#define CB_HW_CONTROL_3__DISABLE_DCC_VRS_OPT__SHIFT 0x1c #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT__SHIFT 0x1e #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_BC__SHIFT 0x1f #define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL_MASK 0x00000001L @@ -10103,12 +10106,15 @@ #define CB_HW_CONTROL_3__DISABLE_NACK_PROCESSING_CM_MASK 0x01000000L #define CB_HW_CONTROL_3__DISABLE_NACK_COLOR_RD_WR_OPT_MASK 0x02000000L #define CB_HW_CONTROL_3__DISABLE_BLENDER_CLOCK_GATING_MASK 0x04000000L +#define CB_HW_CONTROL_3__DISABLE_DCC_VRS_OPT_MASK 0x10000000L #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_MASK 0x40000000L #define CB_HW_CONTROL_3__DISABLE_FMASK_NOFETCH_OPT_BC_MASK 0x80000000L //CB_HW_CONTROL #define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE__SHIFT 0x0 +#define CB_HW_CONTROL__DISABLE_VRS_FILLRATE_OPTIMIZATION__SHIFT 0x1 #define CB_HW_CONTROL__DISABLE_FILLRATE_OPT_FIX_WITH_CFC__SHIFT 0x3 #define CB_HW_CONTROL__DISABLE_POST_DCC_WITH_CFC_FIX__SHIFT 0x4 +#define CB_HW_CONTROL__DISABLE_COMPRESS_1FRAG_WHEN_VRS_RATE_HINT_EN__SHIFT 0x5 #define CB_HW_CONTROL__RMI_CREDITS__SHIFT 0x6 #define CB_HW_CONTROL__CHICKEN_BITS__SHIFT 0xc #define CB_HW_CONTROL__DISABLE_FMASK_MULTI_MGCG_DOMAINS__SHIFT 0xf @@ -10129,8 +10135,10 @@ #define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT__SHIFT 0x1e #define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE__SHIFT 0x1f #define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE_MASK 0x00000001L +#define CB_HW_CONTROL__DISABLE_VRS_FILLRATE_OPTIMIZATION_MASK 0x00000002L #define CB_HW_CONTROL__DISABLE_FILLRATE_OPT_FIX_WITH_CFC_MASK 0x00000008L #define CB_HW_CONTROL__DISABLE_POST_DCC_WITH_CFC_FIX_MASK 0x00000010L +#define CB_HW_CONTROL__DISABLE_COMPRESS_1FRAG_WHEN_VRS_RATE_HINT_EN_MASK 0x00000020L #define CB_HW_CONTROL__RMI_CREDITS_MASK 0x00000FC0L #define CB_HW_CONTROL__CHICKEN_BITS_MASK 0x00007000L #define CB_HW_CONTROL__DISABLE_FMASK_MULTI_MGCG_DOMAINS_MASK 0x00008000L @@ -19881,6 +19889,7 @@ #define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS__SHIFT 0x16 #define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS__SHIFT 0x17 #define DB_RENDER_OVERRIDE2__ALLOW_PARTIAL_RES_HIER_KILL__SHIFT 0x19 +#define DB_RENDER_OVERRIDE2__FORCE_VRS_RATE_FINE__SHIFT 0x1a #define DB_RENDER_OVERRIDE2__CENTROID_COMPUTATION_MODE__SHIFT 0x1b #define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL_MASK 0x00000003L #define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN_MASK 0x0000001CL @@ -19898,6 +19907,7 @@ #define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS_MASK 0x00400000L #define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS_MASK 0x00800000L #define DB_RENDER_OVERRIDE2__ALLOW_PARTIAL_RES_HIER_KILL_MASK 0x02000000L +#define DB_RENDER_OVERRIDE2__FORCE_VRS_RATE_FINE_MASK 0x04000000L #define DB_RENDER_OVERRIDE2__CENTROID_COMPUTATION_MODE_MASK 0x18000000L //DB_HTILE_DATA_BASE #define DB_HTILE_DATA_BASE__BASE_256B__SHIFT 0x0 @@ -20021,6 +20031,13 @@ //DB_RESERVED_REG_3 #define DB_RESERVED_REG_3__FIELD_1__SHIFT 0x0 #define DB_RESERVED_REG_3__FIELD_1_MASK 0x003FFFFFL +//DB_VRS_OVERRIDE_CNTL +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_COMBINER_MODE__SHIFT 0x0 +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_X__SHIFT 0x4 +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_Y__SHIFT 0x6 +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_COMBINER_MODE_MASK 0x00000007L +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_X_MASK 0x00000030L +#define DB_VRS_OVERRIDE_CNTL__VRS_OVERRIDE_RATE_Y_MASK 0x000000C0L //DB_Z_READ_BASE_HI #define DB_Z_READ_BASE_HI__BASE_HI__SHIFT 0x0 #define DB_Z_READ_BASE_HI__BASE_HI_MASK 0x000000FFL @@ -22598,6 +22615,7 @@ #define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA__SHIFT 0x18 #define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG__SHIFT 0x19 #define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH__SHIFT 0x1b +#define PA_CL_VS_OUT_CNTL__USE_VTX_VRS_RATE__SHIFT 0x1c #define PA_CL_VS_OUT_CNTL__BYPASS_VTX_RATE_COMBINER__SHIFT 0x1d #define PA_CL_VS_OUT_CNTL__BYPASS_PRIM_RATE_COMBINER__SHIFT 0x1e #define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0_MASK 0x00000001L @@ -22627,6 +22645,7 @@ #define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA_MASK 0x01000000L #define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG_MASK 0x02000000L #define PA_CL_VS_OUT_CNTL__USE_VTX_LINE_WIDTH_MASK 0x08000000L +#define PA_CL_VS_OUT_CNTL__USE_VTX_VRS_RATE_MASK 0x10000000L #define PA_CL_VS_OUT_CNTL__BYPASS_VTX_RATE_COMBINER_MASK 0x20000000L #define PA_CL_VS_OUT_CNTL__BYPASS_PRIM_RATE_COMBINER_MASK 0x40000000L //PA_CL_NANINF_CNTL @@ -22740,6 +22759,19 @@ //PA_STATE_STEREO_X #define PA_STATE_STEREO_X__STEREO_X_OFFSET__SHIFT 0x0 #define PA_STATE_STEREO_X__STEREO_X_OFFSET_MASK 0xFFFFFFFFL +//PA_CL_VRS_CNTL +#define PA_CL_VRS_CNTL__VERTEX_RATE_COMBINER_MODE__SHIFT 0x0 +#define PA_CL_VRS_CNTL__PRIMITIVE_RATE_COMBINER_MODE__SHIFT 0x3 +#define PA_CL_VRS_CNTL__HTILE_RATE_COMBINER_MODE__SHIFT 0x6 +#define PA_CL_VRS_CNTL__SAMPLE_ITER_COMBINER_MODE__SHIFT 0x9 +#define PA_CL_VRS_CNTL__EXPOSE_VRS_PIXELS_MASK__SHIFT 0xd +#define PA_CL_VRS_CNTL__CMASK_RATE_HINT_FORCE_ZERO__SHIFT 0xe +#define PA_CL_VRS_CNTL__VERTEX_RATE_COMBINER_MODE_MASK 0x00000007L +#define PA_CL_VRS_CNTL__PRIMITIVE_RATE_COMBINER_MODE_MASK 0x00000038L +#define PA_CL_VRS_CNTL__HTILE_RATE_COMBINER_MODE_MASK 0x000001C0L +#define PA_CL_VRS_CNTL__SAMPLE_ITER_COMBINER_MODE_MASK 0x00000E00L +#define PA_CL_VRS_CNTL__EXPOSE_VRS_PIXELS_MASK_MASK 0x00002000L +#define PA_CL_VRS_CNTL__CMASK_RATE_HINT_FORCE_ZERO_MASK 0x00004000L //PA_SU_POINT_SIZE #define PA_SU_POINT_SIZE__HEIGHT__SHIFT 0x0 #define PA_SU_POINT_SIZE__WIDTH__SHIFT 0x10 @@ -23088,6 +23120,7 @@ #define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE__SHIFT 0x10 #define DB_HTILE_SURFACE__RESERVED_FIELD_6__SHIFT 0x11 #define DB_HTILE_SURFACE__PIPE_ALIGNED__SHIFT 0x12 +#define DB_HTILE_SURFACE__VRS_HTILE_ENCODING__SHIFT 0x13 #define DB_HTILE_SURFACE__RESERVED_FIELD_1_MASK 0x00000001L #define DB_HTILE_SURFACE__FULL_CACHE_MASK 0x00000002L #define DB_HTILE_SURFACE__RESERVED_FIELD_2_MASK 0x00000004L @@ -23097,6 +23130,7 @@ #define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE_MASK 0x00010000L #define DB_HTILE_SURFACE__RESERVED_FIELD_6_MASK 0x00020000L #define DB_HTILE_SURFACE__PIPE_ALIGNED_MASK 0x00040000L +#define DB_HTILE_SURFACE__VRS_HTILE_ENCODING_MASK 0x00180000L //DB_SRESULTS_COMPARE_STATE0 #define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0__SHIFT 0x0 #define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0__SHIFT 0x4 @@ -24954,6 +24988,7 @@ #define CB_COLOR0_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR0_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR0_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR0_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR0_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR0_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR0_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -24962,6 +24997,7 @@ #define CB_COLOR0_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR0_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR0_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR0_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR1_ATTRIB3 #define CB_COLOR1_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR1_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -24971,6 +25007,7 @@ #define CB_COLOR1_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR1_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR1_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR1_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR1_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR1_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR1_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -24979,6 +25016,7 @@ #define CB_COLOR1_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR1_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR1_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR1_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR2_ATTRIB3 #define CB_COLOR2_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR2_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -24988,6 +25026,7 @@ #define CB_COLOR2_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR2_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR2_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR2_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR2_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR2_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR2_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -24996,6 +25035,7 @@ #define CB_COLOR2_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR2_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR2_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR2_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR3_ATTRIB3 #define CB_COLOR3_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR3_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -25005,6 +25045,7 @@ #define CB_COLOR3_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR3_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR3_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR3_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR3_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR3_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR3_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -25013,6 +25054,7 @@ #define CB_COLOR3_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR3_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR3_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR3_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR4_ATTRIB3 #define CB_COLOR4_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR4_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -25022,6 +25064,7 @@ #define CB_COLOR4_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR4_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR4_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR4_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR4_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR4_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR4_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -25030,6 +25073,7 @@ #define CB_COLOR4_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR4_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR4_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR4_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR5_ATTRIB3 #define CB_COLOR5_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR5_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -25039,6 +25083,7 @@ #define CB_COLOR5_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR5_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR5_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR5_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR5_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR5_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR5_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -25047,6 +25092,7 @@ #define CB_COLOR5_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR5_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR5_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR5_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR6_ATTRIB3 #define CB_COLOR6_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR6_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -25056,6 +25102,7 @@ #define CB_COLOR6_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR6_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR6_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR6_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR6_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR6_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR6_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -25064,6 +25111,7 @@ #define CB_COLOR6_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR6_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR6_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR6_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L //CB_COLOR7_ATTRIB3 #define CB_COLOR7_ATTRIB3__MIP0_DEPTH__SHIFT 0x0 #define CB_COLOR7_ATTRIB3__META_LINEAR__SHIFT 0xd @@ -25073,6 +25121,7 @@ #define CB_COLOR7_ATTRIB3__CMASK_PIPE_ALIGNED__SHIFT 0x1a #define CB_COLOR7_ATTRIB3__RESOURCE_LEVEL__SHIFT 0x1b #define CB_COLOR7_ATTRIB3__DCC_PIPE_ALIGNED__SHIFT 0x1e +#define CB_COLOR7_ATTRIB3__VRS_RATE_HINT_ENABLE__SHIFT 0x1f #define CB_COLOR7_ATTRIB3__MIP0_DEPTH_MASK 0x00001FFFL #define CB_COLOR7_ATTRIB3__META_LINEAR_MASK 0x00002000L #define CB_COLOR7_ATTRIB3__COLOR_SW_MODE_MASK 0x0007C000L @@ -25081,6 +25130,7 @@ #define CB_COLOR7_ATTRIB3__CMASK_PIPE_ALIGNED_MASK 0x04000000L #define CB_COLOR7_ATTRIB3__RESOURCE_LEVEL_MASK 0x38000000L #define CB_COLOR7_ATTRIB3__DCC_PIPE_ALIGNED_MASK 0x40000000L +#define CB_COLOR7_ATTRIB3__VRS_RATE_HINT_ENABLE_MASK 0x80000000L // addressBlock: gc_gfxudec -- GitLab From 2f7c3686a6b26d86017180fab07751645b885f30 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Fri, 1 May 2020 16:45:09 -0400 Subject: [PATCH 1315/1494] drm/amdgpu: add VCN 3.0 AV1 registers This adds the AV1 registers. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../include/asic_reg/vcn/vcn_3_0_0_sh_mask.h | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_3_0_0_sh_mask.h index c0efd90808f23..58cf7adb9d545 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_3_0_0_sh_mask.h @@ -2393,6 +2393,7 @@ #define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC__SHIFT 0x7 #define VCN_FEATURES__HAS_SCLR_DEC__SHIFT 0x8 #define VCN_FEATURES__HAS_VP9_DEC__SHIFT 0x9 +#define VCN_FEATURES__HAS_AV1_DEC__SHIFT 0xa #define VCN_FEATURES__HAS_EFC_ENC__SHIFT 0xb #define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC__SHIFT 0xc #define VCN_FEATURES__HAS_DUAL_MJPEG_DEC__SHIFT 0xd @@ -2407,6 +2408,7 @@ #define VCN_FEATURES__HAS_MJPEG2_IDCT_DEC_MASK 0x00000080L #define VCN_FEATURES__HAS_SCLR_DEC_MASK 0x00000100L #define VCN_FEATURES__HAS_VP9_DEC_MASK 0x00000200L +#define VCN_FEATURES__HAS_AV1_DEC_MASK 0x00000400L #define VCN_FEATURES__HAS_EFC_ENC_MASK 0x00000800L #define VCN_FEATURES__HAS_EFC_HDR2SDR_ENC_MASK 0x00001000L #define VCN_FEATURES__HAS_DUAL_MJPEG_DEC_MASK 0x00002000L @@ -2809,8 +2811,10 @@ #define UVD_SUVD_CGC_GATE__IME_HEVC__SHIFT 0x18 #define UVD_SUVD_CGC_GATE__EFC__SHIFT 0x19 #define UVD_SUVD_CGC_GATE__SAOE__SHIFT 0x1a +#define UVD_SUVD_CGC_GATE__SRE_AV1__SHIFT 0x1b #define UVD_SUVD_CGC_GATE__FBC_PCLK__SHIFT 0x1c #define UVD_SUVD_CGC_GATE__FBC_CCLK__SHIFT 0x1d +#define UVD_SUVD_CGC_GATE__SCM_AV1__SHIFT 0x1e #define UVD_SUVD_CGC_GATE__SMPA__SHIFT 0x1f #define UVD_SUVD_CGC_GATE__SRE_MASK 0x00000001L #define UVD_SUVD_CGC_GATE__SIT_MASK 0x00000002L @@ -2839,8 +2843,10 @@ #define UVD_SUVD_CGC_GATE__IME_HEVC_MASK 0x01000000L #define UVD_SUVD_CGC_GATE__EFC_MASK 0x02000000L #define UVD_SUVD_CGC_GATE__SAOE_MASK 0x04000000L +#define UVD_SUVD_CGC_GATE__SRE_AV1_MASK 0x08000000L #define UVD_SUVD_CGC_GATE__FBC_PCLK_MASK 0x10000000L #define UVD_SUVD_CGC_GATE__FBC_CCLK_MASK 0x20000000L +#define UVD_SUVD_CGC_GATE__SCM_AV1_MASK 0x40000000L #define UVD_SUVD_CGC_GATE__SMPA_MASK 0x80000000L //UVD_SUVD_CGC_STATUS #define UVD_SUVD_CGC_STATUS__SRE_VCLK__SHIFT 0x0 @@ -2873,6 +2879,8 @@ #define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK__SHIFT 0x1b #define UVD_SUVD_CGC_STATUS__EFC_DCLK__SHIFT 0x1c #define UVD_SUVD_CGC_STATUS__SAOE_DCLK__SHIFT 0x1d +#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK__SHIFT 0x1e +#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK__SHIFT 0x1f #define UVD_SUVD_CGC_STATUS__SRE_VCLK_MASK 0x00000001L #define UVD_SUVD_CGC_STATUS__SRE_DCLK_MASK 0x00000002L #define UVD_SUVD_CGC_STATUS__SIT_DCLK_MASK 0x00000004L @@ -2903,6 +2911,8 @@ #define UVD_SUVD_CGC_STATUS__IME_HEVC_DCLK_MASK 0x08000000L #define UVD_SUVD_CGC_STATUS__EFC_DCLK_MASK 0x10000000L #define UVD_SUVD_CGC_STATUS__SAOE_DCLK_MASK 0x20000000L +#define UVD_SUVD_CGC_STATUS__SRE_AV1_VCLK_MASK 0x40000000L +#define UVD_SUVD_CGC_STATUS__SCM_AV1_DCLK_MASK 0x80000000L //UVD_SUVD_CGC_CTRL #define UVD_SUVD_CGC_CTRL__SRE_MODE__SHIFT 0x0 #define UVD_SUVD_CGC_CTRL__SIT_MODE__SHIFT 0x1 @@ -2919,6 +2929,8 @@ #define UVD_SUVD_CGC_CTRL__SMPA_MODE__SHIFT 0xc #define UVD_SUVD_CGC_CTRL__MPBE0_MODE__SHIFT 0xd #define UVD_SUVD_CGC_CTRL__MPBE1_MODE__SHIFT 0xe +#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE__SHIFT 0xf +#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE__SHIFT 0x10 #define UVD_SUVD_CGC_CTRL__MPC1_MODE__SHIFT 0x11 #define UVD_SUVD_CGC_CTRL__FBC_PCLK__SHIFT 0x1c #define UVD_SUVD_CGC_CTRL__FBC_CCLK__SHIFT 0x1d @@ -2937,6 +2949,8 @@ #define UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK 0x00001000L #define UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK 0x00002000L #define UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK 0x00004000L +#define UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK 0x00008000L +#define UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK 0x00010000L #define UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK 0x00020000L #define UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK 0x10000000L #define UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK 0x20000000L @@ -3658,6 +3672,8 @@ #define UVD_SUVD_CGC_STATUS2__SMPA_VCLK__SHIFT 0x0 #define UVD_SUVD_CGC_STATUS2__SMPA_DCLK__SHIFT 0x1 #define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK__SHIFT 0x3 +#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK__SHIFT 0x4 +#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK__SHIFT 0x5 #define UVD_SUVD_CGC_STATUS2__MPC1_DCLK__SHIFT 0x6 #define UVD_SUVD_CGC_STATUS2__MPC1_SCLK__SHIFT 0x7 #define UVD_SUVD_CGC_STATUS2__MPC1_VCLK__SHIFT 0x8 @@ -3666,6 +3682,8 @@ #define UVD_SUVD_CGC_STATUS2__SMPA_VCLK_MASK 0x00000001L #define UVD_SUVD_CGC_STATUS2__SMPA_DCLK_MASK 0x00000002L #define UVD_SUVD_CGC_STATUS2__MPBE1_DCLK_MASK 0x00000008L +#define UVD_SUVD_CGC_STATUS2__SIT_AV1_DCLK_MASK 0x00000010L +#define UVD_SUVD_CGC_STATUS2__SDB_AV1_DCLK_MASK 0x00000020L #define UVD_SUVD_CGC_STATUS2__MPC1_DCLK_MASK 0x00000040L #define UVD_SUVD_CGC_STATUS2__MPC1_SCLK_MASK 0x00000080L #define UVD_SUVD_CGC_STATUS2__MPC1_VCLK_MASK 0x00000100L @@ -3674,25 +3692,41 @@ //UVD_SUVD_CGC_GATE2 #define UVD_SUVD_CGC_GATE2__MPBE0__SHIFT 0x0 #define UVD_SUVD_CGC_GATE2__MPBE1__SHIFT 0x1 +#define UVD_SUVD_CGC_GATE2__SIT_AV1__SHIFT 0x2 +#define UVD_SUVD_CGC_GATE2__SDB_AV1__SHIFT 0x3 #define UVD_SUVD_CGC_GATE2__MPC1__SHIFT 0x4 #define UVD_SUVD_CGC_GATE2__MPBE0_MASK 0x00000001L #define UVD_SUVD_CGC_GATE2__MPBE1_MASK 0x00000002L +#define UVD_SUVD_CGC_GATE2__SIT_AV1_MASK 0x00000004L +#define UVD_SUVD_CGC_GATE2__SDB_AV1_MASK 0x00000008L #define UVD_SUVD_CGC_GATE2__MPC1_MASK 0x00000010L //UVD_SUVD_INT_STATUS2 #define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT__SHIFT 0x0 #define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT__SHIFT 0x5 +#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT__SHIFT 0x6 +#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT__SHIFT 0xb #define UVD_SUVD_INT_STATUS2__SMPA_FUNC_INT_MASK 0x0000001FL #define UVD_SUVD_INT_STATUS2__SMPA_ERR_INT_MASK 0x00000020L +#define UVD_SUVD_INT_STATUS2__SDB_AV1_FUNC_INT_MASK 0x000007C0L +#define UVD_SUVD_INT_STATUS2__SDB_AV1_ERR_INT_MASK 0x00000800L //UVD_SUVD_INT_EN2 #define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN__SHIFT 0x0 #define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN__SHIFT 0x5 +#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN__SHIFT 0x6 +#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN__SHIFT 0xb #define UVD_SUVD_INT_EN2__SMPA_FUNC_INT_EN_MASK 0x0000001FL #define UVD_SUVD_INT_EN2__SMPA_ERR_INT_EN_MASK 0x00000020L +#define UVD_SUVD_INT_EN2__SDB_AV1_FUNC_INT_EN_MASK 0x000007C0L +#define UVD_SUVD_INT_EN2__SDB_AV1_ERR_INT_EN_MASK 0x00000800L //UVD_SUVD_INT_ACK2 #define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK__SHIFT 0x0 #define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK__SHIFT 0x5 +#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK__SHIFT 0x6 +#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK__SHIFT 0xb #define UVD_SUVD_INT_ACK2__SMPA_FUNC_INT_ACK_MASK 0x0000001FL #define UVD_SUVD_INT_ACK2__SMPA_ERR_INT_ACK_MASK 0x00000020L +#define UVD_SUVD_INT_ACK2__SDB_AV1_FUNC_INT_ACK_MASK 0x000007C0L +#define UVD_SUVD_INT_ACK2__SDB_AV1_ERR_INT_ACK_MASK 0x00000800L // addressBlock: uvd0_ecpudec -- GitLab From d9ed8cb5aa1cafa4001b0a081ababcb605e7e9f6 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Fri, 1 May 2020 16:46:11 -0400 Subject: [PATCH 1316/1494] drm/amdgpu: use the AV1 defines for VCN 3.0 Switch from magic numbers to defines for AV1 clockgating. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 589d6cd8adec9..e074f7ed388c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -746,18 +746,18 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst) | UVD_SUVD_CGC_GATE__IME_HEVC_MASK | UVD_SUVD_CGC_GATE__EFC_MASK | UVD_SUVD_CGC_GATE__SAOE_MASK - | 0x08000000 + | UVD_SUVD_CGC_GATE__SRE_AV1_MASK | UVD_SUVD_CGC_GATE__FBC_PCLK_MASK | UVD_SUVD_CGC_GATE__FBC_CCLK_MASK - | 0x40000000 + | UVD_SUVD_CGC_GATE__SCM_AV1_MASK | UVD_SUVD_CGC_GATE__SMPA_MASK); WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE, data); data = RREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2); data |= (UVD_SUVD_CGC_GATE2__MPBE0_MASK | UVD_SUVD_CGC_GATE2__MPBE1_MASK - | 0x00000004 - | 0x00000008 + | UVD_SUVD_CGC_GATE2__SIT_AV1_MASK + | UVD_SUVD_CGC_GATE2__SDB_AV1_MASK | UVD_SUVD_CGC_GATE2__MPC1_MASK); WREG32_SOC15(VCN, inst, mmUVD_SUVD_CGC_GATE2, data); @@ -776,8 +776,8 @@ static void vcn_v3_0_disable_clock_gating(struct amdgpu_device *adev, int inst) | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK - | 0x00008000 - | 0x00010000 + | UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK + | UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK); @@ -892,8 +892,8 @@ static void vcn_v3_0_enable_clock_gating(struct amdgpu_device *adev, int inst) | UVD_SUVD_CGC_CTRL__SMPA_MODE_MASK | UVD_SUVD_CGC_CTRL__MPBE0_MODE_MASK | UVD_SUVD_CGC_CTRL__MPBE1_MODE_MASK - | 0x00008000 - | 0x00010000 + | UVD_SUVD_CGC_CTRL__SIT_AV1_MODE_MASK + | UVD_SUVD_CGC_CTRL__SDB_AV1_MODE_MASK | UVD_SUVD_CGC_CTRL__MPC1_MODE_MASK | UVD_SUVD_CGC_CTRL__FBC_PCLK_MASK | UVD_SUVD_CGC_CTRL__FBC_CCLK_MASK); -- GitLab From 61278d14bb483308c6065ff3da0f71383ea97403 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Thu, 16 Jan 2020 10:45:38 +0800 Subject: [PATCH 1317/1494] drm/amdgpu: add device ID for sienna_cichlid (v2) Add device ID for sienna_cichlid. v2: squash in additional device ids. Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 52cf9488bbbff..0d4c1d68bfb73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1075,6 +1075,14 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT}, {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT}, + /* Sienna_Cichlid */ + {0x1002, 0x73A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0x1002, 0x73A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0x1002, 0x73A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0x1002, 0x73AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0x1002, 0x73AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, + {0, 0, 0} }; -- GitLab From 8c4e4fd607b17973e54a7e9cc4c275b12ab7308e Mon Sep 17 00:00:00 2001 From: Mauro Rossi <issor.oruam@gmail.com> Date: Thu, 17 Sep 2020 09:33:31 +0200 Subject: [PATCH 1318/1494] drm/amd/display: dc/clk_mgr: make function static [Why] linux-next kernel test robot reported the following problem: warning: no previous prototype for 'dce60_get_dp_ref_freq_khz' [-Wmissing-prototypes] [How] mark dce60_get_dp_ref_freq_khz() as static Fixes: 3ecb3b794e2c "drm/amd/display: dc/clk_mgr: add support for SI parts (v2)" Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Mauro Rossi <issor.oruam@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c index c11c6b3a787d2..0267644717b27 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -80,7 +80,7 @@ static const struct state_dependent_clocks dce60_max_clks_by_state[] = { /* ClocksStatePerformance */ { .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; -int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) +static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); int dprefclk_wdivider; -- GitLab From 71f49c4898eef4b0a5bb39549d8459cbb0ad70ab Mon Sep 17 00:00:00 2001 From: Ye Bin <yebin10@huawei.com> Date: Thu, 17 Sep 2020 18:57:59 +0800 Subject: [PATCH 1319/1494] drm/amd/display: Delete duplicated argument to '&&' or '||' Fixes coccicheck warnig: drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c:282:12-42: duplicated argument to && or || drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c:3240:12-42: duplicated argument to && or || drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c:5520:7-91: duplicated argument to && or || drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c:5309:86-122: duplicated argument to && or || Fixes: 6725a88f88a7 ("drm/amd/display: Add DCN3 DML") Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Ye Bin <yebin10@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 6 +++--- .../drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 8f8bf83a60a17..50b7d011705d1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -3237,7 +3237,7 @@ static bool CalculateBytePerPixelAnd256BBlockSizes( *BytePerPixelDETC = 0; *BytePerPixelY = 4; *BytePerPixelC = 0; - } else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) { + } else if (SourcePixelFormat == dm_444_16) { *BytePerPixelDETY = 2; *BytePerPixelDETC = 0; *BytePerPixelY = 2; @@ -5307,7 +5307,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l ViewportExceedsSurface = true; if (v->SourcePixelFormat[k] != dm_444_64 && v->SourcePixelFormat[k] != dm_444_32 && v->SourcePixelFormat[k] != dm_444_16 - && v->SourcePixelFormat[k] != dm_444_16 && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) { + && v->SourcePixelFormat[k] != dm_444_8 && v->SourcePixelFormat[k] != dm_rgbe) { if (v->ViewportWidthChroma[k] > v->SurfaceWidthC[k] || v->ViewportHeightChroma[k] > v->SurfaceHeightC[k]) { ViewportExceedsSurface = true; } @@ -5517,7 +5517,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( if (WritebackPixelFormat[k] == dm_444_64) { WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding / 2; } - if (mode_lib->vba.WritebackConfiguration == dm_whole_buffer_for_single_stream_interleave || mode_lib->vba.WritebackConfiguration == dm_whole_buffer_for_single_stream_interleave) { + if (mode_lib->vba.WritebackConfiguration == dm_whole_buffer_for_single_stream_interleave) { WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding * 2; } WritebackDRAMClockChangeLatencyMargin = WritebackDRAMClockChangeLatencyHiding - mode_lib->vba.WritebackDRAMClockChangeWatermark; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 5bb10f6e300df..416bf6fb67bd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -279,7 +279,7 @@ static bool CalculateBytePerPixelAnd256BBlockSizes( *BytePerPixelDETC = 0; *BytePerPixelY = 4; *BytePerPixelC = 0; - } else if (SourcePixelFormat == dm_444_16 || SourcePixelFormat == dm_444_16) { + } else if (SourcePixelFormat == dm_444_16) { *BytePerPixelDETY = 2; *BytePerPixelDETC = 0; *BytePerPixelY = 2; -- GitLab From 35d1a405cada8b61dd866e7815a226486b8d55b2 Mon Sep 17 00:00:00 2001 From: Xiaoliang Pang <dawning.pang@gmail.com> Date: Thu, 17 Sep 2020 11:46:10 +0800 Subject: [PATCH 1320/1494] drm/amdgpu/powerplay: hwmgr - modify the return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return value should be -EINVAL rather than EINVAL Fixes: f83a9991648bb("drm/amd/powerplay: add Vega10 powerplay support (v5)") Fixes: 2cac05dee6e30("drm/amd/powerplay: add the hw manager for vega12 (v4)") Cc: Eric Huang <JinHuiEric.Huang@amd.com> Cc: Evan Quan <evan.quan@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Signed-off-by: Xiaoliang Pang <dawning.pang@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 2 +- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index c378a000c9344..7eada3098ffcc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -4659,7 +4659,7 @@ static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) if ((data->water_marks_bitmap & WaterMarksExist) && !(data->water_marks_bitmap & WaterMarksLoaded)) { result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false); - PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); + PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL); data->water_marks_bitmap |= WaterMarksLoaded; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c index f0680dd585089..dc206fa88c5e5 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c @@ -2444,7 +2444,7 @@ static int vega12_display_configuration_changed_task(struct pp_hwmgr *hwmgr) !(data->water_marks_bitmap & WaterMarksLoaded)) { result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, TABLE_WATERMARKS, false); - PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); + PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return -EINVAL); data->water_marks_bitmap |= WaterMarksLoaded; } -- GitLab From 8a491bb31ba40246ae15cbb3c044d72fb9e0d13e Mon Sep 17 00:00:00 2001 From: Philip Cox <Philip.Cox@amd.com> Date: Mon, 29 Jun 2020 09:49:59 -0400 Subject: [PATCH 1321/1494] drm/amdkfd: Add some eveiction debugging code Extending the module parameter debug_evictions to also print a stack trace when the eviction code path is called. Signed-off-by: Philip Cox <Philip.Cox@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 20ef048d6a034..cafbc3aa980a6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1966,6 +1966,7 @@ int kfd_process_vm_fault(struct device_queue_manager *dqm, if (!p) return -EINVAL; + WARN(debug_evictions, "Evicting pid %d", p->lead_thread->pid); pdd = kfd_get_process_device_data(dqm->dev, p); if (pdd) ret = dqm->ops.evict_process_queues(dqm, &pdd->qpd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index a0e12a79ab7d9..1e15aa7d8ae8c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1488,6 +1488,7 @@ void kfd_suspend_all_processes(void) unsigned int temp; int idx = srcu_read_lock(&kfd_processes_srcu); + WARN(debug_evictions, "Evicting all processes"); hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { cancel_delayed_work_sync(&p->eviction_work); cancel_delayed_work_sync(&p->restore_work); -- GitLab From 4327bed2ff8e3ddc57beb27fed8ad2faef240d72 Mon Sep 17 00:00:00 2001 From: Philip Cox <Philip.Cox@amd.com> Date: Tue, 30 Jun 2020 15:51:05 -0400 Subject: [PATCH 1322/1494] drm/amdkfd: Add process eviction counters to sysfs Add per-process eviction counters to sysfs to keep track of how many eviction events have happened for each process. v2: rename the stats dir, and track all evictions per process, per device. v3: Simplify the stats kobject handling and cleanup. v4: more code cleanup Signed-off-by: Philip Cox <Philip.Cox@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 8 ++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 9 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 100 ++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index cafbc3aa980a6..7ef33ea8d37f4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -653,6 +653,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, pr_info_ratelimited("Evicting PASID 0x%x queues\n", pdd->process->pasid); + pdd->last_evict_timestamp = get_jiffies_64(); /* Mark all queues as evicted. Deactivate all active queues on * the qpd. */ @@ -714,6 +715,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, q->properties.is_active = false; decrement_queue_count(dqm, q->properties.type); } + pdd->last_evict_timestamp = get_jiffies_64(); retval = execute_queues_cpsch(dqm, qpd->is_debug ? KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES : @@ -732,6 +734,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, struct mqd_manager *mqd_mgr; struct kfd_process_device *pdd; uint64_t pd_base; + uint64_t eviction_duration; int retval, ret = 0; pdd = qpd_to_pdd(qpd); @@ -799,6 +802,8 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, ret = retval; } qpd->evicted = 0; + eviction_duration = get_jiffies_64() - pdd->last_evict_timestamp; + atomic64_add(eviction_duration, &pdd->evict_duration_counter); out: if (mm) mmput(mm); @@ -812,6 +817,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm, struct queue *q; struct kfd_process_device *pdd; uint64_t pd_base; + uint64_t eviction_duration; int retval = 0; pdd = qpd_to_pdd(qpd); @@ -845,6 +851,8 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm, retval = execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); qpd->evicted = 0; + eviction_duration = get_jiffies_64() - pdd->last_evict_timestamp; + atomic64_add(eviction_duration, &pdd->evict_duration_counter); out: dqm_unlock(dqm); return retval; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 023629f284951..8c2b8ccd27fb7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -631,7 +631,7 @@ enum kfd_pdd_bound { PDD_BOUND_SUSPENDED, }; -#define MAX_SYSFS_FILENAME_LEN 11 +#define MAX_SYSFS_FILENAME_LEN 15 /* * SDMA counter runs at 100MHz frequency. @@ -692,6 +692,13 @@ struct kfd_process_device { uint64_t sdma_past_activity_counter; struct attribute attr_sdma; char sdma_filename[MAX_SYSFS_FILENAME_LEN]; + + /* Eviction activity tracking */ + uint64_t last_evict_timestamp; + atomic64_t evict_duration_counter; + struct attribute attr_evict; + + struct kobject *kobj_stats; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 1e15aa7d8ae8c..ad53b2668221f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -344,6 +344,26 @@ static ssize_t kfd_procfs_queue_show(struct kobject *kobj, return 0; } +static ssize_t kfd_procfs_stats_show(struct kobject *kobj, + struct attribute *attr, char *buffer) +{ + if (strcmp(attr->name, "evicted_ms") == 0) { + struct kfd_process_device *pdd = container_of(attr, + struct kfd_process_device, + attr_evict); + uint64_t evict_jiffies; + + evict_jiffies = atomic64_read(&pdd->evict_duration_counter); + + return snprintf(buffer, + PAGE_SIZE, + "%llu\n", + jiffies64_to_msecs(evict_jiffies)); + } else + pr_err("Invalid attribute"); + + return 0; +} static struct attribute attr_queue_size = { .name = "size", @@ -376,6 +396,19 @@ static struct kobj_type procfs_queue_type = { .default_attrs = procfs_queue_attrs, }; +static const struct sysfs_ops procfs_stats_ops = { + .show = kfd_procfs_stats_show, +}; + +static struct attribute *procfs_stats_attrs[] = { + NULL +}; + +static struct kobj_type procfs_stats_type = { + .sysfs_ops = &procfs_stats_ops, + .default_attrs = procfs_stats_attrs, +}; + int kfd_procfs_add_queue(struct queue *q) { struct kfd_process *proc; @@ -417,6 +450,58 @@ static int kfd_sysfs_create_file(struct kfd_process *p, struct attribute *attr, return ret; } +static int kfd_procfs_add_sysfs_stats(struct kfd_process *p) +{ + int ret = 0; + struct kfd_process_device *pdd; + char stats_dir_filename[MAX_SYSFS_FILENAME_LEN]; + + if (!p) + return -EINVAL; + + if (!p->kobj) + return -EFAULT; + + /* + * Create sysfs files for each GPU: + * - proc/<pid>/stats_<gpuid>/ + * - proc/<pid>/stats_<gpuid>/evicted_ms + */ + list_for_each_entry(pdd, &p->per_device_data, per_device_list) { + struct kobject *kobj_stats; + + snprintf(stats_dir_filename, MAX_SYSFS_FILENAME_LEN, + "stats_%u", pdd->dev->id); + kobj_stats = kfd_alloc_struct(kobj_stats); + if (!kobj_stats) + return -ENOMEM; + + ret = kobject_init_and_add(kobj_stats, + &procfs_stats_type, + p->kobj, + stats_dir_filename); + + if (ret) { + pr_warn("Creating KFD proc/stats_%s folder failed", + stats_dir_filename); + kobject_put(kobj_stats); + goto err; + } + + pdd->kobj_stats = kobj_stats; + pdd->attr_evict.name = "evicted_ms"; + pdd->attr_evict.mode = KFD_SYSFS_FILE_MODE; + sysfs_attr_init(&pdd->attr_evict); + ret = sysfs_create_file(kobj_stats, &pdd->attr_evict); + if (ret) + pr_warn("Creating eviction stats for gpuid %d failed", + (int)pdd->dev->id); + } +err: + return ret; +} + + static int kfd_procfs_add_sysfs_files(struct kfd_process *p) { int ret = 0; @@ -660,6 +745,16 @@ struct kfd_process *kfd_create_process(struct file *filep) if (!process->kobj_queues) pr_warn("Creating KFD proc/queues folder failed"); + ret = kfd_procfs_add_sysfs_stats(process); + if (ret) + pr_warn("Creating sysfs stats dir for pid %d failed", + (int)process->lead_thread->pid); + + ret = kfd_procfs_add_sysfs_stats(process); + if (ret) + pr_warn("Creating sysfs stats dir for pid %d failed", + (int)process->lead_thread->pid); + ret = kfd_procfs_add_sysfs_files(process); if (ret) pr_warn("Creating sysfs usage file for pid %d failed", @@ -816,6 +911,10 @@ static void kfd_process_wq_release(struct work_struct *work) list_for_each_entry(pdd, &p->per_device_data, per_device_list) { sysfs_remove_file(p->kobj, &pdd->attr_vram); sysfs_remove_file(p->kobj, &pdd->attr_sdma); + sysfs_remove_file(p->kobj, &pdd->attr_evict); + kobject_del(pdd->kobj_stats); + kobject_put(pdd->kobj_stats); + pdd->kobj_stats = NULL; } kobject_del(p->kobj); @@ -1125,6 +1224,7 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, pdd->runtime_inuse = false; pdd->vram_usage = 0; pdd->sdma_past_activity_counter = 0; + atomic64_set(&pdd->evict_duration_counter, 0); list_add(&pdd->per_device_list, &p->per_device_data); /* Init idr used for memory handle translation */ -- GitLab From 783a25f4c7bc9a75099f5b0df78e4e8459ec851b Mon Sep 17 00:00:00 2001 From: Philip Cox <Philip.Cox@amd.com> Date: Wed, 9 Sep 2020 15:44:14 -0400 Subject: [PATCH 1323/1494] drm/amdkfd: Reduce eviction/restore message levels Reduce the eviction and restore messages from INFO level to DEBUG level. Signed-off-by: Philip Cox <Philip.Cox@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 7ef33ea8d37f4..ed362ab8ec21a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -650,7 +650,7 @@ static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, goto out; pdd = qpd_to_pdd(qpd); - pr_info_ratelimited("Evicting PASID 0x%x queues\n", + pr_debug_ratelimited("Evicting PASID 0x%x queues\n", pdd->process->pasid); pdd->last_evict_timestamp = get_jiffies_64(); @@ -701,7 +701,7 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm, goto out; pdd = qpd_to_pdd(qpd); - pr_info_ratelimited("Evicting PASID 0x%x queues\n", + pr_debug_ratelimited("Evicting PASID 0x%x queues\n", pdd->process->pasid); /* Mark all queues as evicted. Deactivate all active queues on @@ -749,7 +749,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, goto out; } - pr_info_ratelimited("Restoring PASID 0x%x queues\n", + pr_debug_ratelimited("Restoring PASID 0x%x queues\n", pdd->process->pasid); /* Update PD Base in QPD */ @@ -832,7 +832,7 @@ static int restore_process_queues_cpsch(struct device_queue_manager *dqm, goto out; } - pr_info_ratelimited("Restoring PASID 0x%x queues\n", + pr_debug_ratelimited("Restoring PASID 0x%x queues\n", pdd->process->pasid); /* Update PD Base in QPD */ -- GitLab From d34c7b7b6b9180cc4a1d3447c398792e65c7b04e Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 15 Sep 2020 13:36:20 -0400 Subject: [PATCH 1324/1494] drm/amdgpu: remove experimental flag from navi12 Navi12 has worked fine for a while now. Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 0d4c1d68bfb73..a4b518211b1f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1072,8 +1072,8 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU}, /* Navi12 */ - {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12}, + {0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12}, /* Sienna_Cichlid */ {0x1002, 0x73A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID}, -- GitLab From 85649cc8dc509dfb97f5ac87f7efefe03539323a Mon Sep 17 00:00:00 2001 From: Yuti Amonkar <yamonkar@cadence.com> Date: Fri, 18 Sep 2020 14:09:21 +0200 Subject: [PATCH 1325/1494] dt-bindings: drm/bridge: Document Cadence MHDP8546 bridge bindings Document the bindings used for the Cadence MHDP8546 DPI/DP bridge in yaml format. Signed-off-by: Yuti Amonkar <yamonkar@cadence.com> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com> Reviewed-by: Rob Herring <robh@kernel.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> --- .../display/bridge/cdns,mhdp8546.yaml | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml new file mode 100644 index 0000000000000..74d675fc6e7ba --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml @@ -0,0 +1,169 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/display/bridge/cdns,mhdp8546.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Cadence MHDP8546 bridge + +maintainers: + - Swapnil Jakhade <sjakhade@cadence.com> + - Yuti Amonkar <yamonkar@cadence.com> + +properties: + compatible: + enum: + - cdns,mhdp8546 + - ti,j721e-mhdp8546 + + reg: + minItems: 1 + maxItems: 2 + items: + - description: + Register block of mhdptx apb registers up to PHY mapped area (AUX_CONFIG_P). + The AUX and PMA registers are not part of this range, they are instead + included in the associated PHY. + - description: + Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI J7 SoCs. + + reg-names: + minItems: 1 + maxItems: 2 + items: + - const: mhdptx + - const: j721e-intg + + clocks: + maxItems: 1 + description: + DP bridge clock, used by the IP to know how to translate a number of + clock cycles into a time (which is used to comply with DP standard timings + and delays). + + phys: + maxItems: 1 + description: + phandle to the DisplayPort PHY. + + phy-names: + items: + - const: dpphy + + power-domains: + maxItems: 1 + + interrupts: + maxItems: 1 + + ports: + type: object + description: + Ports as described in Documentation/devicetree/bindings/graph.txt. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + port@0: + type: object + description: + First input port representing the DP bridge input. + + port@1: + type: object + description: + Second input port representing the DP bridge input. + + port@2: + type: object + description: + Third input port representing the DP bridge input. + + port@3: + type: object + description: + Fourth input port representing the DP bridge input. + + port@4: + type: object + description: + Output port representing the DP bridge output. + + required: + - port@0 + - port@4 + - '#address-cells' + - '#size-cells' + +allOf: + - if: + properties: + compatible: + contains: + const: ti,j721e-mhdp8546 + then: + properties: + reg: + minItems: 2 + reg-names: + minItems: 2 + else: + properties: + reg: + maxItems: 1 + reg-names: + maxItems: 1 + +required: + - compatible + - clocks + - reg + - reg-names + - phys + - phy-names + - interrupts + - ports + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + bus { + #address-cells = <2>; + #size-cells = <2>; + + mhdp: dp-bridge@f0fb000000 { + compatible = "cdns,mhdp8546"; + reg = <0xf0 0xfb000000 0x0 0x1000000>; + reg-names = "mhdptx"; + clocks = <&mhdp_clock>; + phys = <&dp_phy>; + phy-names = "dpphy"; + interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dp_bridge_input: endpoint { + remote-endpoint = <&xxx_dpi_output>; + }; + }; + + port@4 { + reg = <4>; + dp_bridge_output: endpoint { + remote-endpoint = <&xxx_dp_connector_input>; + }; + }; + }; + }; + }; +... -- GitLab From fb43aa0acdfd600c75b8c877bdf9f6e9893ffc9b Mon Sep 17 00:00:00 2001 From: Swapnil Jakhade <sjakhade@cadence.com> Date: Fri, 18 Sep 2020 14:09:22 +0200 Subject: [PATCH 1326/1494] drm: bridge: Add support for Cadence MHDP8546 DPI/DP bridge Add a new DRM bridge driver for Cadence MHDP8546 DPTX IP used in TI J721E SoC. MHDP DPTX IP is the component that complies with VESA DisplayPort (DP) and embedded Display Port (eDP) standards. It integrates uCPU running the embedded Firmware (FW) interfaced over APB interface. Basically, it takes a DPI stream as input and outputs it encoded in DP format. Currently, it supports only SST mode. Co-developed-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Co-developed-by: Jyri Sarha <jsarha@ti.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Jyri Sarha <jsarha@ti.com> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com> Signed-off-by: Yuti Amonkar <yamonkar@cadence.com> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> --- drivers/gpu/drm/bridge/Kconfig | 2 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/cadence/Kconfig | 11 + drivers/gpu/drm/bridge/cadence/Makefile | 3 + .../drm/bridge/cadence/cdns-mhdp8546-core.c | 2522 +++++++++++++++++ .../drm/bridge/cadence/cdns-mhdp8546-core.h | 399 +++ 6 files changed, 2938 insertions(+) create mode 100644 drivers/gpu/drm/bridge/cadence/Kconfig create mode 100644 drivers/gpu/drm/bridge/cadence/Makefile create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 3e11af4e9f63e..ef91646441b16 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -241,6 +241,8 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig" source "drivers/gpu/drm/bridge/adv7511/Kconfig" +source "drivers/gpu/drm/bridge/cadence/Kconfig" + source "drivers/gpu/drm/bridge/synopsys/Kconfig" endmenu diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index c589a6a7cbe1d..2b3aff104e466 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -25,4 +25,5 @@ obj-$(CONFIG_DRM_TI_TPD12S015) += ti-tpd12s015.o obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o obj-y += analogix/ +obj-y += cadence/ obj-y += synopsys/ diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig new file mode 100644 index 0000000000000..f49d77eb78148 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config DRM_CDNS_MHDP8546 + tristate "Cadence DPI/DP bridge" + select DRM_KMS_HELPER + select DRM_PANEL_BRIDGE + depends on OF + help + Support Cadence DPI to DP bridge. This is an internal + bridge and is meant to be directly embedded in a SoC. + It takes a DPI stream as input and outputs it encoded + in DP format. diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile new file mode 100644 index 0000000000000..676739cdf5e62 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o +cdns-mhdp8546-y := cdns-mhdp8546-core.o diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c new file mode 100644 index 0000000000000..7b1bd5d10923e --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -0,0 +1,2522 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cadence MHDP8546 DP bridge driver. + * + * Copyright (C) 2020 Cadence Design Systems, Inc. + * + * Authors: Quentin Schulz <quentin.schulz@free-electrons.com> + * Swapnil Jakhade <sjakhade@cadence.com> + * Yuti Amonkar <yamonkar@cadence.com> + * Tomi Valkeinen <tomi.valkeinen@ti.com> + * Jyri Sarha <jsarha@ti.com> + * + * TODO: + * - Implement optimized mailbox communication using mailbox interrupts + * - Add support for power management + * - Add support for features like audio, MST and fast link training + * - Implement request_fw_cancel to handle HW_STATE + * - Fix asynchronous loading of firmware implementation + * - Add DRM helper function for cdns_mhdp_lower_link_rate + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/firmware.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/phy/phy.h> +#include <linux/phy/phy-dp.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/wait.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_bridge.h> +#include <drm/drm_connector.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + +#include <asm/unaligned.h> + +#include "cdns-mhdp8546-core.h" + +static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) +{ + int ret, empty; + + WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); + + ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_EMPTY, + empty, !empty, MAILBOX_RETRY_US, + MAILBOX_TIMEOUT_US); + if (ret < 0) + return ret; + + return readl(mhdp->regs + CDNS_MAILBOX_RX_DATA) & 0xff; +} + +static int cdns_mhdp_mailbox_write(struct cdns_mhdp_device *mhdp, u8 val) +{ + int ret, full; + + WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); + + ret = readx_poll_timeout(readl, mhdp->regs + CDNS_MAILBOX_FULL, + full, !full, MAILBOX_RETRY_US, + MAILBOX_TIMEOUT_US); + if (ret < 0) + return ret; + + writel(val, mhdp->regs + CDNS_MAILBOX_TX_DATA); + + return 0; +} + +static int cdns_mhdp_mailbox_recv_header(struct cdns_mhdp_device *mhdp, + u8 module_id, u8 opcode, + u16 req_size) +{ + u32 mbox_size, i; + u8 header[4]; + int ret; + + /* read the header of the message */ + for (i = 0; i < sizeof(header); i++) { + ret = cdns_mhdp_mailbox_read(mhdp); + if (ret < 0) + return ret; + + header[i] = ret; + } + + mbox_size = get_unaligned_be16(header + 2); + + if (opcode != header[0] || module_id != header[1] || + req_size != mbox_size) { + /* + * If the message in mailbox is not what we want, we need to + * clear the mailbox by reading its contents. + */ + for (i = 0; i < mbox_size; i++) + if (cdns_mhdp_mailbox_read(mhdp) < 0) + break; + + return -EINVAL; + } + + return 0; +} + +static int cdns_mhdp_mailbox_recv_data(struct cdns_mhdp_device *mhdp, + u8 *buff, u16 buff_size) +{ + u32 i; + int ret; + + for (i = 0; i < buff_size; i++) { + ret = cdns_mhdp_mailbox_read(mhdp); + if (ret < 0) + return ret; + + buff[i] = ret; + } + + return 0; +} + +static int cdns_mhdp_mailbox_send(struct cdns_mhdp_device *mhdp, u8 module_id, + u8 opcode, u16 size, u8 *message) +{ + u8 header[4]; + int ret, i; + + header[0] = opcode; + header[1] = module_id; + put_unaligned_be16(size, header + 2); + + for (i = 0; i < sizeof(header); i++) { + ret = cdns_mhdp_mailbox_write(mhdp, header[i]); + if (ret) + return ret; + } + + for (i = 0; i < size; i++) { + ret = cdns_mhdp_mailbox_write(mhdp, message[i]); + if (ret) + return ret; + } + + return 0; +} + +static +int cdns_mhdp_reg_read(struct cdns_mhdp_device *mhdp, u32 addr, u32 *value) +{ + u8 msg[4], resp[8]; + int ret; + + put_unaligned_be32(addr, msg); + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_READ, + sizeof(msg), msg); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_GENERAL, + GENERAL_REGISTER_READ, + sizeof(resp)); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, resp, sizeof(resp)); + if (ret) + goto out; + + /* Returned address value should be the same as requested */ + if (memcmp(msg, resp, sizeof(msg))) { + ret = -EINVAL; + goto out; + } + + *value = get_unaligned_be32(resp + 4); + +out: + mutex_unlock(&mhdp->mbox_mutex); + if (ret) { + dev_err(mhdp->dev, "Failed to read register\n"); + *value = 0; + } + + return ret; +} + +static +int cdns_mhdp_reg_write(struct cdns_mhdp_device *mhdp, u16 addr, u32 val) +{ + u8 msg[6]; + int ret; + + put_unaligned_be16(addr, msg); + put_unaligned_be32(val, msg + 2); + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_WRITE_REGISTER, sizeof(msg), msg); + + mutex_unlock(&mhdp->mbox_mutex); + + return ret; +} + +static +int cdns_mhdp_reg_write_bit(struct cdns_mhdp_device *mhdp, u16 addr, + u8 start_bit, u8 bits_no, u32 val) +{ + u8 field[8]; + int ret; + + put_unaligned_be16(addr, field); + field[2] = start_bit; + field[3] = bits_no; + put_unaligned_be32(val, field + 4); + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_WRITE_FIELD, sizeof(field), field); + + mutex_unlock(&mhdp->mbox_mutex); + + return ret; +} + +static +int cdns_mhdp_dpcd_read(struct cdns_mhdp_device *mhdp, + u32 addr, u8 *data, u16 len) +{ + u8 msg[5], reg[5]; + int ret; + + put_unaligned_be16(len, msg); + put_unaligned_be24(addr, msg + 2); + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_READ_DPCD, sizeof(msg), msg); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_READ_DPCD, + sizeof(reg) + len); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, data, len); + +out: + mutex_unlock(&mhdp->mbox_mutex); + + return ret; +} + +static +int cdns_mhdp_dpcd_write(struct cdns_mhdp_device *mhdp, u32 addr, u8 value) +{ + u8 msg[6], reg[5]; + int ret; + + put_unaligned_be16(1, msg); + put_unaligned_be24(addr, msg + 2); + msg[5] = value; + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_WRITE_DPCD, sizeof(msg), msg); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_WRITE_DPCD, sizeof(reg)); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); + if (ret) + goto out; + + if (addr != get_unaligned_be24(reg + 2)) + ret = -EINVAL; + +out: + mutex_unlock(&mhdp->mbox_mutex); + + if (ret) + dev_err(mhdp->dev, "dpcd write failed: %d\n", ret); + return ret; +} + +static +int cdns_mhdp_set_firmware_active(struct cdns_mhdp_device *mhdp, bool enable) +{ + u8 msg[5]; + int ret, i; + + msg[0] = GENERAL_MAIN_CONTROL; + msg[1] = MB_MODULE_ID_GENERAL; + msg[2] = 0; + msg[3] = 1; + msg[4] = enable ? FW_ACTIVE : FW_STANDBY; + + mutex_lock(&mhdp->mbox_mutex); + + for (i = 0; i < sizeof(msg); i++) { + ret = cdns_mhdp_mailbox_write(mhdp, msg[i]); + if (ret) + goto out; + } + + /* read the firmware state */ + ret = cdns_mhdp_mailbox_recv_data(mhdp, msg, sizeof(msg)); + if (ret) + goto out; + + ret = 0; + +out: + mutex_unlock(&mhdp->mbox_mutex); + + if (ret < 0) + dev_err(mhdp->dev, "set firmware active failed\n"); + return ret; +} + +static +int cdns_mhdp_get_hpd_status(struct cdns_mhdp_device *mhdp) +{ + u8 status; + int ret; + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_HPD_STATE, 0, NULL); + if (ret) + goto err_get_hpd; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_HPD_STATE, + sizeof(status)); + if (ret) + goto err_get_hpd; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, &status, sizeof(status)); + if (ret) + goto err_get_hpd; + + mutex_unlock(&mhdp->mbox_mutex); + + dev_dbg(mhdp->dev, "%s: HPD %splugged\n", __func__, + status ? "" : "un"); + + return status; + +err_get_hpd: + mutex_unlock(&mhdp->mbox_mutex); + + return ret; +} + +static +int cdns_mhdp_get_edid_block(void *data, u8 *edid, + unsigned int block, size_t length) +{ + struct cdns_mhdp_device *mhdp = data; + u8 msg[2], reg[2], i; + int ret; + + mutex_lock(&mhdp->mbox_mutex); + + for (i = 0; i < 4; i++) { + msg[0] = block / 2; + msg[1] = block % 2; + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_GET_EDID, sizeof(msg), msg); + if (ret) + continue; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_GET_EDID, + sizeof(reg) + length); + if (ret) + continue; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, reg, sizeof(reg)); + if (ret) + continue; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, edid, length); + if (ret) + continue; + + if (reg[0] == length && reg[1] == block / 2) + break; + } + + mutex_unlock(&mhdp->mbox_mutex); + + if (ret) + dev_err(mhdp->dev, "get block[%d] edid failed: %d\n", + block, ret); + + return ret; +} + +static +int cdns_mhdp_read_hpd_event(struct cdns_mhdp_device *mhdp) +{ + u8 event = 0; + int ret; + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_READ_EVENT, 0, NULL); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_READ_EVENT, sizeof(event)); + if (ret < 0) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, &event, sizeof(event)); +out: + mutex_unlock(&mhdp->mbox_mutex); + + if (ret < 0) + return ret; + + dev_dbg(mhdp->dev, "%s: %s%s%s%s\n", __func__, + (event & DPTX_READ_EVENT_HPD_TO_HIGH) ? "TO_HIGH " : "", + (event & DPTX_READ_EVENT_HPD_TO_LOW) ? "TO_LOW " : "", + (event & DPTX_READ_EVENT_HPD_PULSE) ? "PULSE " : "", + (event & DPTX_READ_EVENT_HPD_STATE) ? "HPD_STATE " : ""); + + return event; +} + +static +int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes, + unsigned int udelay, const u8 *lanes_data, + u8 link_status[DP_LINK_STATUS_SIZE]) +{ + u8 payload[7]; + u8 hdr[5]; /* For DPCD read response header */ + u32 addr; + int ret; + + if (nlanes != 4 && nlanes != 2 && nlanes != 1) { + dev_err(mhdp->dev, "invalid number of lanes: %u\n", nlanes); + ret = -EINVAL; + goto out; + } + + payload[0] = nlanes; + put_unaligned_be16(udelay, payload + 1); + memcpy(payload + 3, lanes_data, nlanes); + + mutex_lock(&mhdp->mbox_mutex); + + ret = cdns_mhdp_mailbox_send(mhdp, MB_MODULE_ID_DP_TX, + DPTX_ADJUST_LT, + sizeof(payload), payload); + if (ret) + goto out; + + /* Yes, read the DPCD read command response */ + ret = cdns_mhdp_mailbox_recv_header(mhdp, MB_MODULE_ID_DP_TX, + DPTX_READ_DPCD, + sizeof(hdr) + DP_LINK_STATUS_SIZE); + if (ret) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, hdr, sizeof(hdr)); + if (ret) + goto out; + + addr = get_unaligned_be24(hdr + 2); + if (addr != DP_LANE0_1_STATUS) + goto out; + + ret = cdns_mhdp_mailbox_recv_data(mhdp, link_status, + DP_LINK_STATUS_SIZE); + +out: + mutex_unlock(&mhdp->mbox_mutex); + + if (ret) + dev_err(mhdp->dev, "Failed to adjust Link Training.\n"); + + return ret; +} + +/** + * cdns_mhdp_link_power_up() - power up a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +static +int cdns_mhdp_link_power_up(struct drm_dp_aux *aux, struct cdns_mhdp_link *link) +{ + u8 value; + int err; + + /* DP_SET_POWER register is only available on DPCD v1.1 and later */ + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + /* + * According to the DP 1.1 specification, a "Sink Device must exit the + * power saving state within 1 ms" (Section 2.5.3.1, Table 5-52, "Sink + * Control Field" (register 0x600). + */ + usleep_range(1000, 2000); + + return 0; +} + +/** + * cdns_mhdp_link_power_down() - power down a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +static +int cdns_mhdp_link_power_down(struct drm_dp_aux *aux, + struct cdns_mhdp_link *link) +{ + u8 value; + int err; + + /* DP_SET_POWER register is only available on DPCD v1.1 and later */ + if (link->revision < 0x11) + return 0; + + err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); + if (err < 0) + return err; + + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D3; + + err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); + if (err < 0) + return err; + + return 0; +} + +/** + * cdns_mhdp_link_configure() - configure a DisplayPort link + * @aux: DisplayPort AUX channel + * @link: pointer to a structure containing the link configuration + * + * Returns 0 on success or a negative error code on failure. + */ +static +int cdns_mhdp_link_configure(struct drm_dp_aux *aux, + struct cdns_mhdp_link *link) +{ + u8 values[2]; + int err; + + values[0] = drm_dp_link_rate_to_bw_code(link->rate); + values[1] = link->num_lanes; + + if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) + values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); + if (err < 0) + return err; + + return 0; +} + +static unsigned int cdns_mhdp_max_link_rate(struct cdns_mhdp_device *mhdp) +{ + return min(mhdp->host.link_rate, mhdp->sink.link_rate); +} + +static u8 cdns_mhdp_max_num_lanes(struct cdns_mhdp_device *mhdp) +{ + return min(mhdp->sink.lanes_cnt, mhdp->host.lanes_cnt); +} + +static u8 cdns_mhdp_eq_training_pattern_supported(struct cdns_mhdp_device *mhdp) +{ + return fls(mhdp->host.pattern_supp & mhdp->sink.pattern_supp); +} + +static bool cdns_mhdp_get_ssc_supported(struct cdns_mhdp_device *mhdp) +{ + /* Check if SSC is supported by both sides */ + return mhdp->host.ssc && mhdp->sink.ssc; +} + +static enum drm_connector_status cdns_mhdp_detect(struct cdns_mhdp_device *mhdp) +{ + dev_dbg(mhdp->dev, "%s: %d\n", __func__, mhdp->plugged); + + if (mhdp->plugged) + return connector_status_connected; + else + return connector_status_disconnected; +} + +static int cdns_mhdp_check_fw_version(struct cdns_mhdp_device *mhdp) +{ + u32 major_num, minor_num, revision; + u32 fw_ver, lib_ver; + + fw_ver = (readl(mhdp->regs + CDNS_VER_H) << 8) + | readl(mhdp->regs + CDNS_VER_L); + + lib_ver = (readl(mhdp->regs + CDNS_LIB_H_ADDR) << 8) + | readl(mhdp->regs + CDNS_LIB_L_ADDR); + + if (lib_ver < 33984) { + /* + * Older FW versions with major number 1, used to store FW + * version information by storing repository revision number + * in registers. This is for identifying these FW versions. + */ + major_num = 1; + minor_num = 2; + if (fw_ver == 26098) { + revision = 15; + } else if (lib_ver == 0 && fw_ver == 0) { + revision = 17; + } else { + dev_err(mhdp->dev, "Unsupported FW version: fw_ver = %u, lib_ver = %u\n", + fw_ver, lib_ver); + return -ENODEV; + } + } else { + /* To identify newer FW versions with major number 2 onwards. */ + major_num = fw_ver / 10000; + minor_num = (fw_ver / 100) % 100; + revision = (fw_ver % 10000) % 100; + } + + dev_dbg(mhdp->dev, "FW version: v%u.%u.%u\n", major_num, minor_num, + revision); + return 0; +} + +static int cdns_mhdp_fw_activate(const struct firmware *fw, + struct cdns_mhdp_device *mhdp) +{ + unsigned int reg; + int ret; + + /* Release uCPU reset and stall it. */ + writel(CDNS_CPU_STALL, mhdp->regs + CDNS_APB_CTRL); + + memcpy_toio(mhdp->regs + CDNS_MHDP_IMEM, fw->data, fw->size); + + /* Leave debug mode, release stall */ + writel(0, mhdp->regs + CDNS_APB_CTRL); + + /* + * Wait for the KEEP_ALIVE "message" on the first 8 bits. + * Updated each sched "tick" (~2ms) + */ + ret = readl_poll_timeout(mhdp->regs + CDNS_KEEP_ALIVE, reg, + reg & CDNS_KEEP_ALIVE_MASK, 500, + CDNS_KEEP_ALIVE_TIMEOUT); + if (ret) { + dev_err(mhdp->dev, + "device didn't give any life sign: reg %d\n", reg); + return ret; + } + + ret = cdns_mhdp_check_fw_version(mhdp); + if (ret) + return ret; + + /* Init events to 0 as it's not cleared by FW at boot but on read */ + readl(mhdp->regs + CDNS_SW_EVENT0); + readl(mhdp->regs + CDNS_SW_EVENT1); + readl(mhdp->regs + CDNS_SW_EVENT2); + readl(mhdp->regs + CDNS_SW_EVENT3); + + /* Activate uCPU */ + ret = cdns_mhdp_set_firmware_active(mhdp, true); + if (ret) + return ret; + + spin_lock(&mhdp->start_lock); + + mhdp->hw_state = MHDP_HW_READY; + + /* + * Here we must keep the lock while enabling the interrupts + * since it would otherwise be possible that interrupt enable + * code is executed after the bridge is detached. The similar + * situation is not possible in attach()/detach() callbacks + * since the hw_state changes from MHDP_HW_READY to + * MHDP_HW_STOPPED happens only due to driver removal when + * bridge should already be detached. + */ + if (mhdp->bridge_attached) + writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + mhdp->regs + CDNS_APB_INT_MASK); + + spin_unlock(&mhdp->start_lock); + + wake_up(&mhdp->fw_load_wq); + dev_dbg(mhdp->dev, "DP FW activated\n"); + + return 0; +} + +static void cdns_mhdp_fw_cb(const struct firmware *fw, void *context) +{ + struct cdns_mhdp_device *mhdp = context; + bool bridge_attached; + int ret; + + dev_dbg(mhdp->dev, "firmware callback\n"); + + if (!fw || !fw->data) { + dev_err(mhdp->dev, "%s: No firmware.\n", __func__); + return; + } + + ret = cdns_mhdp_fw_activate(fw, mhdp); + + release_firmware(fw); + + if (ret) + return; + + /* + * XXX how to make sure the bridge is still attached when + * calling drm_kms_helper_hotplug_event() after releasing + * the lock? We should not hold the spin lock when + * calling drm_kms_helper_hotplug_event() since it may + * cause a dead lock. FB-dev console calls detect from the + * same thread just down the call stack started here. + */ + spin_lock(&mhdp->start_lock); + bridge_attached = mhdp->bridge_attached; + spin_unlock(&mhdp->start_lock); + if (bridge_attached) { + if (mhdp->connector.dev) + drm_kms_helper_hotplug_event(mhdp->bridge.dev); + else + drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); + } +} + +static int cdns_mhdp_load_firmware(struct cdns_mhdp_device *mhdp) +{ + int ret; + + ret = request_firmware_nowait(THIS_MODULE, true, FW_NAME, mhdp->dev, + GFP_KERNEL, mhdp, cdns_mhdp_fw_cb); + if (ret) { + dev_err(mhdp->dev, "failed to load firmware (%s), ret: %d\n", + FW_NAME, ret); + return ret; + } + + return 0; +} + +static ssize_t cdns_mhdp_transfer(struct drm_dp_aux *aux, + struct drm_dp_aux_msg *msg) +{ + struct cdns_mhdp_device *mhdp = dev_get_drvdata(aux->dev); + int ret; + + if (msg->request != DP_AUX_NATIVE_WRITE && + msg->request != DP_AUX_NATIVE_READ) + return -EOPNOTSUPP; + + if (msg->request == DP_AUX_NATIVE_WRITE) { + const u8 *buf = msg->buffer; + unsigned int i; + + for (i = 0; i < msg->size; ++i) { + ret = cdns_mhdp_dpcd_write(mhdp, + msg->address + i, buf[i]); + if (!ret) + continue; + + dev_err(mhdp->dev, + "Failed to write DPCD addr %u\n", + msg->address + i); + + return ret; + } + } else { + ret = cdns_mhdp_dpcd_read(mhdp, msg->address, + msg->buffer, msg->size); + if (ret) { + dev_err(mhdp->dev, + "Failed to read DPCD addr %u\n", + msg->address); + + return ret; + } + } + + return msg->size; +} + +static int cdns_mhdp_link_training_init(struct cdns_mhdp_device *mhdp) +{ + union phy_configure_opts phy_cfg; + u32 reg32; + int ret; + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + /* Reset PHY configuration */ + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1); + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; + + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_ENHNCD, + mhdp->sink.enhanced & mhdp->host.enhanced); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_LANE_EN, + CDNS_DP_LANE_EN_LANES(mhdp->link.num_lanes)); + + cdns_mhdp_link_configure(&mhdp->aux, &mhdp->link); + phy_cfg.dp.link_rate = mhdp->link.rate / 100; + phy_cfg.dp.lanes = mhdp->link.num_lanes; + + memset(phy_cfg.dp.voltage, 0, sizeof(phy_cfg.dp.voltage)); + memset(phy_cfg.dp.pre, 0, sizeof(phy_cfg.dp.pre)); + + phy_cfg.dp.ssc = cdns_mhdp_get_ssc_supported(mhdp); + phy_cfg.dp.set_lanes = true; + phy_cfg.dp.set_rate = true; + phy_cfg.dp.set_voltages = true; + ret = phy_configure(mhdp->phy, &phy_cfg); + if (ret) { + dev_err(mhdp->dev, "%s: phy_configure() failed: %d\n", + __func__, ret); + return ret; + } + + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, + CDNS_PHY_COMMON_CONFIG | + CDNS_PHY_TRAINING_EN | + CDNS_PHY_TRAINING_TYPE(1) | + CDNS_PHY_SCRAMBLER_BYPASS); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE); + + return 0; +} + +static void cdns_mhdp_get_adjust_train(struct cdns_mhdp_device *mhdp, + u8 link_status[DP_LINK_STATUS_SIZE], + u8 lanes_data[CDNS_DP_MAX_NUM_LANES], + union phy_configure_opts *phy_cfg) +{ + u8 adjust, max_pre_emph, max_volt_swing; + u8 set_volt, set_pre; + unsigned int i; + + max_pre_emph = CDNS_PRE_EMPHASIS(mhdp->host.pre_emphasis) + << DP_TRAIN_PRE_EMPHASIS_SHIFT; + max_volt_swing = CDNS_VOLT_SWING(mhdp->host.volt_swing); + + for (i = 0; i < mhdp->link.num_lanes; i++) { + /* Check if Voltage swing and pre-emphasis are within limits */ + adjust = drm_dp_get_adjust_request_voltage(link_status, i); + set_volt = min(adjust, max_volt_swing); + + adjust = drm_dp_get_adjust_request_pre_emphasis(link_status, i); + set_pre = min(adjust, max_pre_emph) + >> DP_TRAIN_PRE_EMPHASIS_SHIFT; + + /* + * Voltage swing level and pre-emphasis level combination is + * not allowed: leaving pre-emphasis as-is, and adjusting + * voltage swing. + */ + if (set_volt + set_pre > 3) + set_volt = 3 - set_pre; + + phy_cfg->dp.voltage[i] = set_volt; + lanes_data[i] = set_volt; + + if (set_volt == max_volt_swing) + lanes_data[i] |= DP_TRAIN_MAX_SWING_REACHED; + + phy_cfg->dp.pre[i] = set_pre; + lanes_data[i] |= (set_pre << DP_TRAIN_PRE_EMPHASIS_SHIFT); + + if (set_pre == (max_pre_emph >> DP_TRAIN_PRE_EMPHASIS_SHIFT)) + lanes_data[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + } +} + +static +void cdns_mhdp_set_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], + unsigned int lane, u8 volt) +{ + unsigned int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + unsigned int idx = DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS + (lane >> 1); + + link_status[idx] &= ~(DP_ADJUST_VOLTAGE_SWING_LANE0_MASK << s); + link_status[idx] |= volt << s; +} + +static +void cdns_mhdp_set_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], + unsigned int lane, u8 pre_emphasis) +{ + unsigned int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + unsigned int idx = DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS + (lane >> 1); + + link_status[idx] &= ~(DP_ADJUST_PRE_EMPHASIS_LANE0_MASK << s); + link_status[idx] |= pre_emphasis << s; +} + +static void cdns_mhdp_adjust_requested_eq(struct cdns_mhdp_device *mhdp, + u8 link_status[DP_LINK_STATUS_SIZE]) +{ + u8 max_pre = CDNS_PRE_EMPHASIS(mhdp->host.pre_emphasis); + u8 max_volt = CDNS_VOLT_SWING(mhdp->host.volt_swing); + unsigned int i; + u8 volt, pre; + + for (i = 0; i < mhdp->link.num_lanes; i++) { + volt = drm_dp_get_adjust_request_voltage(link_status, i); + pre = drm_dp_get_adjust_request_pre_emphasis(link_status, i); + if (volt + pre > 3) + cdns_mhdp_set_adjust_request_voltage(link_status, i, + 3 - pre); + if (mhdp->host.volt_swing & CDNS_FORCE_VOLT_SWING) + cdns_mhdp_set_adjust_request_voltage(link_status, i, + max_volt); + if (mhdp->host.pre_emphasis & CDNS_FORCE_PRE_EMPHASIS) + cdns_mhdp_set_adjust_request_pre_emphasis(link_status, + i, max_pre); + } +} + +static void cdns_mhdp_print_lt_status(const char *prefix, + struct cdns_mhdp_device *mhdp, + union phy_configure_opts *phy_cfg) +{ + char vs[8] = "0/0/0/0"; + char pe[8] = "0/0/0/0"; + unsigned int i; + + for (i = 0; i < mhdp->link.num_lanes; i++) { + vs[i * 2] = '0' + phy_cfg->dp.voltage[i]; + pe[i * 2] = '0' + phy_cfg->dp.pre[i]; + } + + vs[i * 2 - 1] = '\0'; + pe[i * 2 - 1] = '\0'; + + dev_dbg(mhdp->dev, "%s, %u lanes, %u Mbps, vs %s, pe %s\n", + prefix, + mhdp->link.num_lanes, mhdp->link.rate / 100, + vs, pe); +} + +static bool cdns_mhdp_link_training_channel_eq(struct cdns_mhdp_device *mhdp, + u8 eq_tps, + unsigned int training_interval) +{ + u8 lanes_data[CDNS_DP_MAX_NUM_LANES], fail_counter_short = 0; + u8 link_status[DP_LINK_STATUS_SIZE]; + union phy_configure_opts phy_cfg; + u32 reg32; + int ret; + bool r; + + dev_dbg(mhdp->dev, "Starting EQ phase\n"); + + /* Enable link training TPS[eq_tps] in PHY */ + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_EN | + CDNS_PHY_TRAINING_TYPE(eq_tps); + if (eq_tps != 4) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + (eq_tps != 4) ? eq_tps | DP_LINK_SCRAMBLING_DISABLE : + CDNS_DP_TRAINING_PATTERN_4); + + drm_dp_dpcd_read_link_status(&mhdp->aux, link_status); + + do { + cdns_mhdp_get_adjust_train(mhdp, link_status, lanes_data, + &phy_cfg); + phy_cfg.dp.lanes = mhdp->link.num_lanes; + phy_cfg.dp.ssc = cdns_mhdp_get_ssc_supported(mhdp); + phy_cfg.dp.set_lanes = false; + phy_cfg.dp.set_rate = false; + phy_cfg.dp.set_voltages = true; + ret = phy_configure(mhdp->phy, &phy_cfg); + if (ret) { + dev_err(mhdp->dev, "%s: phy_configure() failed: %d\n", + __func__, ret); + goto err; + } + + cdns_mhdp_adjust_lt(mhdp, mhdp->link.num_lanes, + training_interval, lanes_data, link_status); + + r = drm_dp_clock_recovery_ok(link_status, mhdp->link.num_lanes); + if (!r) + goto err; + + if (drm_dp_channel_eq_ok(link_status, mhdp->link.num_lanes)) { + cdns_mhdp_print_lt_status("EQ phase ok", mhdp, + &phy_cfg); + return true; + } + + fail_counter_short++; + + cdns_mhdp_adjust_requested_eq(mhdp, link_status); + } while (fail_counter_short < 5); + +err: + cdns_mhdp_print_lt_status("EQ phase failed", mhdp, &phy_cfg); + + return false; +} + +static void cdns_mhdp_adjust_requested_cr(struct cdns_mhdp_device *mhdp, + u8 link_status[DP_LINK_STATUS_SIZE], + u8 *req_volt, u8 *req_pre) +{ + const u8 max_volt = CDNS_VOLT_SWING(mhdp->host.volt_swing); + const u8 max_pre = CDNS_PRE_EMPHASIS(mhdp->host.pre_emphasis); + unsigned int i; + + for (i = 0; i < mhdp->link.num_lanes; i++) { + u8 val; + + val = mhdp->host.volt_swing & CDNS_FORCE_VOLT_SWING ? + max_volt : req_volt[i]; + cdns_mhdp_set_adjust_request_voltage(link_status, i, val); + + val = mhdp->host.pre_emphasis & CDNS_FORCE_PRE_EMPHASIS ? + max_pre : req_pre[i]; + cdns_mhdp_set_adjust_request_pre_emphasis(link_status, i, val); + } +} + +static +void cdns_mhdp_validate_cr(struct cdns_mhdp_device *mhdp, bool *cr_done, + bool *same_before_adjust, bool *max_swing_reached, + u8 before_cr[CDNS_DP_MAX_NUM_LANES], + u8 after_cr[DP_LINK_STATUS_SIZE], u8 *req_volt, + u8 *req_pre) +{ + const u8 max_volt = CDNS_VOLT_SWING(mhdp->host.volt_swing); + const u8 max_pre = CDNS_PRE_EMPHASIS(mhdp->host.pre_emphasis); + bool same_pre, same_volt; + unsigned int i; + u8 adjust; + + *same_before_adjust = false; + *max_swing_reached = false; + *cr_done = drm_dp_clock_recovery_ok(after_cr, mhdp->link.num_lanes); + + for (i = 0; i < mhdp->link.num_lanes; i++) { + adjust = drm_dp_get_adjust_request_voltage(after_cr, i); + req_volt[i] = min(adjust, max_volt); + + adjust = drm_dp_get_adjust_request_pre_emphasis(after_cr, i) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT; + req_pre[i] = min(adjust, max_pre); + + same_pre = (before_cr[i] & DP_TRAIN_PRE_EMPHASIS_MASK) == + req_pre[i] << DP_TRAIN_PRE_EMPHASIS_SHIFT; + same_volt = (before_cr[i] & DP_TRAIN_VOLTAGE_SWING_MASK) == + req_volt[i]; + if (same_pre && same_volt) + *same_before_adjust = true; + + /* 3.1.5.2 in DP Standard v1.4. Table 3-1 */ + if (!*cr_done && req_volt[i] + req_pre[i] >= 3) { + *max_swing_reached = true; + return; + } + } +} + +static bool cdns_mhdp_link_training_cr(struct cdns_mhdp_device *mhdp) +{ + u8 lanes_data[CDNS_DP_MAX_NUM_LANES], + fail_counter_short = 0, fail_counter_cr_long = 0; + u8 link_status[DP_LINK_STATUS_SIZE]; + bool cr_done; + union phy_configure_opts phy_cfg; + int ret; + + dev_dbg(mhdp->dev, "Starting CR phase\n"); + + ret = cdns_mhdp_link_training_init(mhdp); + if (ret) + goto err; + + drm_dp_dpcd_read_link_status(&mhdp->aux, link_status); + + do { + u8 requested_adjust_volt_swing[CDNS_DP_MAX_NUM_LANES] = {}; + u8 requested_adjust_pre_emphasis[CDNS_DP_MAX_NUM_LANES] = {}; + bool same_before_adjust, max_swing_reached; + + cdns_mhdp_get_adjust_train(mhdp, link_status, lanes_data, + &phy_cfg); + phy_cfg.dp.lanes = mhdp->link.num_lanes; + phy_cfg.dp.ssc = cdns_mhdp_get_ssc_supported(mhdp); + phy_cfg.dp.set_lanes = false; + phy_cfg.dp.set_rate = false; + phy_cfg.dp.set_voltages = true; + ret = phy_configure(mhdp->phy, &phy_cfg); + if (ret) { + dev_err(mhdp->dev, "%s: phy_configure() failed: %d\n", + __func__, ret); + goto err; + } + + cdns_mhdp_adjust_lt(mhdp, mhdp->link.num_lanes, 100, + lanes_data, link_status); + + cdns_mhdp_validate_cr(mhdp, &cr_done, &same_before_adjust, + &max_swing_reached, lanes_data, + link_status, + requested_adjust_volt_swing, + requested_adjust_pre_emphasis); + + if (max_swing_reached) { + dev_err(mhdp->dev, "CR: max swing reached\n"); + goto err; + } + + if (cr_done) { + cdns_mhdp_print_lt_status("CR phase ok", mhdp, + &phy_cfg); + return true; + } + + /* Not all CR_DONE bits set */ + fail_counter_cr_long++; + + if (same_before_adjust) { + fail_counter_short++; + continue; + } + + fail_counter_short = 0; + /* + * Voltage swing/pre-emphasis adjust requested + * during CR phase + */ + cdns_mhdp_adjust_requested_cr(mhdp, link_status, + requested_adjust_volt_swing, + requested_adjust_pre_emphasis); + } while (fail_counter_short < 5 && fail_counter_cr_long < 10); + +err: + cdns_mhdp_print_lt_status("CR phase failed", mhdp, &phy_cfg); + + return false; +} + +static void cdns_mhdp_lower_link_rate(struct cdns_mhdp_link *link) +{ + switch (drm_dp_link_rate_to_bw_code(link->rate)) { + case DP_LINK_BW_2_7: + link->rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_1_62); + break; + case DP_LINK_BW_5_4: + link->rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_2_7); + break; + case DP_LINK_BW_8_1: + link->rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_5_4); + break; + } +} + +static int cdns_mhdp_link_training(struct cdns_mhdp_device *mhdp, + unsigned int training_interval) +{ + u32 reg32; + const u8 eq_tps = cdns_mhdp_eq_training_pattern_supported(mhdp); + int ret; + + while (1) { + if (!cdns_mhdp_link_training_cr(mhdp)) { + if (drm_dp_link_rate_to_bw_code(mhdp->link.rate) != + DP_LINK_BW_1_62) { + dev_dbg(mhdp->dev, + "Reducing link rate during CR phase\n"); + cdns_mhdp_lower_link_rate(&mhdp->link); + + continue; + } else if (mhdp->link.num_lanes > 1) { + dev_dbg(mhdp->dev, + "Reducing lanes number during CR phase\n"); + mhdp->link.num_lanes >>= 1; + mhdp->link.rate = cdns_mhdp_max_link_rate(mhdp); + + continue; + } + + dev_err(mhdp->dev, + "Link training failed during CR phase\n"); + goto err; + } + + if (cdns_mhdp_link_training_channel_eq(mhdp, eq_tps, + training_interval)) + break; + + if (mhdp->link.num_lanes > 1) { + dev_dbg(mhdp->dev, + "Reducing lanes number during EQ phase\n"); + mhdp->link.num_lanes >>= 1; + + continue; + } else if (drm_dp_link_rate_to_bw_code(mhdp->link.rate) != + DP_LINK_BW_1_62) { + dev_dbg(mhdp->dev, + "Reducing link rate during EQ phase\n"); + cdns_mhdp_lower_link_rate(&mhdp->link); + mhdp->link.num_lanes = cdns_mhdp_max_num_lanes(mhdp); + + continue; + } + + dev_err(mhdp->dev, "Link training failed during EQ phase\n"); + goto err; + } + + dev_dbg(mhdp->dev, "Link training ok. Lanes: %u, Rate %u Mbps\n", + mhdp->link.num_lanes, mhdp->link.rate / 100); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + mhdp->host.scrambler ? 0 : + DP_LINK_SCRAMBLING_DISABLE); + + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, ®32); + if (ret < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", + ret); + return ret; + } + reg32 &= ~GENMASK(1, 0); + reg32 |= CDNS_DP_NUM_LANES(mhdp->link.num_lanes); + reg32 |= CDNS_DP_WR_FAILING_EDGE_VSYNC; + reg32 |= CDNS_DP_FRAMER_EN; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, reg32); + + /* Reset PHY config */ + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1); + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); + + return 0; +err: + /* Reset PHY config */ + reg32 = CDNS_PHY_COMMON_CONFIG | CDNS_PHY_TRAINING_TYPE(1); + if (!mhdp->host.scrambler) + reg32 |= CDNS_PHY_SCRAMBLER_BYPASS; + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_PHY_CONFIG, reg32); + + drm_dp_dpcd_writeb(&mhdp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); + + return -EIO; +} + +static u32 cdns_mhdp_get_training_interval_us(struct cdns_mhdp_device *mhdp, + u32 interval) +{ + if (interval == 0) + return 400; + if (interval < 5) + return 4000 << (interval - 1); + dev_err(mhdp->dev, + "wrong training interval returned by DPCD: %d\n", interval); + return 0; +} + +static void cdns_mhdp_fill_host_caps(struct cdns_mhdp_device *mhdp) +{ + unsigned int link_rate; + + /* Get source capabilities based on PHY attributes */ + + mhdp->host.lanes_cnt = mhdp->phy->attrs.bus_width; + if (!mhdp->host.lanes_cnt) + mhdp->host.lanes_cnt = 4; + + link_rate = mhdp->phy->attrs.max_link_rate; + if (!link_rate) + link_rate = drm_dp_bw_code_to_link_rate(DP_LINK_BW_8_1); + else + /* PHY uses Mb/s, DRM uses tens of kb/s. */ + link_rate *= 100; + + mhdp->host.link_rate = link_rate; + mhdp->host.volt_swing = CDNS_VOLT_SWING(3); + mhdp->host.pre_emphasis = CDNS_PRE_EMPHASIS(3); + mhdp->host.pattern_supp = CDNS_SUPPORT_TPS(1) | + CDNS_SUPPORT_TPS(2) | CDNS_SUPPORT_TPS(3) | + CDNS_SUPPORT_TPS(4); + mhdp->host.lane_mapping = CDNS_LANE_MAPPING_NORMAL; + mhdp->host.fast_link = false; + mhdp->host.enhanced = true; + mhdp->host.scrambler = true; + mhdp->host.ssc = false; +} + +static void cdns_mhdp_fill_sink_caps(struct cdns_mhdp_device *mhdp, + u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + mhdp->sink.link_rate = mhdp->link.rate; + mhdp->sink.lanes_cnt = mhdp->link.num_lanes; + mhdp->sink.enhanced = !!(mhdp->link.capabilities & + DP_LINK_CAP_ENHANCED_FRAMING); + + /* Set SSC support */ + mhdp->sink.ssc = !!(dpcd[DP_MAX_DOWNSPREAD] & + DP_MAX_DOWNSPREAD_0_5); + + /* Set TPS support */ + mhdp->sink.pattern_supp = CDNS_SUPPORT_TPS(1) | CDNS_SUPPORT_TPS(2); + if (drm_dp_tps3_supported(dpcd)) + mhdp->sink.pattern_supp |= CDNS_SUPPORT_TPS(3); + if (drm_dp_tps4_supported(dpcd)) + mhdp->sink.pattern_supp |= CDNS_SUPPORT_TPS(4); + + /* Set fast link support */ + mhdp->sink.fast_link = !!(dpcd[DP_MAX_DOWNSPREAD] & + DP_NO_AUX_HANDSHAKE_LINK_TRAINING); +} + +static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp) +{ + u8 dpcd[DP_RECEIVER_CAP_SIZE], amp[2]; + u32 resp, interval, interval_us; + u8 ext_cap_chk = 0; + unsigned int addr; + int err; + + WARN_ON(!mutex_is_locked(&mhdp->link_mutex)); + + drm_dp_dpcd_readb(&mhdp->aux, DP_TRAINING_AUX_RD_INTERVAL, + &ext_cap_chk); + + if (ext_cap_chk & DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT) + addr = DP_DP13_DPCD_REV; + else + addr = DP_DPCD_REV; + + err = drm_dp_dpcd_read(&mhdp->aux, addr, dpcd, DP_RECEIVER_CAP_SIZE); + if (err < 0) { + dev_err(mhdp->dev, "Failed to read receiver capabilities\n"); + return err; + } + + mhdp->link.revision = dpcd[0]; + mhdp->link.rate = drm_dp_bw_code_to_link_rate(dpcd[1]); + mhdp->link.num_lanes = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + + if (dpcd[2] & DP_ENHANCED_FRAME_CAP) + mhdp->link.capabilities |= DP_LINK_CAP_ENHANCED_FRAMING; + + dev_dbg(mhdp->dev, "Set sink device power state via DPCD\n"); + cdns_mhdp_link_power_up(&mhdp->aux, &mhdp->link); + + cdns_mhdp_fill_sink_caps(mhdp, dpcd); + + mhdp->link.rate = cdns_mhdp_max_link_rate(mhdp); + mhdp->link.num_lanes = cdns_mhdp_max_num_lanes(mhdp); + + /* Disable framer for link training */ + err = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); + if (err < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", + err); + return err; + } + + resp &= ~CDNS_DP_FRAMER_EN; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); + + /* Spread AMP if required, enable 8b/10b coding */ + amp[0] = cdns_mhdp_get_ssc_supported(mhdp) ? DP_SPREAD_AMP_0_5 : 0; + amp[1] = DP_SET_ANSI_8B10B; + drm_dp_dpcd_write(&mhdp->aux, DP_DOWNSPREAD_CTRL, amp, 2); + + if (mhdp->host.fast_link & mhdp->sink.fast_link) { + dev_err(mhdp->dev, "fastlink not supported\n"); + return -EOPNOTSUPP; + } + + interval = dpcd[DP_TRAINING_AUX_RD_INTERVAL] & DP_TRAINING_AUX_RD_MASK; + interval_us = cdns_mhdp_get_training_interval_us(mhdp, interval); + if (!interval_us || + cdns_mhdp_link_training(mhdp, interval_us)) { + dev_err(mhdp->dev, "Link training failed. Exiting.\n"); + return -EIO; + } + + mhdp->link_up = true; + + return 0; +} + +static void cdns_mhdp_link_down(struct cdns_mhdp_device *mhdp) +{ + WARN_ON(!mutex_is_locked(&mhdp->link_mutex)); + + if (mhdp->plugged) + cdns_mhdp_link_power_down(&mhdp->aux, &mhdp->link); + + mhdp->link_up = false; +} + +static struct edid *cdns_mhdp_get_edid(struct cdns_mhdp_device *mhdp, + struct drm_connector *connector) +{ + if (!mhdp->plugged) + return NULL; + + return drm_do_get_edid(connector, cdns_mhdp_get_edid_block, mhdp); +} + +static int cdns_mhdp_get_modes(struct drm_connector *connector) +{ + struct cdns_mhdp_device *mhdp = connector_to_mhdp(connector); + struct edid *edid; + int num_modes; + + if (!mhdp->plugged) + return 0; + + edid = cdns_mhdp_get_edid(mhdp, connector); + if (!edid) { + dev_err(mhdp->dev, "Failed to read EDID\n"); + return 0; + } + + drm_connector_update_edid_property(connector, edid); + num_modes = drm_add_edid_modes(connector, edid); + kfree(edid); + + /* + * HACK: Warn about unsupported display formats until we deal + * with them correctly. + */ + if (connector->display_info.color_formats && + !(connector->display_info.color_formats & + mhdp->display_fmt.color_format)) + dev_warn(mhdp->dev, + "%s: No supported color_format found (0x%08x)\n", + __func__, connector->display_info.color_formats); + + if (connector->display_info.bpc && + connector->display_info.bpc < mhdp->display_fmt.bpc) + dev_warn(mhdp->dev, "%s: Display bpc only %d < %d\n", + __func__, connector->display_info.bpc, + mhdp->display_fmt.bpc); + + return num_modes; +} + +static int cdns_mhdp_connector_detect(struct drm_connector *conn, + struct drm_modeset_acquire_ctx *ctx, + bool force) +{ + struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); + + return cdns_mhdp_detect(mhdp); +} + +static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt) +{ + u32 bpp; + + if (fmt->y_only) + return fmt->bpc; + + switch (fmt->color_format) { + case DRM_COLOR_FORMAT_RGB444: + case DRM_COLOR_FORMAT_YCRCB444: + bpp = fmt->bpc * 3; + break; + case DRM_COLOR_FORMAT_YCRCB422: + bpp = fmt->bpc * 2; + break; + case DRM_COLOR_FORMAT_YCRCB420: + bpp = fmt->bpc * 3 / 2; + break; + default: + bpp = fmt->bpc * 3; + WARN_ON(1); + } + return bpp; +} + +static +bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp, + const struct drm_display_mode *mode, + unsigned int lanes, unsigned int rate) +{ + u32 max_bw, req_bw, bpp; + + /* + * mode->clock is expressed in kHz. Multiplying by bpp and dividing by 8 + * we get the number of kB/s. DisplayPort applies a 8b-10b encoding, the + * value thus equals the bandwidth in 10kb/s units, which matches the + * units of the rate parameter. + */ + + bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt); + req_bw = mode->clock * bpp / 8; + max_bw = lanes * rate; + if (req_bw > max_bw) { + dev_dbg(mhdp->dev, + "Unsupported Mode: %s, Req BW: %u, Available Max BW:%u\n", + mode->name, req_bw, max_bw); + + return false; + } + + return true; +} + +static +enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn, + struct drm_display_mode *mode) +{ + struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); + + mutex_lock(&mhdp->link_mutex); + + if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes, + mhdp->link.rate)) { + mutex_unlock(&mhdp->link_mutex); + return MODE_CLOCK_HIGH; + } + + mutex_unlock(&mhdp->link_mutex); + return MODE_OK; +} + +static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = { + .detect_ctx = cdns_mhdp_connector_detect, + .get_modes = cdns_mhdp_get_modes, + .mode_valid = cdns_mhdp_mode_valid, +}; + +static const struct drm_connector_funcs cdns_mhdp_conn_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .reset = drm_atomic_helper_connector_reset, + .destroy = drm_connector_cleanup, +}; + +static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp) +{ + u32 bus_format = MEDIA_BUS_FMT_RGB121212_1X36; + struct drm_connector *conn = &mhdp->connector; + struct drm_bridge *bridge = &mhdp->bridge; + int ret; + + if (!bridge->encoder) { + dev_err(mhdp->dev, "Parent encoder object not found"); + return -ENODEV; + } + + conn->polled = DRM_CONNECTOR_POLL_HPD; + + ret = drm_connector_init(bridge->dev, conn, &cdns_mhdp_conn_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) { + dev_err(mhdp->dev, "Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(conn, &cdns_mhdp_conn_helper_funcs); + + ret = drm_display_info_set_bus_formats(&conn->display_info, + &bus_format, 1); + if (ret) + return ret; + + ret = drm_connector_attach_encoder(conn, bridge->encoder); + if (ret) { + dev_err(mhdp->dev, "Failed to attach connector to encoder\n"); + return ret; + } + + return 0; +} + +static int cdns_mhdp_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + bool hw_ready; + int ret; + + dev_dbg(mhdp->dev, "%s\n", __func__); + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { + ret = cdns_mhdp_connector_init(mhdp); + if (ret) + return ret; + } + + spin_lock(&mhdp->start_lock); + + mhdp->bridge_attached = true; + hw_ready = mhdp->hw_state == MHDP_HW_READY; + + spin_unlock(&mhdp->start_lock); + + /* Enable SW event interrupts */ + if (hw_ready) + writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + mhdp->regs + CDNS_APB_INT_MASK); + + return 0; +} + +static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp, + const struct drm_display_mode *mode) +{ + unsigned int dp_framer_sp = 0, msa_horizontal_1, + msa_vertical_1, bnd_hsync2vsync, hsync2vsync_pol_ctrl, + misc0 = 0, misc1 = 0, pxl_repr, + front_porch, back_porch, msa_h0, msa_v0, hsync, vsync, + dp_vertical_1; + u8 stream_id = mhdp->stream_id; + u32 bpp, bpc, pxlfmt, framer; + int ret; + + pxlfmt = mhdp->display_fmt.color_format; + bpc = mhdp->display_fmt.bpc; + + /* + * If YCBCR supported and stream not SD, use ITU709 + * Need to handle ITU version with YCBCR420 when supported + */ + if ((pxlfmt == DRM_COLOR_FORMAT_YCRCB444 || + pxlfmt == DRM_COLOR_FORMAT_YCRCB422) && mode->crtc_vdisplay >= 720) + misc0 = DP_YCBCR_COEFFICIENTS_ITU709; + + bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt); + + switch (pxlfmt) { + case DRM_COLOR_FORMAT_RGB444: + pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT; + misc0 |= DP_COLOR_FORMAT_RGB; + break; + case DRM_COLOR_FORMAT_YCRCB444: + pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT; + misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA; + break; + case DRM_COLOR_FORMAT_YCRCB422: + pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT; + misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA; + break; + case DRM_COLOR_FORMAT_YCRCB420: + pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT; + break; + default: + pxl_repr = CDNS_DP_FRAMER_Y_ONLY << CDNS_DP_FRAMER_PXL_FORMAT; + } + + switch (bpc) { + case 6: + misc0 |= DP_TEST_BIT_DEPTH_6; + pxl_repr |= CDNS_DP_FRAMER_6_BPC; + break; + case 8: + misc0 |= DP_TEST_BIT_DEPTH_8; + pxl_repr |= CDNS_DP_FRAMER_8_BPC; + break; + case 10: + misc0 |= DP_TEST_BIT_DEPTH_10; + pxl_repr |= CDNS_DP_FRAMER_10_BPC; + break; + case 12: + misc0 |= DP_TEST_BIT_DEPTH_12; + pxl_repr |= CDNS_DP_FRAMER_12_BPC; + break; + case 16: + misc0 |= DP_TEST_BIT_DEPTH_16; + pxl_repr |= CDNS_DP_FRAMER_16_BPC; + break; + } + + bnd_hsync2vsync = CDNS_IP_BYPASS_V_INTERFACE; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT; + + cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id), + bnd_hsync2vsync); + + hsync2vsync_pol_ctrl = 0; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + hsync2vsync_pol_ctrl |= CDNS_H2V_HSYNC_POL_ACTIVE_LOW; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + hsync2vsync_pol_ctrl |= CDNS_H2V_VSYNC_POL_ACTIVE_LOW; + cdns_mhdp_reg_write(mhdp, CDNS_HSYNC2VSYNC_POL_CTRL(stream_id), + hsync2vsync_pol_ctrl); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(stream_id), pxl_repr); + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + dp_framer_sp |= CDNS_DP_FRAMER_INTERLACE; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + dp_framer_sp |= CDNS_DP_FRAMER_HSYNC_POL_LOW; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + dp_framer_sp |= CDNS_DP_FRAMER_VSYNC_POL_LOW; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_SP(stream_id), dp_framer_sp); + + front_porch = mode->crtc_hsync_start - mode->crtc_hdisplay; + back_porch = mode->crtc_htotal - mode->crtc_hsync_end; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRONT_BACK_PORCH(stream_id), + CDNS_DP_FRONT_PORCH(front_porch) | + CDNS_DP_BACK_PORCH(back_porch)); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id), + mode->crtc_hdisplay * bpp / 8); + + msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start; + cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id), + CDNS_DP_MSAH0_H_TOTAL(mode->crtc_htotal) | + CDNS_DP_MSAH0_HSYNC_START(msa_h0)); + + hsync = mode->crtc_hsync_end - mode->crtc_hsync_start; + msa_horizontal_1 = CDNS_DP_MSAH1_HSYNC_WIDTH(hsync) | + CDNS_DP_MSAH1_HDISP_WIDTH(mode->crtc_hdisplay); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + msa_horizontal_1 |= CDNS_DP_MSAH1_HSYNC_POL_LOW; + cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_1(stream_id), + msa_horizontal_1); + + msa_v0 = mode->crtc_vtotal - mode->crtc_vsync_start; + cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_0(stream_id), + CDNS_DP_MSAV0_V_TOTAL(mode->crtc_vtotal) | + CDNS_DP_MSAV0_VSYNC_START(msa_v0)); + + vsync = mode->crtc_vsync_end - mode->crtc_vsync_start; + msa_vertical_1 = CDNS_DP_MSAV1_VSYNC_WIDTH(vsync) | + CDNS_DP_MSAV1_VDISP_WIDTH(mode->crtc_vdisplay); + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + msa_vertical_1 |= CDNS_DP_MSAV1_VSYNC_POL_LOW; + cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_VERTICAL_1(stream_id), + msa_vertical_1); + + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + mode->crtc_vtotal % 2 == 0) + misc1 = DP_TEST_INTERLACED; + if (mhdp->display_fmt.y_only) + misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY; + /* Use VSC SDP for Y420 */ + if (pxlfmt == DRM_COLOR_FORMAT_YCRCB420) + misc1 = CDNS_DP_TEST_VSC_SDP; + + cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id), + misc0 | (misc1 << 8)); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_HORIZONTAL(stream_id), + CDNS_DP_H_HSYNC_WIDTH(hsync) | + CDNS_DP_H_H_TOTAL(mode->crtc_hdisplay)); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_0(stream_id), + CDNS_DP_V0_VHEIGHT(mode->crtc_vdisplay) | + CDNS_DP_V0_VSTART(msa_v0)); + + dp_vertical_1 = CDNS_DP_V1_VTOTAL(mode->crtc_vtotal); + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + mode->crtc_vtotal % 2 == 0) + dp_vertical_1 |= CDNS_DP_V1_VTOTAL_EVEN; + + cdns_mhdp_reg_write(mhdp, CDNS_DP_VERTICAL_1(stream_id), dp_vertical_1); + + cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_VB_ID(stream_id), 2, 1, + (mode->flags & DRM_MODE_FLAG_INTERLACE) ? + CDNS_DP_VB_ID_INTERLACED : 0); + + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer); + if (ret < 0) { + dev_err(mhdp->dev, + "Failed to read CDNS_DP_FRAMER_GLOBAL_CONFIG %d\n", + ret); + return; + } + framer |= CDNS_DP_FRAMER_EN; + framer &= ~CDNS_DP_NO_VIDEO_MODE; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer); +} + +static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp, + const struct drm_display_mode *mode) +{ + u32 rate, vs, required_bandwidth, available_bandwidth; + s32 line_thresh1, line_thresh2, line_thresh = 0; + int pxlclock = mode->crtc_clock; + u32 tu_size = 64; + u32 bpp; + + /* Get rate in MSymbols per second per lane */ + rate = mhdp->link.rate / 1000; + + bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt); + + required_bandwidth = pxlclock * bpp / 8; + available_bandwidth = mhdp->link.num_lanes * rate; + + vs = tu_size * required_bandwidth / available_bandwidth; + vs /= 1000; + + if (vs == tu_size) + vs = tu_size - 1; + + line_thresh1 = ((vs + 1) << 5) * 8 / bpp; + line_thresh2 = (pxlclock << 5) / 1000 / rate * (vs + 1) - (1 << 5); + line_thresh = line_thresh1 - line_thresh2 / (s32)mhdp->link.num_lanes; + line_thresh = (line_thresh >> 5) + 2; + + mhdp->stream_id = 0; + + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_TU, + CDNS_DP_FRAMER_TU_VS(vs) | + CDNS_DP_FRAMER_TU_SIZE(tu_size) | + CDNS_DP_FRAMER_TU_CNT_RST_EN); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_LINE_THRESH(0), + line_thresh & GENMASK(5, 0)); + + cdns_mhdp_reg_write(mhdp, CDNS_DP_STREAM_CONFIG_2(0), + CDNS_DP_SC2_TU_VS_DIFF((tu_size - vs > 3) ? + 0 : tu_size - vs)); + + cdns_mhdp_configure_video(mhdp, mode); +} + +static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + struct drm_atomic_state *state = bridge_state->base.state; + struct cdns_mhdp_bridge_state *mhdp_state; + struct drm_crtc_state *crtc_state; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_bridge_state *new_state; + const struct drm_display_mode *mode; + u32 resp; + int ret; + + dev_dbg(mhdp->dev, "bridge enable\n"); + + mutex_lock(&mhdp->link_mutex); + + if (mhdp->plugged && !mhdp->link_up) { + ret = cdns_mhdp_link_up(mhdp); + if (ret < 0) + goto out; + } + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->enable) + mhdp->info->ops->enable(mhdp); + + /* Enable VIF clock for stream 0 */ + ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp); + if (ret < 0) { + dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret); + goto out; + } + + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR, + resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN); + + connector = drm_atomic_get_new_connector_for_encoder(state, + bridge->encoder); + if (WARN_ON(!connector)) + goto out; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + goto out; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + goto out; + + mode = &crtc_state->adjusted_mode; + + new_state = drm_atomic_get_new_bridge_state(state, bridge); + if (WARN_ON(!new_state)) + goto out; + + if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes, + mhdp->link.rate)) { + ret = -EINVAL; + goto out; + } + + cdns_mhdp_sst_enable(mhdp, mode); + + mhdp_state = to_cdns_mhdp_bridge_state(new_state); + + mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode); + drm_mode_set_name(mhdp_state->current_mode); + + dev_dbg(mhdp->dev, "%s: Enabling mode %s\n", __func__, mode->name); + + mhdp->bridge_enabled = true; + +out: + mutex_unlock(&mhdp->link_mutex); + if (ret < 0) + schedule_work(&mhdp->modeset_retry_work); +} + +static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + u32 resp; + + dev_dbg(mhdp->dev, "%s\n", __func__); + + mutex_lock(&mhdp->link_mutex); + + mhdp->bridge_enabled = false; + cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); + resp &= ~CDNS_DP_FRAMER_EN; + resp |= CDNS_DP_NO_VIDEO_MODE; + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, resp); + + cdns_mhdp_link_down(mhdp); + + /* Disable VIF clock for stream 0 */ + cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp); + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR, + resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN)); + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable) + mhdp->info->ops->disable(mhdp); + + mutex_unlock(&mhdp->link_mutex); +} + +static void cdns_mhdp_detach(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + dev_dbg(mhdp->dev, "%s\n", __func__); + + spin_lock(&mhdp->start_lock); + + mhdp->bridge_attached = false; + + spin_unlock(&mhdp->start_lock); + + writel(~0, mhdp->regs + CDNS_APB_INT_MASK); +} + +static struct drm_bridge_state * +cdns_mhdp_bridge_atomic_duplicate_state(struct drm_bridge *bridge) +{ + struct cdns_mhdp_bridge_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_bridge_duplicate_state(bridge, &state->base); + + return &state->base; +} + +static void +cdns_mhdp_bridge_atomic_destroy_state(struct drm_bridge *bridge, + struct drm_bridge_state *state) +{ + struct cdns_mhdp_bridge_state *cdns_mhdp_state; + + cdns_mhdp_state = to_cdns_mhdp_bridge_state(state); + + if (cdns_mhdp_state->current_mode) { + drm_mode_destroy(bridge->dev, cdns_mhdp_state->current_mode); + cdns_mhdp_state->current_mode = NULL; + } + + kfree(cdns_mhdp_state); +} + +static struct drm_bridge_state * +cdns_mhdp_bridge_atomic_reset(struct drm_bridge *bridge) +{ + struct cdns_mhdp_bridge_state *cdns_mhdp_state; + + cdns_mhdp_state = kzalloc(sizeof(*cdns_mhdp_state), GFP_KERNEL); + if (!cdns_mhdp_state) + return NULL; + + __drm_atomic_helper_bridge_reset(bridge, &cdns_mhdp_state->base); + + return &cdns_mhdp_state->base; +} + +static int cdns_mhdp_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + const struct drm_display_mode *mode = &crtc_state->adjusted_mode; + + mutex_lock(&mhdp->link_mutex); + + if (!cdns_mhdp_bandwidth_ok(mhdp, mode, mhdp->link.num_lanes, + mhdp->link.rate)) { + dev_err(mhdp->dev, "%s: Not enough BW for %s (%u lanes at %u Mbps)\n", + __func__, mode->name, mhdp->link.num_lanes, + mhdp->link.rate / 100); + mutex_unlock(&mhdp->link_mutex); + return -EINVAL; + } + + mutex_unlock(&mhdp->link_mutex); + return 0; +} + +static enum drm_connector_status cdns_mhdp_bridge_detect(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + return cdns_mhdp_detect(mhdp); +} + +static struct edid *cdns_mhdp_bridge_get_edid(struct drm_bridge *bridge, + struct drm_connector *connector) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + return cdns_mhdp_get_edid(mhdp, connector); +} + +static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + /* Enable SW event interrupts */ + if (mhdp->bridge_attached) + writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + mhdp->regs + CDNS_APB_INT_MASK); +} + +static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge) +{ + struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge); + + writel(CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK); +} + +static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = { + .atomic_enable = cdns_mhdp_atomic_enable, + .atomic_disable = cdns_mhdp_atomic_disable, + .atomic_check = cdns_mhdp_atomic_check, + .attach = cdns_mhdp_attach, + .detach = cdns_mhdp_detach, + .atomic_duplicate_state = cdns_mhdp_bridge_atomic_duplicate_state, + .atomic_destroy_state = cdns_mhdp_bridge_atomic_destroy_state, + .atomic_reset = cdns_mhdp_bridge_atomic_reset, + .detect = cdns_mhdp_bridge_detect, + .get_edid = cdns_mhdp_bridge_get_edid, + .hpd_enable = cdns_mhdp_bridge_hpd_enable, + .hpd_disable = cdns_mhdp_bridge_hpd_disable, +}; + +static bool cdns_mhdp_detect_hpd(struct cdns_mhdp_device *mhdp, bool *hpd_pulse) +{ + int hpd_event, hpd_status; + + *hpd_pulse = false; + + hpd_event = cdns_mhdp_read_hpd_event(mhdp); + + /* Getting event bits failed, bail out */ + if (hpd_event < 0) { + dev_warn(mhdp->dev, "%s: read event failed: %d\n", + __func__, hpd_event); + return false; + } + + hpd_status = cdns_mhdp_get_hpd_status(mhdp); + if (hpd_status < 0) { + dev_warn(mhdp->dev, "%s: get hpd status failed: %d\n", + __func__, hpd_status); + return false; + } + + if (hpd_event & DPTX_READ_EVENT_HPD_PULSE) + *hpd_pulse = true; + + return !!hpd_status; +} + +static int cdns_mhdp_update_link_status(struct cdns_mhdp_device *mhdp) +{ + struct cdns_mhdp_bridge_state *cdns_bridge_state; + struct drm_display_mode *current_mode; + bool old_plugged = mhdp->plugged; + struct drm_bridge_state *state; + u8 status[DP_LINK_STATUS_SIZE]; + bool hpd_pulse; + int ret = 0; + + mutex_lock(&mhdp->link_mutex); + + mhdp->plugged = cdns_mhdp_detect_hpd(mhdp, &hpd_pulse); + + if (!mhdp->plugged) { + cdns_mhdp_link_down(mhdp); + mhdp->link.rate = mhdp->host.link_rate; + mhdp->link.num_lanes = mhdp->host.lanes_cnt; + goto out; + } + + /* + * If we get a HPD pulse event and we were and still are connected, + * check the link status. If link status is ok, there's nothing to do + * as we don't handle DP interrupts. If link status is bad, continue + * with full link setup. + */ + if (hpd_pulse && old_plugged == mhdp->plugged) { + ret = drm_dp_dpcd_read_link_status(&mhdp->aux, status); + + /* + * If everything looks fine, just return, as we don't handle + * DP IRQs. + */ + if (ret > 0 && + drm_dp_channel_eq_ok(status, mhdp->link.num_lanes) && + drm_dp_clock_recovery_ok(status, mhdp->link.num_lanes)) + goto out; + + /* If link is bad, mark link as down so that we do a new LT */ + mhdp->link_up = false; + } + + if (!mhdp->link_up) { + ret = cdns_mhdp_link_up(mhdp); + if (ret < 0) + goto out; + } + + if (mhdp->bridge_enabled) { + state = drm_priv_to_bridge_state(mhdp->bridge.base.state); + if (!state) { + ret = -EINVAL; + goto out; + } + + cdns_bridge_state = to_cdns_mhdp_bridge_state(state); + if (!cdns_bridge_state) { + ret = -EINVAL; + goto out; + } + + current_mode = cdns_bridge_state->current_mode; + if (!current_mode) { + ret = -EINVAL; + goto out; + } + + if (!cdns_mhdp_bandwidth_ok(mhdp, current_mode, mhdp->link.num_lanes, + mhdp->link.rate)) { + ret = -EINVAL; + goto out; + } + + dev_dbg(mhdp->dev, "%s: Enabling mode %s\n", __func__, + current_mode->name); + + cdns_mhdp_sst_enable(mhdp, current_mode); + } +out: + mutex_unlock(&mhdp->link_mutex); + return ret; +} + +static void cdns_mhdp_modeset_retry_fn(struct work_struct *work) +{ + struct cdns_mhdp_device *mhdp; + struct drm_connector *conn; + + mhdp = container_of(work, typeof(*mhdp), modeset_retry_work); + + conn = &mhdp->connector; + + /* Grab the locks before changing connector property */ + mutex_lock(&conn->dev->mode_config.mutex); + + /* + * Set connector link status to BAD and send a Uevent to notify + * userspace to do a modeset. + */ + drm_connector_set_link_status_property(conn, DRM_MODE_LINK_STATUS_BAD); + mutex_unlock(&conn->dev->mode_config.mutex); + + /* Send Hotplug uevent so userspace can reprobe */ + drm_kms_helper_hotplug_event(mhdp->bridge.dev); +} + +static irqreturn_t cdns_mhdp_irq_handler(int irq, void *data) +{ + struct cdns_mhdp_device *mhdp = data; + u32 apb_stat, sw_ev0; + bool bridge_attached; + int ret; + + apb_stat = readl(mhdp->regs + CDNS_APB_INT_STATUS); + if (!(apb_stat & CDNS_APB_INT_MASK_SW_EVENT_INT)) + return IRQ_NONE; + + sw_ev0 = readl(mhdp->regs + CDNS_SW_EVENT0); + + /* + * Calling drm_kms_helper_hotplug_event() when not attached + * to drm device causes an oops because the drm_bridge->dev + * is NULL. See cdns_mhdp_fw_cb() comments for details about the + * problems related drm_kms_helper_hotplug_event() call. + */ + spin_lock(&mhdp->start_lock); + bridge_attached = mhdp->bridge_attached; + spin_unlock(&mhdp->start_lock); + + if (bridge_attached && (sw_ev0 & CDNS_DPTX_HPD)) { + ret = cdns_mhdp_update_link_status(mhdp); + if (mhdp->connector.dev) { + if (ret < 0) + schedule_work(&mhdp->modeset_retry_work); + else + drm_kms_helper_hotplug_event(mhdp->bridge.dev); + } else { + drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); + } + } + + return IRQ_HANDLED; +} + +static int cdns_mhdp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct cdns_mhdp_device *mhdp; + unsigned long rate; + struct clk *clk; + int ret; + int irq; + + mhdp = devm_kzalloc(dev, sizeof(*mhdp), GFP_KERNEL); + if (!mhdp) + return -ENOMEM; + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + dev_err(dev, "couldn't get clk: %ld\n", PTR_ERR(clk)); + return PTR_ERR(clk); + } + + mhdp->clk = clk; + mhdp->dev = dev; + mutex_init(&mhdp->mbox_mutex); + mutex_init(&mhdp->link_mutex); + spin_lock_init(&mhdp->start_lock); + + drm_dp_aux_init(&mhdp->aux); + mhdp->aux.dev = dev; + mhdp->aux.transfer = cdns_mhdp_transfer; + + mhdp->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mhdp->regs)) { + dev_err(dev, "Failed to get memory resource\n"); + return PTR_ERR(mhdp->regs); + } + + mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0); + if (IS_ERR(mhdp->phy)) { + dev_err(dev, "no PHY configured\n"); + return PTR_ERR(mhdp->phy); + } + + platform_set_drvdata(pdev, mhdp); + + mhdp->info = of_device_get_match_data(dev); + + clk_prepare_enable(clk); + + pm_runtime_enable(dev); + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err(dev, "pm_runtime_get_sync failed\n"); + pm_runtime_disable(dev); + goto clk_disable; + } + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->init) { + ret = mhdp->info->ops->init(mhdp); + if (ret != 0) { + dev_err(dev, "MHDP platform initialization failed: %d\n", + ret); + goto runtime_put; + } + } + + rate = clk_get_rate(clk); + writel(rate % 1000000, mhdp->regs + CDNS_SW_CLK_L); + writel(rate / 1000000, mhdp->regs + CDNS_SW_CLK_H); + + dev_dbg(dev, "func clk rate %lu Hz\n", rate); + + writel(~0, mhdp->regs + CDNS_APB_INT_MASK); + + irq = platform_get_irq(pdev, 0); + ret = devm_request_threaded_irq(mhdp->dev, irq, NULL, + cdns_mhdp_irq_handler, IRQF_ONESHOT, + "mhdp8546", mhdp); + if (ret) { + dev_err(dev, "cannot install IRQ %d\n", irq); + ret = -EIO; + goto plat_fini; + } + + cdns_mhdp_fill_host_caps(mhdp); + + /* Initialize link rate and num of lanes to host values */ + mhdp->link.rate = mhdp->host.link_rate; + mhdp->link.num_lanes = mhdp->host.lanes_cnt; + + /* The only currently supported format */ + mhdp->display_fmt.y_only = false; + mhdp->display_fmt.color_format = DRM_COLOR_FORMAT_RGB444; + mhdp->display_fmt.bpc = 8; + + mhdp->bridge.of_node = pdev->dev.of_node; + mhdp->bridge.funcs = &cdns_mhdp_bridge_funcs; + mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_HPD; + mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; + if (mhdp->info) + mhdp->bridge.timings = mhdp->info->timings; + + ret = phy_init(mhdp->phy); + if (ret) { + dev_err(mhdp->dev, "Failed to initialize PHY: %d\n", ret); + goto plat_fini; + } + + /* Initialize the work for modeset in case of link train failure */ + INIT_WORK(&mhdp->modeset_retry_work, cdns_mhdp_modeset_retry_fn); + + init_waitqueue_head(&mhdp->fw_load_wq); + + ret = cdns_mhdp_load_firmware(mhdp); + if (ret) + goto phy_exit; + + drm_bridge_add(&mhdp->bridge); + + return 0; + +phy_exit: + phy_exit(mhdp->phy); +plat_fini: + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->exit) + mhdp->info->ops->exit(mhdp); +runtime_put: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +clk_disable: + clk_disable_unprepare(mhdp->clk); + + return ret; +} + +static int cdns_mhdp_remove(struct platform_device *pdev) +{ + struct cdns_mhdp_device *mhdp = dev_get_drvdata(&pdev->dev); + unsigned long timeout = msecs_to_jiffies(100); + bool stop_fw = false; + int ret; + + drm_bridge_remove(&mhdp->bridge); + + ret = wait_event_timeout(mhdp->fw_load_wq, + mhdp->hw_state == MHDP_HW_READY, + timeout); + if (ret == 0) + dev_err(mhdp->dev, "%s: Timeout waiting for fw loading\n", + __func__); + else + stop_fw = true; + + spin_lock(&mhdp->start_lock); + mhdp->hw_state = MHDP_HW_STOPPED; + spin_unlock(&mhdp->start_lock); + + if (stop_fw) + ret = cdns_mhdp_set_firmware_active(mhdp, false); + + phy_exit(mhdp->phy); + + if (mhdp->info && mhdp->info->ops && mhdp->info->ops->exit) + mhdp->info->ops->exit(mhdp); + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + cancel_work_sync(&mhdp->modeset_retry_work); + flush_scheduled_work(); + + clk_disable_unprepare(mhdp->clk); + + return ret; +} + +static const struct of_device_id mhdp_ids[] = { + { .compatible = "cdns,mhdp8546", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mhdp_ids); + +static struct platform_driver mhdp_driver = { + .driver = { + .name = "cdns-mhdp8546", + .of_match_table = of_match_ptr(mhdp_ids), + }, + .probe = cdns_mhdp_probe, + .remove = cdns_mhdp_remove, +}; +module_platform_driver(mhdp_driver); + +MODULE_FIRMWARE(FW_NAME); + +MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>"); +MODULE_AUTHOR("Swapnil Jakhade <sjakhade@cadence.com>"); +MODULE_AUTHOR("Yuti Amonkar <yamonkar@cadence.com>"); +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); +MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>"); +MODULE_DESCRIPTION("Cadence MHDP8546 DP bridge driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:cdns-mhdp8546"); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h new file mode 100644 index 0000000000000..c0fff78d15be1 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Cadence MHDP8546 DP bridge driver. + * + * Copyright (C) 2020 Cadence Design Systems, Inc. + * + * Author: Quentin Schulz <quentin.schulz@free-electrons.com> + * Swapnil Jakhade <sjakhade@cadence.com> + */ + +#ifndef CDNS_MHDP8546_CORE_H +#define CDNS_MHDP8546_CORE_H + +#include <linux/bits.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> + +#include <drm/drm_bridge.h> +#include <drm/drm_connector.h> +#include <drm/drm_dp_helper.h> + +struct clk; +struct device; +struct phy; + +/* Register offsets */ +#define CDNS_APB_CTRL 0x00000 +#define CDNS_CPU_STALL BIT(3) + +#define CDNS_MAILBOX_FULL 0x00008 +#define CDNS_MAILBOX_EMPTY 0x0000c +#define CDNS_MAILBOX_TX_DATA 0x00010 +#define CDNS_MAILBOX_RX_DATA 0x00014 +#define CDNS_KEEP_ALIVE 0x00018 +#define CDNS_KEEP_ALIVE_MASK GENMASK(7, 0) + +#define CDNS_VER_L 0x0001C +#define CDNS_VER_H 0x00020 +#define CDNS_LIB_L_ADDR 0x00024 +#define CDNS_LIB_H_ADDR 0x00028 + +#define CDNS_MB_INT_MASK 0x00034 +#define CDNS_MB_INT_STATUS 0x00038 + +#define CDNS_SW_CLK_L 0x0003c +#define CDNS_SW_CLK_H 0x00040 + +#define CDNS_SW_EVENT0 0x00044 +#define CDNS_DPTX_HPD BIT(0) + +#define CDNS_SW_EVENT1 0x00048 +#define CDNS_SW_EVENT2 0x0004c +#define CDNS_SW_EVENT3 0x00050 + +#define CDNS_APB_INT_MASK 0x0006C +#define CDNS_APB_INT_MASK_MAILBOX_INT BIT(0) +#define CDNS_APB_INT_MASK_SW_EVENT_INT BIT(1) + +#define CDNS_APB_INT_STATUS 0x00070 + +#define CDNS_DPTX_CAR 0x00904 +#define CDNS_VIF_CLK_EN BIT(0) +#define CDNS_VIF_CLK_RSTN BIT(1) + +#define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20)) +#define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \ + 0x00) +#define CDNS_IP_DTCT_WIN GENMASK(11, 0) +#define CDNS_IP_DET_INTERLACE_FORMAT BIT(12) +#define CDNS_IP_BYPASS_V_INTERFACE BIT(13) + +#define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \ + 0x10) +#define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1) +#define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2) + +#define CDNS_DPTX_PHY_CONFIG 0x02000 +#define CDNS_PHY_TRAINING_EN BIT(0) +#define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1) +#define CDNS_PHY_SCRAMBLER_BYPASS BIT(5) +#define CDNS_PHY_ENCODER_BYPASS BIT(6) +#define CDNS_PHY_SKEW_BYPASS BIT(7) +#define CDNS_PHY_TRAINING_AUTO BIT(8) +#define CDNS_PHY_LANE0_SKEW(x) (((x) & GENMASK(2, 0)) << 9) +#define CDNS_PHY_LANE1_SKEW(x) (((x) & GENMASK(2, 0)) << 12) +#define CDNS_PHY_LANE2_SKEW(x) (((x) & GENMASK(2, 0)) << 15) +#define CDNS_PHY_LANE3_SKEW(x) (((x) & GENMASK(2, 0)) << 18) +#define CDNS_PHY_COMMON_CONFIG (CDNS_PHY_LANE1_SKEW(1) | \ + CDNS_PHY_LANE2_SKEW(2) | \ + CDNS_PHY_LANE3_SKEW(3)) +#define CDNS_PHY_10BIT_EN BIT(21) + +#define CDNS_DP_FRAMER_GLOBAL_CONFIG 0x02200 +#define CDNS_DP_NUM_LANES(x) ((x) - 1) +#define CDNS_DP_MST_EN BIT(2) +#define CDNS_DP_FRAMER_EN BIT(3) +#define CDNS_DP_RATE_GOVERNOR_EN BIT(4) +#define CDNS_DP_NO_VIDEO_MODE BIT(5) +#define CDNS_DP_DISABLE_PHY_RST BIT(6) +#define CDNS_DP_WR_FAILING_EDGE_VSYNC BIT(7) + +#define CDNS_DP_FRAMER_TU 0x02208 +#define CDNS_DP_FRAMER_TU_SIZE(x) (((x) & GENMASK(6, 0)) << 8) +#define CDNS_DP_FRAMER_TU_VS(x) ((x) & GENMASK(5, 0)) +#define CDNS_DP_FRAMER_TU_CNT_RST_EN BIT(15) + +#define CDNS_DP_MTPH_CONTROL 0x02264 +#define CDNS_DP_MTPH_ECF_EN BIT(0) +#define CDNS_DP_MTPH_ACT_EN BIT(1) +#define CDNS_DP_MTPH_LVP_EN BIT(2) + +#define CDNS_DP_MTPH_STATUS 0x0226C +#define CDNS_DP_MTPH_ACT_STATUS BIT(0) + +#define CDNS_DP_LANE_EN 0x02300 +#define CDNS_DP_LANE_EN_LANES(x) GENMASK((x) - 1, 0) + +#define CDNS_DP_ENHNCD 0x02304 + +#define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80) +#define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00) +#define CDNS_DP_MSAH0_H_TOTAL(x) (x) +#define CDNS_DP_MSAH0_HSYNC_START(x) ((x) << 16) + +#define CDNS_DP_MSA_HORIZONTAL_1(s) (CDNS_DPTX_STREAM(s) + 0x04) +#define CDNS_DP_MSAH1_HSYNC_WIDTH(x) (x) +#define CDNS_DP_MSAH1_HSYNC_POL_LOW BIT(15) +#define CDNS_DP_MSAH1_HDISP_WIDTH(x) ((x) << 16) + +#define CDNS_DP_MSA_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x08) +#define CDNS_DP_MSAV0_V_TOTAL(x) (x) +#define CDNS_DP_MSAV0_VSYNC_START(x) ((x) << 16) + +#define CDNS_DP_MSA_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x0c) +#define CDNS_DP_MSAV1_VSYNC_WIDTH(x) (x) +#define CDNS_DP_MSAV1_VSYNC_POL_LOW BIT(15) +#define CDNS_DP_MSAV1_VDISP_WIDTH(x) ((x) << 16) + +#define CDNS_DP_MSA_MISC(s) (CDNS_DPTX_STREAM(s) + 0x10) +#define CDNS_DP_STREAM_CONFIG(s) (CDNS_DPTX_STREAM(s) + 0x14) +#define CDNS_DP_STREAM_CONFIG_2(s) (CDNS_DPTX_STREAM(s) + 0x2c) +#define CDNS_DP_SC2_TU_VS_DIFF(x) ((x) << 8) + +#define CDNS_DP_HORIZONTAL(s) (CDNS_DPTX_STREAM(s) + 0x30) +#define CDNS_DP_H_HSYNC_WIDTH(x) (x) +#define CDNS_DP_H_H_TOTAL(x) ((x) << 16) + +#define CDNS_DP_VERTICAL_0(s) (CDNS_DPTX_STREAM(s) + 0x34) +#define CDNS_DP_V0_VHEIGHT(x) (x) +#define CDNS_DP_V0_VSTART(x) ((x) << 16) + +#define CDNS_DP_VERTICAL_1(s) (CDNS_DPTX_STREAM(s) + 0x38) +#define CDNS_DP_V1_VTOTAL(x) (x) +#define CDNS_DP_V1_VTOTAL_EVEN BIT(16) + +#define CDNS_DP_MST_SLOT_ALLOCATE(s) (CDNS_DPTX_STREAM(s) + 0x44) +#define CDNS_DP_S_ALLOC_START_SLOT(x) (x) +#define CDNS_DP_S_ALLOC_END_SLOT(x) ((x) << 8) + +#define CDNS_DP_RATE_GOVERNING(s) (CDNS_DPTX_STREAM(s) + 0x48) +#define CDNS_DP_RG_TARG_AV_SLOTS_Y(x) (x) +#define CDNS_DP_RG_TARG_AV_SLOTS_X(x) ((x) << 4) +#define CDNS_DP_RG_ENABLE BIT(10) + +#define CDNS_DP_FRAMER_PXL_REPR(s) (CDNS_DPTX_STREAM(s) + 0x4c) +#define CDNS_DP_FRAMER_6_BPC BIT(0) +#define CDNS_DP_FRAMER_8_BPC BIT(1) +#define CDNS_DP_FRAMER_10_BPC BIT(2) +#define CDNS_DP_FRAMER_12_BPC BIT(3) +#define CDNS_DP_FRAMER_16_BPC BIT(4) +#define CDNS_DP_FRAMER_PXL_FORMAT 0x8 +#define CDNS_DP_FRAMER_RGB BIT(0) +#define CDNS_DP_FRAMER_YCBCR444 BIT(1) +#define CDNS_DP_FRAMER_YCBCR422 BIT(2) +#define CDNS_DP_FRAMER_YCBCR420 BIT(3) +#define CDNS_DP_FRAMER_Y_ONLY BIT(4) + +#define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50) +#define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0) +#define CDNS_DP_FRAMER_HSYNC_POL_LOW BIT(1) +#define CDNS_DP_FRAMER_INTERLACE BIT(2) + +#define CDNS_DP_LINE_THRESH(s) (CDNS_DPTX_STREAM(s) + 0x64) +#define CDNS_DP_ACTIVE_LINE_THRESH(x) (x) + +#define CDNS_DP_VB_ID(s) (CDNS_DPTX_STREAM(s) + 0x68) +#define CDNS_DP_VB_ID_INTERLACED BIT(2) +#define CDNS_DP_VB_ID_COMPRESSED BIT(6) + +#define CDNS_DP_FRONT_BACK_PORCH(s) (CDNS_DPTX_STREAM(s) + 0x78) +#define CDNS_DP_BACK_PORCH(x) (x) +#define CDNS_DP_FRONT_PORCH(x) ((x) << 16) + +#define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c) +#define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16 + +/* mailbox */ +#define MAILBOX_RETRY_US 1000 +#define MAILBOX_TIMEOUT_US 2000000 + +#define MB_OPCODE_ID 0 +#define MB_MODULE_ID 1 +#define MB_SIZE_MSB_ID 2 +#define MB_SIZE_LSB_ID 3 +#define MB_DATA_ID 4 + +#define MB_MODULE_ID_DP_TX 0x01 +#define MB_MODULE_ID_HDCP_TX 0x07 +#define MB_MODULE_ID_HDCP_RX 0x08 +#define MB_MODULE_ID_HDCP_GENERAL 0x09 +#define MB_MODULE_ID_GENERAL 0x0a + +/* firmware and opcodes */ +#define FW_NAME "cadence/mhdp8546.bin" +#define CDNS_MHDP_IMEM 0x10000 + +#define GENERAL_MAIN_CONTROL 0x01 +#define GENERAL_TEST_ECHO 0x02 +#define GENERAL_BUS_SETTINGS 0x03 +#define GENERAL_TEST_ACCESS 0x04 +#define GENERAL_REGISTER_READ 0x07 + +#define DPTX_SET_POWER_MNG 0x00 +#define DPTX_GET_EDID 0x02 +#define DPTX_READ_DPCD 0x03 +#define DPTX_WRITE_DPCD 0x04 +#define DPTX_ENABLE_EVENT 0x05 +#define DPTX_WRITE_REGISTER 0x06 +#define DPTX_READ_REGISTER 0x07 +#define DPTX_WRITE_FIELD 0x08 +#define DPTX_READ_EVENT 0x0a +#define DPTX_GET_LAST_AUX_STAUS 0x0e +#define DPTX_HPD_STATE 0x11 +#define DPTX_ADJUST_LT 0x12 + +#define FW_STANDBY 0 +#define FW_ACTIVE 1 + +/* HPD */ +#define DPTX_READ_EVENT_HPD_TO_HIGH BIT(0) +#define DPTX_READ_EVENT_HPD_TO_LOW BIT(1) +#define DPTX_READ_EVENT_HPD_PULSE BIT(2) +#define DPTX_READ_EVENT_HPD_STATE BIT(3) + +/* general */ +#define CDNS_DP_TRAINING_PATTERN_4 0x7 + +#define CDNS_KEEP_ALIVE_TIMEOUT 2000 + +#define CDNS_VOLT_SWING(x) ((x) & GENMASK(1, 0)) +#define CDNS_FORCE_VOLT_SWING BIT(2) + +#define CDNS_PRE_EMPHASIS(x) ((x) & GENMASK(1, 0)) +#define CDNS_FORCE_PRE_EMPHASIS BIT(2) + +#define CDNS_SUPPORT_TPS(x) BIT((x) - 1) + +#define CDNS_FAST_LINK_TRAINING BIT(0) + +#define CDNS_LANE_MAPPING_TYPE_C_LANE_0(x) ((x) & GENMASK(1, 0)) +#define CDNS_LANE_MAPPING_TYPE_C_LANE_1(x) ((x) & GENMASK(3, 2)) +#define CDNS_LANE_MAPPING_TYPE_C_LANE_2(x) ((x) & GENMASK(5, 4)) +#define CDNS_LANE_MAPPING_TYPE_C_LANE_3(x) ((x) & GENMASK(7, 6)) +#define CDNS_LANE_MAPPING_NORMAL 0xe4 +#define CDNS_LANE_MAPPING_FLIPPED 0x1b + +#define CDNS_DP_MAX_NUM_LANES 4 +#define CDNS_DP_TEST_VSC_SDP BIT(6) /* 1.3+ */ +#define CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY BIT(7) + +#define CDNS_MHDP_MAX_STREAMS 4 + +#define DP_LINK_CAP_ENHANCED_FRAMING BIT(0) + +struct cdns_mhdp_link { + unsigned char revision; + unsigned int rate; + unsigned int num_lanes; + unsigned long capabilities; +}; + +struct cdns_mhdp_host { + unsigned int link_rate; + u8 lanes_cnt; + u8 volt_swing; + u8 pre_emphasis; + u8 pattern_supp; + u8 lane_mapping; + bool fast_link; + bool enhanced; + bool scrambler; + bool ssc; +}; + +struct cdns_mhdp_sink { + unsigned int link_rate; + u8 lanes_cnt; + u8 pattern_supp; + bool fast_link; + bool enhanced; + bool ssc; +}; + +struct cdns_mhdp_display_fmt { + u32 color_format; + u32 bpc; + bool y_only; +}; + +/* + * These enums present MHDP hw initialization state + * Legal state transitions are: + * MHDP_HW_READY <-> MHDP_HW_STOPPED + */ +enum mhdp_hw_state { + MHDP_HW_READY = 1, /* HW ready, FW active */ + MHDP_HW_STOPPED /* Driver removal FW to be stopped */ +}; + +struct cdns_mhdp_device; + +struct mhdp_platform_ops { + int (*init)(struct cdns_mhdp_device *mhdp); + void (*exit)(struct cdns_mhdp_device *mhdp); + void (*enable)(struct cdns_mhdp_device *mhdp); + void (*disable)(struct cdns_mhdp_device *mhdp); +}; + +struct cdns_mhdp_bridge_state { + struct drm_bridge_state base; + struct drm_display_mode *current_mode; +}; + +struct cdns_mhdp_platform_info { + const struct drm_bridge_timings *timings; + const struct mhdp_platform_ops *ops; +}; + +#define to_cdns_mhdp_bridge_state(s) \ + container_of(s, struct cdns_mhdp_bridge_state, base) + +struct cdns_mhdp_device { + void __iomem *regs; + + struct device *dev; + struct clk *clk; + struct phy *phy; + + const struct cdns_mhdp_platform_info *info; + + /* This is to protect mailbox communications with the firmware */ + struct mutex mbox_mutex; + + /* + * "link_mutex" protects the access to all the link parameters + * including the link training process. Link training will be + * invoked both from threaded interrupt handler and from atomic + * callbacks when link_up is not set. So this mutex protects + * flags such as link_up, bridge_enabled, link.num_lanes, + * link.rate etc. + */ + struct mutex link_mutex; + + struct drm_connector connector; + struct drm_bridge bridge; + + struct cdns_mhdp_link link; + struct drm_dp_aux aux; + + struct cdns_mhdp_host host; + struct cdns_mhdp_sink sink; + struct cdns_mhdp_display_fmt display_fmt; + u8 stream_id; + + bool link_up; + bool plugged; + + /* + * "start_lock" protects the access to bridge_attached and + * hw_state data members that control the delayed firmware + * loading and attaching the bridge. They are accessed from + * both the DRM core and cdns_mhdp_fw_cb(). In most cases just + * protecting the data members is enough, but the irq mask + * setting needs to be protected when enabling the FW. + */ + spinlock_t start_lock; + bool bridge_attached; + bool bridge_enabled; + enum mhdp_hw_state hw_state; + wait_queue_head_t fw_load_wq; + + /* Work struct to schedule a uevent on link train failure */ + struct work_struct modeset_retry_work; +}; + +#define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector) +#define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge) + +#endif -- GitLab From afba7e6c5fc190b687f3d87bc6d1029d1500c059 Mon Sep 17 00:00:00 2001 From: Swapnil Jakhade <sjakhade@cadence.com> Date: Fri, 18 Sep 2020 14:09:23 +0200 Subject: [PATCH 1327/1494] drm: bridge: cdns-mhdp8546: Add TI J721E wrapper Add J721E wrapper for mhdp, which sets up the clock and data muxes. Signed-off-by: Jyri Sarha <jsarha@ti.com> Signed-off-by: Yuti Amonkar <yamonkar@cadence.com> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> --- drivers/gpu/drm/bridge/cadence/Kconfig | 13 ++++ drivers/gpu/drm/bridge/cadence/Makefile | 1 + .../drm/bridge/cadence/cdns-mhdp8546-core.c | 10 +++ .../drm/bridge/cadence/cdns-mhdp8546-core.h | 1 + .../drm/bridge/cadence/cdns-mhdp8546-j721e.c | 78 +++++++++++++++++++ .../drm/bridge/cadence/cdns-mhdp8546-j721e.h | 19 +++++ 6 files changed, 122 insertions(+) create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h diff --git a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig index f49d77eb78148..511d67b16d14d 100644 --- a/drivers/gpu/drm/bridge/cadence/Kconfig +++ b/drivers/gpu/drm/bridge/cadence/Kconfig @@ -9,3 +9,16 @@ config DRM_CDNS_MHDP8546 bridge and is meant to be directly embedded in a SoC. It takes a DPI stream as input and outputs it encoded in DP format. + +if DRM_CDNS_MHDP8546 + +config DRM_CDNS_MHDP8546_J721E + depends on ARCH_K3_J721E_SOC || COMPILE_TEST + bool "J721E Cadence DPI/DP wrapper support" + default y + help + Support J721E Cadence DPI/DP wrapper. This is a wrapper + which adds support for J721E related platform ops. It + initializes the J721E Display Port and sets up the + clock and data muxes. +endif diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile index 676739cdf5e62..8f647991b3741 100644 --- a/drivers/gpu/drm/bridge/cadence/Makefile +++ b/drivers/gpu/drm/bridge/cadence/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o cdns-mhdp8546-y := cdns-mhdp8546-core.o +cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 7b1bd5d10923e..621ebdbff8a3a 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -50,6 +50,8 @@ #include "cdns-mhdp8546-core.h" +#include "cdns-mhdp8546-j721e.h" + static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) { int ret, empty; @@ -2496,6 +2498,14 @@ static int cdns_mhdp_remove(struct platform_device *pdev) static const struct of_device_id mhdp_ids[] = { { .compatible = "cdns,mhdp8546", }, +#ifdef CONFIG_DRM_CDNS_MHDP8546_J721E + { .compatible = "ti,j721e-mhdp8546", + .data = &(const struct cdns_mhdp_platform_info) { + .timings = &mhdp_ti_j721e_bridge_timings, + .ops = &mhdp_ti_j721e_ops, + }, + }, +#endif { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mhdp_ids); diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h index c0fff78d15be1..5897a85e31599 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h @@ -341,6 +341,7 @@ struct cdns_mhdp_platform_info { struct cdns_mhdp_device { void __iomem *regs; + void __iomem *j721e_regs; struct device *dev; struct clk *clk; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c new file mode 100644 index 0000000000000..dfe1b59514f74 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * TI j721e Cadence MHDP8546 DP wrapper + * + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Jyri Sarha <jsarha@ti.com> + */ + +#include <linux/io.h> +#include <linux/platform_device.h> + +#include "cdns-mhdp8546-j721e.h" + +#define REVISION 0x00 +#define DPTX_IPCFG 0x04 +#define ECC_MEM_CFG 0x08 +#define DPTX_DSC_CFG 0x0c +#define DPTX_SRC_CFG 0x10 +#define DPTX_VIF_SECURE_MODE_CFG 0x14 +#define DPTX_VIF_CONN_STATUS 0x18 +#define PHY_CLK_STATUS 0x1c + +#define DPTX_SRC_AIF_EN BIT(16) +#define DPTX_SRC_VIF_3_IN30B BIT(11) +#define DPTX_SRC_VIF_2_IN30B BIT(10) +#define DPTX_SRC_VIF_1_IN30B BIT(9) +#define DPTX_SRC_VIF_0_IN30B BIT(8) +#define DPTX_SRC_VIF_3_SEL_DPI5 BIT(7) +#define DPTX_SRC_VIF_3_SEL_DPI3 0 +#define DPTX_SRC_VIF_2_SEL_DPI4 BIT(6) +#define DPTX_SRC_VIF_2_SEL_DPI2 0 +#define DPTX_SRC_VIF_1_SEL_DPI3 BIT(5) +#define DPTX_SRC_VIF_1_SEL_DPI1 0 +#define DPTX_SRC_VIF_0_SEL_DPI2 BIT(4) +#define DPTX_SRC_VIF_0_SEL_DPI0 0 +#define DPTX_SRC_VIF_3_EN BIT(3) +#define DPTX_SRC_VIF_2_EN BIT(2) +#define DPTX_SRC_VIF_1_EN BIT(1) +#define DPTX_SRC_VIF_0_EN BIT(0) + +/* TODO turn DPTX_IPCFG fw_mem_clk_en at pm_runtime_suspend. */ + +static int cdns_mhdp_j721e_init(struct cdns_mhdp_device *mhdp) +{ + struct platform_device *pdev = to_platform_device(mhdp->dev); + + mhdp->j721e_regs = devm_platform_ioremap_resource(pdev, 1); + return PTR_ERR_OR_ZERO(mhdp->j721e_regs); +} + +static void cdns_mhdp_j721e_enable(struct cdns_mhdp_device *mhdp) +{ + /* + * Enable VIF_0 and select DPI2 as its input. DSS0 DPI0 is connected + * to eDP DPI2. This is the only supported SST configuration on + * J721E. + */ + writel(DPTX_SRC_VIF_0_EN | DPTX_SRC_VIF_0_SEL_DPI2, + mhdp->j721e_regs + DPTX_SRC_CFG); +} + +static void cdns_mhdp_j721e_disable(struct cdns_mhdp_device *mhdp) +{ + /* Put everything to defaults */ + writel(0, mhdp->j721e_regs + DPTX_DSC_CFG); +} + +const struct mhdp_platform_ops mhdp_ti_j721e_ops = { + .init = cdns_mhdp_j721e_init, + .enable = cdns_mhdp_j721e_enable, + .disable = cdns_mhdp_j721e_disable, +}; + +const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings = { + .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE | + DRM_BUS_FLAG_DE_HIGH, +}; diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h new file mode 100644 index 0000000000000..97d20d115a242 --- /dev/null +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * TI j721e Cadence MHDP8546 DP wrapper + * + * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Jyri Sarha <jsarha@ti.com> + */ + +#ifndef CDNS_MHDP8546_J721E_H +#define CDNS_MHDP8546_J721E_H + +#include "cdns-mhdp8546-core.h" + +struct mhdp_platform_ops; + +extern const struct mhdp_platform_ops mhdp_ti_j721e_ops; +extern const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings; + +#endif /* !CDNS_MHDP8546_J721E_H */ -- GitLab From 4e139a9abb007370e8d0266ea31192e606c800cf Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta <vaibhavgupta40@gmail.com> Date: Thu, 17 Sep 2020 17:23:14 +0530 Subject: [PATCH 1328/1494] fbdev: aty: remove CONFIG_PM container The changes made in below mentioned commit removed CONFIG_PM containers from drivers/video/fbdev/aty/atyfb_base.c but not from drivers/video/fbdev/aty/atyfb.h for respective callbacks. This resulted in error for implicit declaration for those callbacks. Fixes: 348b2956d5e6 ("fbdev: aty: use generic power management") Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200917115313.725622-1-vaibhavgupta40@gmail.com --- drivers/video/fbdev/aty/atyfb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbdev/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h index a7833bc98225f..551372f9b9aa2 100644 --- a/drivers/video/fbdev/aty/atyfb.h +++ b/drivers/video/fbdev/aty/atyfb.h @@ -287,8 +287,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par) #endif } -#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ -defined (CONFIG_FB_ATY_GENERIC_LCD) || defined (CONFIG_FB_ATY_BACKLIGHT) +#if defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) || \ +defined (CONFIG_FB_ATY_BACKLIGHT) extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); #endif -- GitLab From c7b360612fe7583350b0bb8ecec18abf1029695e Mon Sep 17 00:00:00 2001 From: Jing Xiangfeng <jingxiangfeng@huawei.com> Date: Fri, 18 Sep 2020 09:05:21 +0800 Subject: [PATCH 1329/1494] fbcon: Remove the superfluous break Remove the superfluous break, as there is a 'return' before it. Fixes: bad07ff74c32 ("fbcon: smart blitter usage for scrolling") Signed-off-by: Jing Xiangfeng <jingxiangfeng@huawei.com> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200918010521.69950-1-jingxiangfeng@huawei.com --- drivers/video/fbdev/core/fbcon.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 66167830fefd1..ae4de3bfd2d70 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1912,7 +1912,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, vc->vc_video_erase_char, vc->vc_size_row * count); return true; - break; case SCROLL_WRAP_MOVE: if (b - t - count > 3 * vc->vc_rows >> 2) { @@ -2003,7 +2002,6 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, vc->vc_video_erase_char, vc->vc_size_row * count); return true; - break; case SCROLL_WRAP_MOVE: if (b - t - count > 3 * vc->vc_rows >> 2) { -- GitLab From e491214613ffe52516df623d81e06e6999bbaaed Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 18 Sep 2020 10:31:14 +0800 Subject: [PATCH 1330/1494] drm/amd/pm: apply dummy reads workaround for CDR enabled only For CDR disabled case, the dummy reads workaround is not needed. Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index a027c7fdad56f..846c9c98e8b6a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2303,10 +2303,12 @@ static int navi10_run_umc_cdr_workaround(struct smu_context *smu) if (umc_fw_greater_than_v136) return 0; - if (umc_fw_disable_cdr && adev->asic_type == CHIP_NAVI10) - return navi10_umc_hybrid_cdr_workaround(smu); - else + if (umc_fw_disable_cdr) { + if (adev->asic_type == CHIP_NAVI10) + return navi10_umc_hybrid_cdr_workaround(smu); + } else { return navi10_set_dummy_pstates_table_location(smu); + } } else { if (adev->asic_type == CHIP_NAVI10) return navi10_umc_hybrid_cdr_workaround(smu); -- GitLab From 911d5bd5e7b8531b39301c2c27e5b90d7bd71b88 Mon Sep 17 00:00:00 2001 From: Jingwen Chen <Jingwen.Chen2@amd.com> Date: Thu, 17 Sep 2020 15:58:40 +0800 Subject: [PATCH 1331/1494] drm/amd/pm: Skip smu_post_init in SRIOV smu_post_init needs to enable SMU feature, while this require virtualization off. Skip it since this feature is not used in SRIOV. v2: move the check to the early stage of smu_post_init. v3: fix typo Signed-off-by: Jingwen Chen <Jingwen.Chen2@amd.com> Reviewed-by: Emily.Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 846c9c98e8b6a..985c70615944a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2633,6 +2633,9 @@ static int navi10_post_smu_init(struct smu_context *smu) uint64_t feature_mask = 0; int ret = 0; + if (amdgpu_sriov_vf(adev)) + return 0; + /* For Naiv1x, enable these features only after DAL initialization */ if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); -- GitLab From 55fd7dd29d679836a308d81c27c770b0a9c6a8d1 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Sat, 19 Sep 2020 10:17:53 -0700 Subject: [PATCH 1332/1494] drm/msm/dp: Fix crash if no DP device Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index db9e2761085bf..89b33b39087f5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -212,7 +212,8 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - msm_dp_debugfs_init(priv->dp, minor); + if (priv->dp) + msm_dp_debugfs_init(priv->dp, minor); return dpu_core_perf_debugfs_init(dpu_kms, entry); } -- GitLab From 710a040a4dd7ff0e0b8df007c885e7f916a7b099 Mon Sep 17 00:00:00 2001 From: Stephen Boyd <swboyd@chromium.org> Date: Thu, 17 Sep 2020 15:44:25 -0700 Subject: [PATCH 1333/1494] drm/msm/dp: Sleep properly in dp_hpd_handler kthread We shouldn't be waiting for an event here with a timeout of 100ms when we're not in the 'timeout' arm of the if condition. Instead we should be sleeping in the interruptible state (S) until something happens and we need to wakeup. Right now this kthread is running almost all the time because it sleeps for 100ms, wakes up, sees there's nothing to do, and then starts the process all over again. Looking at top it shows up in the D state (uninterruptible) because it uses wait_event_timeout(). FIx this up. Cc: Tanmay Shah <tanmay@codeaurora.org> Cc: Kuogee Hsieh <khsieh@codeaurora.org> Reported-by: Douglas Anderson <dianders@chromium.org> Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets") Signed-off-by: Stephen Boyd <swboyd@chromium.org> Reviewed-by: Kuogee Hsieh <khsieh@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_display.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 05a97e097edf3..e175aa3fd3a93 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -970,9 +970,8 @@ static int hpd_event_thread(void *data) (dp_priv->event_pndx == dp_priv->event_gndx), EVENT_TIMEOUT); } else { - wait_event_timeout(dp_priv->event_q, - (dp_priv->event_pndx != dp_priv->event_gndx), - EVENT_TIMEOUT); + wait_event_interruptible(dp_priv->event_q, + (dp_priv->event_pndx != dp_priv->event_gndx)); } spin_lock_irqsave(&dp_priv->event_lock, flag); todo = &dp_priv->event_list[dp_priv->event_gndx]; -- GitLab From e9ba8d550dd1e28870a0bdc7c11af026c2a94702 Mon Sep 17 00:00:00 2001 From: Jordan Crouse <jcrouse@codeaurora.org> Date: Tue, 15 Sep 2020 10:35:51 -0600 Subject: [PATCH 1334/1494] drm/msm: Fix the a650 hw_apriv check Commit 604234f33658 ("drm/msm: Enable expanded apriv support for a650") was checking the result of adreno_is_a650() before the gpu revision got probed in adreno_gpu_init() so it was always coming across as false. Snoop into the revision ID ahead of time to correctly set the hw_apriv flag so that it can be used by msm_gpu to properly setup global buffers. Fixes: 604234f33658 ("drm/msm: Enable expanded apriv support for a650") Reported-by: Jonathan Marek <jonathan@marek.ca> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Tested-by: Jonathan Marek <jonathan@marek.ca> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 3248c89aa0010..8915882e44449 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1182,6 +1182,8 @@ 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; + const struct adreno_info *info; struct device_node *node; struct a6xx_gpu *a6xx_gpu; struct adreno_gpu *adreno_gpu; @@ -1197,7 +1199,14 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = NULL; - if (adreno_is_a650(adreno_gpu)) + /* + * We need to know the platform type before calling into adreno_gpu_init + * so that the hw_apriv flag can be correctly set. Snoop into the info + * and grab the revision number + */ + info = adreno_info(config->rev); + + if (info && info->revn == 650) adreno_gpu->base.hw_apriv = true; ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); -- GitLab From ca9b38e6d671616e95bdf247cf5ded269e3f3fb9 Mon Sep 17 00:00:00 2001 From: Georgi Djakov <georgi.djakov@linaro.org> Date: Wed, 16 Sep 2020 14:07:06 +0300 Subject: [PATCH 1335/1494] drm/msm: Remove depends on interconnect The dependency on interconnect in the Kconfig was introduced to avoid the case of interconnect=m and driver=y, but the interconnect framework has been converted from tristate to bool now. Remove the dependency as the framework can't be a module anymore. Signed-off-by: Georgi Djakov <georgi.djakov@linaro.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 8c399bc9f3d4c..e5816b4984942 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -6,7 +6,6 @@ config DRM_MSM depends on ARCH_QCOM || SOC_IMX5 || (ARM && COMPILE_TEST) depends on OF && COMMON_CLK depends on MMU - depends on INTERCONNECT || !INTERCONNECT depends on QCOM_OCMEM || QCOM_OCMEM=n select IOMMU_IO_PGTABLE select QCOM_MDT_LOADER if ARCH_QCOM -- GitLab From 73bb394cb969ba11d612cc0bc05b375bd599a28c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski <krzk@kernel.org> Date: Wed, 26 Aug 2020 16:55:12 +0200 Subject: [PATCH 1336/1494] drm/exynos: dsi: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 1a1a2853a8429..5b9666fc7af1a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1760,11 +1760,8 @@ static int exynos_dsi_probe(struct platform_device *pdev) dsi->supplies[1].supply = "vddio"; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies), dsi->supplies); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_info(dev, "failed to get regulators: %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to get regulators\n"); dsi->clks = devm_kcalloc(dev, dsi->driver_data->num_clks, sizeof(*dsi->clks), -- GitLab From 231a474dd2b1fbd47671ca1f56fa221d9b0e72cb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski <krzk@kernel.org> Date: Wed, 26 Aug 2020 16:55:13 +0200 Subject: [PATCH 1337/1494] drm/exynos: hdmi: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and also it prints the error value. Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_hdmi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index c5ba32fca5f36..dc01c188c0e09 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1797,11 +1797,8 @@ static int hdmi_resources_init(struct hdmi_context *hdata) hdata->regul_bulk[i].supply = supply[i]; ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk); - if (ret) { - if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get regulators\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to get regulators\n"); hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en"); -- GitLab From 82be0d7540b1046d8950a180731b68371778f98e Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri, 18 Sep 2020 15:25:02 +0200 Subject: [PATCH 1338/1494] drm/i915/selftest: Create mock_destroy_device Just some prep work before we rework the lifetime handling, which requires replacing all the drm_dev_put in selftests by something else. v2: Don't go with a static inline, upsets the header tests and separation. Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200918132505.2316382-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c | 2 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 2 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- drivers/gpu/drm/i915/selftests/i915_vma.c | 2 +- drivers/gpu/drm/i915/selftests/intel_memory_region.c | 2 +- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 7 ++++++- drivers/gpu/drm/i915/selftests/mock_gem_device.h | 2 ++ 13 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 5daf4a2be422a..1f35e71429b47 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1617,7 +1617,7 @@ int i915_gem_huge_page_mock_selftests(void) out_put: i915_vm_put(&ppgtt->vm); out_unlock: - drm_dev_put(&dev_priv->drm); + mock_destroy_device(dev_priv); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 99becb86abd33..d3f87dc4eda38 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1997,7 +1997,7 @@ int i915_gem_context_mock_selftests(void) err = i915_subtests(tests, i915); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index 2a52b92586b9f..0845ce1ae37c1 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -272,7 +272,7 @@ int i915_gem_dmabuf_mock_selftests(void) err = i915_subtests(tests, i915); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c index faa5b6d917954..bf853c40ec65f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_object.c @@ -85,7 +85,7 @@ int i915_gem_object_mock_selftests(void) err = i915_subtests(tests, i915); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c index a94243dc4c5cf..8cee68c6a6dc8 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c @@ -73,6 +73,6 @@ int i915_gem_phys_mock_selftests(void) err = i915_subtests(tests, i915); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 96d164a3841dc..19c2cb166e7c2 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -158,7 +158,7 @@ static int mock_hwsp_freelist(void *arg) __mock_hwsp_record(&state, na, NULL); kfree(state.history); err_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 028baae9631f2..f88473d396f4b 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -536,7 +536,7 @@ int i915_gem_evict_mock_selftests(void) with_intel_runtime_pm(&i915->runtime_pm, wakeref) err = i915_subtests(tests, &i915->gt); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index af8205a2bd8fd..c53a222e3dece 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1727,7 +1727,7 @@ int i915_gem_gtt_mock_selftests(void) mock_fini_ggtt(ggtt); kfree(ggtt); out_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 3092ca763789c..64bbb82882494 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -527,7 +527,7 @@ int i915_request_mock_selftests(void) with_intel_runtime_pm(&i915->runtime_pm, wakeref) err = i915_subtests(tests, i915); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 88c5e9acb84c7..1b6125e4c1ac6 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -841,7 +841,7 @@ int i915_vma_mock_selftests(void) mock_fini_ggtt(ggtt); kfree(ggtt); out_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 93a38a3235843..334b0648e253e 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -791,7 +791,7 @@ int intel_memory_region_mock_selftests(void) intel_memory_region_put(mem); out_unref: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index f127e633f7ca8..fbb403edb7a00 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -224,7 +224,12 @@ struct drm_i915_private *mock_gem_device(void) intel_gt_driver_late_release(&i915->gt); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return NULL; } + +void mock_destroy_device(struct drm_i915_private *i915) +{ + drm_dev_put(&i915->drm); +} diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.h b/drivers/gpu/drm/i915/selftests/mock_gem_device.h index b5dc4e3945550..953cfe4fab34f 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.h +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.h @@ -7,4 +7,6 @@ struct drm_i915_private; struct drm_i915_private *mock_gem_device(void); void mock_device_flush(struct drm_i915_private *i915); +void mock_destroy_device(struct drm_i915_private *i915); + #endif /* !__MOCK_GEM_DEVICE_H__ */ -- GitLab From cd01269d11a352f06490a286227f3a50504248e5 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat, 19 Sep 2020 15:40:32 +0200 Subject: [PATCH 1339/1494] drm/i915/selftests: align more to real device lifetimes To avoid having to create all the device and driver scaffolding we just manually create and destroy a devres_group. v2: Rebased v3: use devres_open/release_group so we can use devm without real hacks in the driver core or having to create an entire fake bus for testing drivers. Might want to extract this into helpers eventually, maybe as a mock_drm_dev_alloc or test_drm_dev_alloc. v4: - Fix IS_ERR handling (Matt) - Delete surplus put_device() in mock_device_release (intel-gfx-ci) v5: - do not switch to device_add - it breaks runtime pm in the tests and with the devres_group_add/release no longer needed for automatic cleanup (CI). Update commit message to match. - print correct error in pr_err (Matt) v6: Remove now unused err variable (CI). v7: More warning fixes ... Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Matthew Auld <matthew.william.auld@gmail.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> (v3) Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Matthew Auld <matthew.william.auld@gmail.com> (v4) Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200919134032.2488403-1-daniel.vetter@ffwll.ch --- .../gpu/drm/i915/selftests/mock_gem_device.c | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index fbb403edb7a00..c207d22397916 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -79,8 +79,6 @@ static void mock_device_release(struct drm_device *dev) out: i915_params_free(&i915->params); - put_device(&i915->drm.pdev->dev); - i915->drm.pdev = NULL; } static struct drm_driver mock_driver = { @@ -123,17 +121,10 @@ struct drm_i915_private *mock_gem_device(void) #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) struct dev_iommu iommu; #endif - int err; pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); if (!pdev) return NULL; - i915 = kzalloc(sizeof(*i915), GFP_KERNEL); - if (!i915) { - kfree(pdev); - return NULL; - } - device_initialize(&pdev->dev); pdev->class = PCI_BASE_CLASS_DISPLAY << 16; pdev->dev.release = release_dev; @@ -146,8 +137,23 @@ struct drm_i915_private *mock_gem_device(void) iommu.priv = (void *)-1; pdev->dev.iommu = &iommu; #endif + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + put_device(&pdev->dev); + return NULL; + } + + i915 = devm_drm_dev_alloc(&pdev->dev, &mock_driver, + struct drm_i915_private, drm); + if (IS_ERR(i915)) { + pr_err("Failed to allocate mock GEM device: err=%ld\n", PTR_ERR(i915)); + devres_release_group(&pdev->dev, NULL); + put_device(&pdev->dev); + + return NULL; + } pci_set_drvdata(pdev, i915); + i915->drm.pdev = pdev; dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); @@ -155,16 +161,6 @@ struct drm_i915_private *mock_gem_device(void) if (pm_runtime_enabled(&pdev->dev)) WARN_ON(pm_runtime_get_sync(&pdev->dev)); - err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev); - if (err) { - pr_err("Failed to initialise mock GEM device: err=%d\n", err); - put_device(&pdev->dev); - kfree(i915); - - return NULL; - } - i915->drm.pdev = pdev; - drmm_add_final_kfree(&i915->drm, i915); i915_params_copy(&i915->params, &i915_modparams); @@ -231,5 +227,8 @@ struct drm_i915_private *mock_gem_device(void) void mock_destroy_device(struct drm_i915_private *i915) { - drm_dev_put(&i915->drm); + struct device *dev = i915->drm.dev; + + devres_release_group(dev, NULL); + put_device(dev); } -- GitLab From df2ce4596c04485fd77adcb18ec033d6c94da2dd Mon Sep 17 00:00:00 2001 From: Luben Tuikov <luben.tuikov@amd.com> Date: Fri, 18 Sep 2020 15:25:04 +0200 Subject: [PATCH 1340/1494] drm/amdgpu: Convert to using devm_drm_dev_alloc() (v2) Convert to using devm_drm_dev_alloc(), as drm_dev_init() is going away. v2: Remove drm_dev_put() since a) devres doesn't do refcounting, see Documentation/driver-api/driver-model/devres.rst, Section 4, paragraph 1; and since b) devres acts as garbage collector when the DRM device's parent's devres "action" callback is called to free the container device (amdgpu_device), which embeds the DRM dev. Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200918132505.2316382-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6edde2b9e4020..3ded6f43f9826 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1142,25 +1142,20 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, if (ret) return ret; - adev = kzalloc(sizeof(*adev), GFP_KERNEL); - if (!adev) - return -ENOMEM; + adev = devm_drm_dev_alloc(&pdev->dev, &kms_driver, typeof(*adev), ddev); + if (IS_ERR(adev)) + return PTR_ERR(adev); adev->dev = &pdev->dev; adev->pdev = pdev; ddev = adev_to_drm(adev); - ret = drm_dev_init(ddev, &kms_driver, &pdev->dev); - if (ret) - goto err_free; - - drmm_add_final_kfree(ddev, adev); if (!supports_atomic) ddev->driver_features &= ~DRIVER_ATOMIC; ret = pci_enable_device(pdev); if (ret) - goto err_free; + return ret; ddev->pdev = pdev; pci_set_drvdata(pdev, ddev); @@ -1188,8 +1183,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, err_pci: pci_disable_device(pdev); -err_free: - drm_dev_put(ddev); return ret; } @@ -1206,7 +1199,6 @@ amdgpu_pci_remove(struct pci_dev *pdev) amdgpu_driver_unload_kms(dev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - drm_dev_put(dev); } static void -- GitLab From a7d39439f8bd14b5becebc095aef3f1ec3191fe2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Fri, 18 Sep 2020 15:25:05 +0200 Subject: [PATCH 1341/1494] drm/dev: Remove drm_dev_init We can now also delete drm_dev_init, now that vkms, vgem and i915 selftests are resolved. Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200918132505.2316382-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_drv.c | 41 +++------------------------------- drivers/gpu/drm/drm_internal.h | 1 + drivers/gpu/drm/drm_managed.c | 13 ----------- include/drm/drm_drv.h | 4 ---- 4 files changed, 4 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3b70f91e4316a..cd162d406078a 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -573,43 +573,9 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) drm_legacy_destroy_members(dev); } -/** - * drm_dev_init - Initialise new DRM device - * @dev: DRM device - * @driver: DRM driver - * @parent: Parent device object - * - * Initialize a new DRM device. No device registration is done. - * Call drm_dev_register() to advertice the device to user space and register it - * with other core subsystems. This should be done last in the device - * initialization sequence to make sure userspace can't access an inconsistent - * state. - * - * The initial ref-count of the object is 1. Use drm_dev_get() and - * drm_dev_put() to take and drop further ref-counts. - * - * It is recommended that drivers embed &struct drm_device into their own device - * structure. - * - * Drivers that do not want to allocate their own device struct - * embedding &struct drm_device can call drm_dev_alloc() instead. For drivers - * that do embed &struct drm_device it must be placed first in the overall - * structure, and the overall structure must be allocated using kmalloc(): The - * drm core's release function unconditionally calls kfree() on the @dev pointer - * when the final reference is released. To override this behaviour, and so - * allow embedding of the drm_device inside the driver's device struct at an - * arbitrary offset, you must supply a &drm_driver.release callback and control - * the finalization explicitly. - * - * Note that drivers must call drmm_add_final_kfree() after this function has - * completed successfully. - * - * RETURNS: - * 0 on success, or error code on failure. - */ -int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent) +static int drm_dev_init(struct drm_device *dev, + struct drm_driver *driver, + struct device *parent) { int ret; @@ -689,7 +655,6 @@ int drm_dev_init(struct drm_device *dev, return ret; } -EXPORT_SYMBOL(drm_dev_init); static void devm_drm_dev_init_release(void *data) { diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 8e01caaf95cc4..b65865c630b0a 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -95,6 +95,7 @@ void drm_minor_release(struct drm_minor *minor); /* drm_managed.c */ void drm_managed_release(struct drm_device *dev); +void drmm_add_final_kfree(struct drm_device *dev, void *container); /* drm_vblank.c */ static inline bool drm_vblank_passed(u64 seq, u64 ref) diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index c36e3d98fd713..37d7db6223be6 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -125,18 +125,6 @@ static void add_dr(struct drm_device *dev, struct drmres *dr) dr, dr->node.name, (unsigned long) dr->node.size); } -/** - * drmm_add_final_kfree - add release action for the final kfree() - * @dev: DRM device - * @container: pointer to the kmalloc allocation containing @dev - * - * Since the allocation containing the struct &drm_device must be allocated - * before it can be initialized with drm_dev_init() there's no way to allocate - * that memory with drmm_kmalloc(). To side-step this chicken-egg problem the - * pointer for this final kfree() must be specified by calling this function. It - * will be released in the final drm_dev_put() for @dev, after all other release - * actions installed through drmm_add_action() have been processed. - */ void drmm_add_final_kfree(struct drm_device *dev, void *container) { WARN_ON(dev->managed.final_kfree); @@ -144,7 +132,6 @@ void drmm_add_final_kfree(struct drm_device *dev, void *container) WARN_ON(dev + 1 > (struct drm_device *) (container + ksize(container))); dev->managed.final_kfree = container; } -EXPORT_SYMBOL(drmm_add_final_kfree); int __drmm_add_action(struct drm_device *dev, drmres_release_t action, diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 9b11a2f0babc0..e57d0440f00f6 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -588,10 +588,6 @@ struct drm_driver { int dev_priv_size; }; -int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent); - void *__devm_drm_dev_alloc(struct device *parent, struct drm_driver *driver, size_t size, size_t offset); -- GitLab From 91e89097b86f566636ea5a7329c79d5521be46d2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong <narmstrong@baylibre.com> Date: Wed, 16 Sep 2020 17:01:45 +0200 Subject: [PATCH 1342/1494] drm/panfrost: add support for vendor quirk The T820, G31 & G52 GPUs integrated by Amlogic in the respective GXM, G12A/SM1 & G12B SoCs needs a quirk in the PWR registers after each reset. This adds a callback in the device compatible struct of permit this. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> [Steven: Fix typo in commit log] Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916150147.25753-2-narmstrong@baylibre.com --- drivers/gpu/drm/panfrost/panfrost_device.h | 3 +++ drivers/gpu/drm/panfrost/panfrost_gpu.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index 953f7536a773f..2e9cbd1c4a58e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -70,6 +70,9 @@ struct panfrost_compatible { int num_pm_domains; /* Only required if num_pm_domains > 1. */ const char * const *pm_domain_names; + + /* Vendor implementation quirks callback */ + void (*vendor_quirk)(struct panfrost_device *pfdev); }; struct panfrost_device { diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index c7c5da5a31d47..a6de78bc1fa86 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -136,6 +136,10 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) if (quirks) gpu_write(pfdev, GPU_JM_CONFIG, quirks); + + /* Here goes platform specific quirks */ + if (pfdev->comp->vendor_quirk) + pfdev->comp->vendor_quirk(pfdev); } #define MAX_HW_REVS 6 -- GitLab From 110003002291525bb209f47e6dbf121a63249a97 Mon Sep 17 00:00:00 2001 From: Neil Armstrong <narmstrong@baylibre.com> Date: Wed, 16 Sep 2020 17:01:46 +0200 Subject: [PATCH 1343/1494] drm/panfrost: add amlogic reset quirk callback The T820, G31 & G52 GPUs integrated by Amlogic in the respective GXM, G12A/SM1 & G12B SoCs needs a quirk in the PWR registers at the GPU reset time. Since the Amlogic's integration of the GPU cores with the SoC is not publicly documented we do not know what does these values, but they permit having a fully functional GPU running with Panfrost. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> [Steven: Fix typo in commit log] Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916150147.25753-3-narmstrong@baylibre.com --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 11 +++++++++++ drivers/gpu/drm/panfrost/panfrost_gpu.h | 2 ++ drivers/gpu/drm/panfrost/panfrost_regs.h | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index a6de78bc1fa86..e1b2a3376624a 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -76,6 +76,17 @@ int panfrost_gpu_soft_reset(struct panfrost_device *pfdev) return 0; } +void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev) +{ + /* + * The Amlogic integrated Mali-T820, Mali-G31 & Mali-G52 needs + * these undocumented bits in GPU_PWR_OVERRIDE1 to be set in order + * to operate correctly. + */ + gpu_write(pfdev, GPU_PWR_KEY, GPU_PWR_KEY_UNLOCK); + gpu_write(pfdev, GPU_PWR_OVERRIDE1, 0xfff | (0x20 << 16)); +} + static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) { u32 quirks = 0; diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.h b/drivers/gpu/drm/panfrost/panfrost_gpu.h index 4112412087b27..468c51e7e46db 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.h +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.h @@ -16,4 +16,6 @@ int panfrost_gpu_soft_reset(struct panfrost_device *pfdev); void panfrost_gpu_power_on(struct panfrost_device *pfdev); void panfrost_gpu_power_off(struct panfrost_device *pfdev); +void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev); + #endif diff --git a/drivers/gpu/drm/panfrost/panfrost_regs.h b/drivers/gpu/drm/panfrost/panfrost_regs.h index ea38ac60581c6..eddaa62ad8b0e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_regs.h +++ b/drivers/gpu/drm/panfrost/panfrost_regs.h @@ -51,6 +51,10 @@ #define GPU_STATUS 0x34 #define GPU_STATUS_PRFCNT_ACTIVE BIT(2) #define GPU_LATEST_FLUSH_ID 0x38 +#define GPU_PWR_KEY 0x50 /* (WO) Power manager key register */ +#define GPU_PWR_KEY_UNLOCK 0x2968A819 +#define GPU_PWR_OVERRIDE0 0x54 /* (RW) Power manager override settings */ +#define GPU_PWR_OVERRIDE1 0x58 /* (RW) Power manager override settings */ #define GPU_FAULT_STATUS 0x3C #define GPU_FAULT_ADDRESS_LO 0x40 #define GPU_FAULT_ADDRESS_HI 0x44 -- GitLab From afcd0c7d3d4c22afc8befcfc906db6ce3058d3ee Mon Sep 17 00:00:00 2001 From: Neil Armstrong <narmstrong@baylibre.com> Date: Wed, 16 Sep 2020 17:01:47 +0200 Subject: [PATCH 1344/1494] drm/panfrost: add Amlogic GPU integration quirks This adds the required GPU quirks, including the quirk in the PWR registers at the GPU reset time and the IOMMU quirk for shareability issues observed on G52 in Amlogic G12B SoCs. Signed-off-by: Neil Armstrong <narmstrong@baylibre.com> Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916150147.25753-4-narmstrong@baylibre.com --- drivers/gpu/drm/panfrost/panfrost_drv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 36463c89e9669..37d4cb7a5491c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -656,7 +656,18 @@ static const struct panfrost_compatible default_data = { .pm_domain_names = NULL, }; +static const struct panfrost_compatible amlogic_data = { + .num_supplies = ARRAY_SIZE(default_supplies), + .supply_names = default_supplies, + .vendor_quirk = panfrost_gpu_amlogic_quirk, +}; + static const struct of_device_id dt_match[] = { + /* Set first to probe before the generic compatibles */ + { .compatible = "amlogic,meson-gxm-mali", + .data = &amlogic_data, }, + { .compatible = "amlogic,meson-g12a-mali", + .data = &amlogic_data, }, { .compatible = "arm,mali-t604", .data = &default_data, }, { .compatible = "arm,mali-t624", .data = &default_data, }, { .compatible = "arm,mali-t628", .data = &default_data, }, -- GitLab From 92fdb97d648a0120bc342342d199f5be119cfd67 Mon Sep 17 00:00:00 2001 From: Tian Tao <tiantao6@hisilicon.com> Date: Fri, 18 Sep 2020 17:52:58 +0800 Subject: [PATCH 1345/1494] drm/ttm: update kernel-doc line comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update kernel-doc line comments to fix warnings reported by make W=1. drivers/gpu/drm/ttm/ttm_memory.c:271: warning: Function parameter or member 'glob' not described in 'ttm_shrink' drivers/gpu/drm/ttm/ttm_memory.c:271: warning: Function parameter or member 'from_wq' not described in 'ttm_shrink' drivers/gpu/drm/ttm/ttm_memory.c:271: warning: Function parameter or member 'extra' not described in 'ttm_shrink' drivers/gpu/drm/ttm/ttm_memory.c:271: warning: Function parameter or member 'ctx' not described in 'ttm_shrink' Signed-off-by: Tian Tao <tiantao6@hisilicon.com> Reviewed-by: Christian König <christian.koenig@amd.com> Acked-by: Huang Rui <ray.huang@amd.com> Link: https://patchwork.freedesktop.org/patch/391317/ Signed-off-by: Christian König <christian.koenig@amd.com> --- drivers/gpu/drm/ttm/ttm_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index 987aa32c48086..89d50f38c0f2c 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -259,7 +259,7 @@ static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob, return false; } -/** +/* * At this point we only support a single shrink callback. * Extend this if needed, perhaps using a linked list of callbacks. * Note that this function is reentrant: -- GitLab From 089d83418914abd4d908db117d9a3eca7f51a68c Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Thu, 17 Sep 2020 14:16:23 +0200 Subject: [PATCH 1346/1494] drm/vc4: hvs: Pull the state of all the CRTCs prior to PV muxing The vc4 display engine has a first controller called the HVS that will perform the composition of the planes. That HVS has 3 FIFOs and can therefore compose planes for up to three outputs. The timings part is generated through a component called the Pixel Valve, and the BCM2711 has 6 of them. Thus, the HVS has some bits to control which FIFO gets output to which Pixel Valve. The current code supports that muxing by looking at all the CRTCs in a new DRM atomic state in atomic_check, and given the set of constraints that we have, assigns FIFOs to CRTCs or reject the mode entirely. The actual muxing will occur during atomic_commit. However, that doesn't work if only a fraction of the CRTCs' state is updated in that state, since it will ignore the CRTCs that are kept running unmodified, and will thus unassign its associated FIFO, and later disable it. In order to make the code work as expected, let's pull the CRTC state of all the enabled CRTC in our atomic_check so that we can operate on all the running CRTCs, no matter whether they are affected by the new state or not. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Reviewed-by: Hoegeun Kwon <hoegeun.kwon@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200917121623.42023-1-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_kms.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 16e233e1406e9..af3ee3dcdab61 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -620,6 +620,23 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) struct drm_crtc *crtc; int i, ret; + /* + * Since the HVS FIFOs are shared across all the pixelvalves and + * the TXP (and thus all the CRTCs), we need to pull the current + * state of all the enabled CRTCs so that an update to a single + * CRTC still keeps the previous FIFOs enabled and assigned to + * the same CRTCs, instead of evaluating only the CRTC being + * modified. + */ + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (!crtc->state->enable) + continue; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + } + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc_state); -- GitLab From ddfd4ab6bb08832e1261d7c8c4ae11e5568485af Mon Sep 17 00:00:00 2001 From: Marek Szyprowski <m.szyprowski@samsung.com> Date: Tue, 7 Jul 2020 13:08:27 +0200 Subject: [PATCH 1347/1494] drm/exynos: Fix dma_parms allocation Since commit 9495b7e92f71 ("driver core: platform: Initialize dma_parms for platform devices") driver core handles allocation of the dma_parms structure for platform device, so there is no need to manually allocate nor free it. Reported-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com> --- drivers/gpu/drm/exynos/exynos_drm_dma.c | 27 +------------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c b/drivers/gpu/drm/exynos/exynos_drm_dma.c index 58b89ec11b0eb..5887f7f52f96e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dma.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c @@ -31,23 +31,6 @@ #define EXYNOS_DEV_ADDR_START 0x20000000 #define EXYNOS_DEV_ADDR_SIZE 0x40000000 -static inline int configure_dma_max_seg_size(struct device *dev) -{ - if (!dev->dma_parms) - dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL); - if (!dev->dma_parms) - return -ENOMEM; - - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); - return 0; -} - -static inline void clear_dma_max_seg_size(struct device *dev) -{ - kfree(dev->dma_parms); - dev->dma_parms = NULL; -} - /* * drm_iommu_attach_device- attach device to iommu mapping * @@ -69,10 +52,7 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev, return -EINVAL; } - ret = configure_dma_max_seg_size(subdrv_dev); - if (ret) - return ret; - + dma_set_max_seg_size(subdrv_dev, DMA_BIT_MASK(32)); if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { /* * Keep the original DMA mapping of the sub-device and @@ -89,9 +69,6 @@ static int drm_iommu_attach_device(struct drm_device *drm_dev, ret = iommu_attach_device(priv->mapping, subdrv_dev); } - if (ret) - clear_dma_max_seg_size(subdrv_dev); - return ret; } @@ -114,8 +91,6 @@ static void drm_iommu_detach_device(struct drm_device *drm_dev, arm_iommu_attach_device(subdrv_dev, *dma_priv); } else if (IS_ENABLED(CONFIG_IOMMU_DMA)) iommu_detach_device(priv->mapping, subdrv_dev); - - clear_dma_max_seg_size(subdrv_dev); } int exynos_drm_register_dma(struct drm_device *drm, struct device *dev, -- GitLab From 2cd9df2be75766452fef87c37ec37d91f4cbaf6b Mon Sep 17 00:00:00 2001 From: Biju Das <biju.das.jz@bp.renesas.com> Date: Mon, 10 Aug 2020 16:22:17 +0100 Subject: [PATCH 1348/1494] dt-bindings: display: bridge: lvds-codec: Document power-supply property Document optional power-supply property that may be used to specify the regulator powering up the device. Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/lvds-codec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index 68951d56ebba9..ff3ae25f8b23e 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -79,6 +79,9 @@ properties: The GPIO used to control the power down line of this device. maxItems: 1 + power-supply: + maxItems: 1 + required: - compatible - ports -- GitLab From 946a61ab2d758cc645f6e63f1a5e2731690c3943 Mon Sep 17 00:00:00 2001 From: Biju Das <biju.das.jz@bp.renesas.com> Date: Mon, 10 Aug 2020 16:22:18 +0100 Subject: [PATCH 1349/1494] drm/bridge: lvds-codec: Add support for regulator Add the support for enabling optional regulator that may be used as VCC source. Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> [Replaced 'error' variable with 'ret'] [Renamed regulator from 'vcc' to 'power'] Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> --- drivers/gpu/drm/bridge/lvds-codec.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index f19d9f7a5db24..f52ccffc1bd1d 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -10,13 +10,16 @@ #include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #include <drm/drm_bridge.h> #include <drm/drm_panel.h> struct lvds_codec { + struct device *dev; struct drm_bridge bridge; struct drm_bridge *panel_bridge; + struct regulator *vcc; struct gpio_desc *powerdown_gpio; u32 connector_type; }; @@ -38,6 +41,14 @@ static int lvds_codec_attach(struct drm_bridge *bridge, static void lvds_codec_enable(struct drm_bridge *bridge) { struct lvds_codec *lvds_codec = to_lvds_codec(bridge); + int ret; + + ret = regulator_enable(lvds_codec->vcc); + if (ret) { + dev_err(lvds_codec->dev, + "Failed to enable regulator \"vcc\": %d\n", ret); + return; + } if (lvds_codec->powerdown_gpio) gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0); @@ -46,9 +57,15 @@ static void lvds_codec_enable(struct drm_bridge *bridge) static void lvds_codec_disable(struct drm_bridge *bridge) { struct lvds_codec *lvds_codec = to_lvds_codec(bridge); + int ret; if (lvds_codec->powerdown_gpio) gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1); + + ret = regulator_disable(lvds_codec->vcc); + if (ret) + dev_err(lvds_codec->dev, + "Failed to disable regulator \"vcc\": %d\n", ret); } static const struct drm_bridge_funcs funcs = { @@ -63,12 +80,24 @@ static int lvds_codec_probe(struct platform_device *pdev) struct device_node *panel_node; struct drm_panel *panel; struct lvds_codec *lvds_codec; + int ret; lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); if (!lvds_codec) return -ENOMEM; + lvds_codec->dev = &pdev->dev; lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev); + + lvds_codec->vcc = devm_regulator_get(lvds_codec->dev, "power"); + if (IS_ERR(lvds_codec->vcc)) { + ret = PTR_ERR(lvds_codec->vcc); + if (ret != -EPROBE_DEFER) + dev_err(lvds_codec->dev, + "Unable to get \"vcc\" supply: %d\n", ret); + return ret; + } + lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); if (IS_ERR(lvds_codec->powerdown_gpio)) -- GitLab From 4b6f2b971e8d142474b7ab7e6d3c23e38d83057f Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Date: Wed, 12 Aug 2020 15:02:09 +0100 Subject: [PATCH 1350/1494] dt-bindings: display: renesas,du: Document r8a774e1 bindings Document the RZ/G2H (a.k.a. r8a774e1) SoC in the R-Car DU bindings. Signed-off-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 3f1e3ca4bea9a..0a14f944180d3 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -11,6 +11,7 @@ Required Properties: - "renesas,du-r8a774a1" for R8A774A1 (RZ/G2M) compatible DU - "renesas,du-r8a774b1" for R8A774B1 (RZ/G2N) compatible DU - "renesas,du-r8a774c0" for R8A774C0 (RZ/G2E) compatible DU + - "renesas,du-r8a774e1" for R8A774E1 (RZ/G2H) compatible DU - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU @@ -77,6 +78,7 @@ corresponding to each DU output. R8A774A1 (RZ/G2M) DPAD 0 HDMI 0 LVDS 0 - R8A774B1 (RZ/G2N) DPAD 0 HDMI 0 LVDS 0 - R8A774C0 (RZ/G2E) DPAD 0 LVDS 0 LVDS 1 - + R8A774E1 (RZ/G2H) DPAD 0 HDMI 0 LVDS 0 - R8A7779 (R-Car H1) DPAD 0 DPAD 1 - - R8A7790 (R-Car H2) DPAD 0 LVDS 0 LVDS 1 - R8A7791 (R-Car M2-W) DPAD 0 LVDS 0 - - -- GitLab From 31057d444d41ea820a5c61126e2c810a80a16e79 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Date: Wed, 12 Aug 2020 15:02:10 +0100 Subject: [PATCH 1351/1494] drm: rcar-du: Add support for R8A774E1 SoC Hookup RZ/G2H (R8A774E1) to DU driver. R8A774E1 has one RGB output, one LVDS output and one HDMI output. Signed-off-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0f870c282455c..0e3dd5d8d5c37 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -186,6 +186,35 @@ static const struct rcar_du_device_info rcar_du_r8a774c0_info = { .lvds_clk_mask = BIT(1) | BIT(0), }; +static const struct rcar_du_device_info rcar_du_r8a774e1_info = { + .gen = 3, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + | RCAR_DU_FEATURE_VSP1_SOURCE + | RCAR_DU_FEATURE_INTERLACED + | RCAR_DU_FEATURE_TVM_SYNC, + .channels_mask = BIT(3) | BIT(1) | BIT(0), + .routes = { + /* + * R8A774E1 has one RGB output, one LVDS output and one HDMI + * output. + */ + [RCAR_DU_OUTPUT_DPAD0] = { + .possible_crtcs = BIT(2), + .port = 0, + }, + [RCAR_DU_OUTPUT_HDMI0] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + [RCAR_DU_OUTPUT_LVDS0] = { + .possible_crtcs = BIT(0), + .port = 2, + }, + }, + .num_lvds = 1, + .dpll_mask = BIT(1), +}; + static const struct rcar_du_device_info rcar_du_r8a7779_info = { .gen = 1, .features = RCAR_DU_FEATURE_INTERLACED @@ -452,6 +481,7 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info }, { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info }, { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info }, + { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info }, { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info }, -- GitLab From 45d6ec79dd42258ada43fedf3bb00c04ae7c17eb Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Date: Wed, 12 Aug 2020 15:02:12 +0100 Subject: [PATCH 1352/1494] dt-bindings: display: renesas,lvds: Document r8a774e1 bindings Document the RZ/G2H (R8A774E1) LVDS bindings. Signed-off-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/renesas,lvds.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml index bf3dee252c1aa..e5b163951b919 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml @@ -22,6 +22,7 @@ properties: - renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders - renesas,r8a774b1-lvds # for RZ/G2N compatible LVDS encoders - renesas,r8a774c0-lvds # for RZ/G2E compatible LVDS encoders + - renesas,r8a774e1-lvds # for RZ/G2H compatible LVDS encoders - renesas,r8a7790-lvds # for R-Car H2 compatible LVDS encoders - renesas,r8a7791-lvds # for R-Car M2-W compatible LVDS encoders - renesas,r8a7793-lvds # for R-Car M2-N compatible LVDS encoders -- GitLab From 0c905a0a30d16c43efc381a29f509fbff606b91d Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Date: Wed, 12 Aug 2020 15:02:13 +0100 Subject: [PATCH 1353/1494] dt-bindings: display: renesas,dw-hdmi: Add r8a774e1 support Document RZ/G2H (R8A774E1) SoC bindings. Signed-off-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index 819f3e31013c7..f275997ab947f 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -14,6 +14,7 @@ Required properties: - compatible : Shall contain one or more of - "renesas,r8a774a1-hdmi" for R8A774A1 (RZ/G2M) compatible HDMI TX - "renesas,r8a774b1-hdmi" for R8A774B1 (RZ/G2N) compatible HDMI TX + - "renesas,r8a774e1-hdmi" for R8A774E1 (RZ/G2H) compatible HDMI TX - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX - "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX - "renesas,r8a77965-hdmi" for R8A77965 (R-Car M3-N) compatible HDMI TX -- GitLab From 6d981d276110c7d6e866179db4bb1c6cbfcd1819 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Date: Wed, 12 Aug 2020 15:02:15 +0100 Subject: [PATCH 1354/1494] drm: rcar-du: lvds: Add support for R8A774E1 SoC The LVDS encoder on RZ/G2H (R8A774E1) SoC is identical to R-Car Gen3 so just reuse the rcar_lvds_gen3_info structure to hookup R8A774E1 to LVDS encoder driver. Signed-off-by: Marian-Cristian Rotariu <marian-cristian.rotariu.rb@bp.renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index dc386e3a763c3..70dbbe44bb23d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -984,6 +984,7 @@ static const struct of_device_id rcar_lvds_of_table[] = { { .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a774b1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info }, + { .compatible = "renesas,r8a774e1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info }, -- GitLab From 542d9a658eebac0e6054a5734cb1f893778a43f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Tue, 8 Sep 2020 09:34:04 +0900 Subject: [PATCH 1355/1494] dt-bindings: display: renesas: du: Document the r8a77961 bindings Document the R-Car M3-W+ (R8A77961) SoC in the R-Car DU bindings. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 0a14f944180d3..7d65c24fcda87 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -20,6 +20,7 @@ Required Properties: - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU + - "renesas,du-r8a77961" for R8A77961 (R-Car M3-W+) compatible DU - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU @@ -87,6 +88,7 @@ corresponding to each DU output. R8A7794 (R-Car E2) DPAD 0 DPAD 1 - - R8A7795 (R-Car H3) DPAD 0 HDMI 0 HDMI 1 LVDS 0 R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 - + R8A77961 (R-Car M3-W+) DPAD 0 HDMI 0 LVDS 0 - R8A77965 (R-Car M3-N) DPAD 0 HDMI 0 LVDS 0 - R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - - R8A77980 (R-Car V3H) DPAD 0 LVDS 0 - - -- GitLab From 0356f0fbc53d7d787e4d827ed06241ce9df1fbfc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Tue, 8 Sep 2020 09:34:11 +0900 Subject: [PATCH 1356/1494] dt-bindings: display: renesas: dw-hdmi: Tidyup example compatible The DT example erronously uses the "renesas,r8a7795-dw-hdmi", when the correct value is "renesas,r8a7795-hdmi". It is furthermore missing the generic "renesas,rcar-gen3-hdmi" compatible string. Fix it. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> [Add "renesas,rcar-gen3-hdmi" and rework commit message] Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index f275997ab947f..9c56c5169a882 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -43,7 +43,7 @@ Optional properties: Example: hdmi0: hdmi@fead0000 { - compatible = "renesas,r8a7795-dw-hdmi"; + compatible = "renesas,r8a7795-hdmi", "renesas,rcar-gen3-hdmi"; reg = <0 0xfead0000 0 0x10000>; interrupts = <0 389 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>; -- GitLab From 460941cd6923fdfe731d12ca97a433bc4c2f0afb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Tue, 8 Sep 2020 09:34:17 +0900 Subject: [PATCH 1357/1494] dt-bindings: display: renesas: dw-hdmi: Add R8A77961 support This patch adds R-Car M3-W+ (R8A77961) SoC bindings. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index 9c56c5169a882..3f60726511828 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -17,6 +17,7 @@ Required properties: - "renesas,r8a774e1-hdmi" for R8A774E1 (RZ/G2H) compatible HDMI TX - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX - "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX + - "renesas,r8a77961-hdmi" for R8A77961 (R-Car M3-W+) compatible HDMI TX - "renesas,r8a77965-hdmi" for R8A77965 (R-Car M3-N) compatible HDMI TX - "renesas,rcar-gen3-hdmi" for the generic R-Car Gen3 and RZ/G2 compatible HDMI TX -- GitLab From ef84ad32f41c2b84560ca3577fb0cb85dd4895fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Tue, 8 Sep 2020 09:34:32 +0900 Subject: [PATCH 1358/1494] drm: rcar-du: Add r8a77961 support This patch adds R-Car M3-W+ (R8A77961) support which is compatible with the R-Car M3-W (R8A77960). Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0e3dd5d8d5c37..447be991fa25c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -490,6 +490,7 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info }, { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info }, -- GitLab From dc86d6bc9bc3d0080bd18b54777a22b70eae4aa6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Date: Thu, 6 Aug 2020 05:24:34 +0300 Subject: [PATCH 1359/1494] drm: rcar-du: Fix pitch handling for fully planar YUV formats When creating a frame buffer, the driver verifies that the pitches for the chroma planes match the luma plane. This is done incorrectly for fully planar YUV formats, without taking horizontal subsampling into account. Fix it. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 54 ++++++++++++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_kms.h | 1 + 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 482329102f192..72dda446355fe 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -40,6 +40,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_RGB565, .bpp = 16, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_NONE, }, { @@ -47,6 +48,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_ARGB555, .bpp = 16, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB, .edf = PnDDCR4_EDF_NONE, }, { @@ -61,6 +63,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_XBGR32, .bpp = 32, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_RGB888, }, { @@ -68,6 +71,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_ABGR32, .bpp = 32, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_ARGB8888, }, { @@ -75,6 +79,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_UYVY, .bpp = 16, .planes = 1, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -82,6 +87,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_YUYV, .bpp = 16, .planes = 1, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -89,6 +95,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV12M, .bpp = 12, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -96,6 +103,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV21M, .bpp = 12, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -103,6 +111,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV16M, .bpp = 16, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, @@ -115,156 +124,187 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_RGB332, .bpp = 8, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ARGB4444, .v4l2 = V4L2_PIX_FMT_ARGB444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XRGB4444, .v4l2 = V4L2_PIX_FMT_XRGB444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA4444, .v4l2 = V4L2_PIX_FMT_RGBA444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX4444, .v4l2 = V4L2_PIX_FMT_RGBX444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR4444, .v4l2 = V4L2_PIX_FMT_ABGR444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR4444, .v4l2 = V4L2_PIX_FMT_XBGR444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA4444, .v4l2 = V4L2_PIX_FMT_BGRA444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX4444, .v4l2 = V4L2_PIX_FMT_BGRX444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA5551, .v4l2 = V4L2_PIX_FMT_RGBA555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX5551, .v4l2 = V4L2_PIX_FMT_RGBX555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR1555, .v4l2 = V4L2_PIX_FMT_ABGR555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR1555, .v4l2 = V4L2_PIX_FMT_XBGR555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA5551, .v4l2 = V4L2_PIX_FMT_BGRA555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX5551, .v4l2 = V4L2_PIX_FMT_BGRX555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGR888, .v4l2 = V4L2_PIX_FMT_RGB24, .bpp = 24, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGB888, .v4l2 = V4L2_PIX_FMT_BGR24, .bpp = 24, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA8888, .v4l2 = V4L2_PIX_FMT_BGRA32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX8888, .v4l2 = V4L2_PIX_FMT_BGRX32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR8888, .v4l2 = V4L2_PIX_FMT_RGBA32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR8888, .v4l2 = V4L2_PIX_FMT_RGBX32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA8888, .v4l2 = V4L2_PIX_FMT_ARGB32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX8888, .v4l2 = V4L2_PIX_FMT_XRGB32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_YVYU, .v4l2 = V4L2_PIX_FMT_YVYU, .bpp = 16, .planes = 1, + .hsub = 2, }, { .fourcc = DRM_FORMAT_NV61, .v4l2 = V4L2_PIX_FMT_NV61M, .bpp = 16, .planes = 2, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV420, .v4l2 = V4L2_PIX_FMT_YUV420M, .bpp = 12, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YVU420, .v4l2 = V4L2_PIX_FMT_YVU420M, .bpp = 12, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV422, .v4l2 = V4L2_PIX_FMT_YUV422M, .bpp = 16, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YVU422, .v4l2 = V4L2_PIX_FMT_YVU422M, .bpp = 16, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV444, .v4l2 = V4L2_PIX_FMT_YUV444M, .bpp = 24, .planes = 3, + .hsub = 1, }, { .fourcc = DRM_FORMAT_YVU444, .v4l2 = V4L2_PIX_FMT_YVU444M, .bpp = 24, .planes = 3, + .hsub = 1, }, }; @@ -311,6 +351,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, { struct rcar_du_device *rcdu = dev->dev_private; const struct rcar_du_format_info *format; + unsigned int chroma_pitch; unsigned int max_pitch; unsigned int align; unsigned int i; @@ -353,10 +394,19 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-EINVAL); } + /* + * Calculate the chroma plane(s) pitch using the horizontal subsampling + * factor. For semi-planar formats, the U and V planes are combined, the + * pitch must thus be doubled. + */ + chroma_pitch = mode_cmd->pitches[0] / format->hsub; + if (format->planes == 2) + chroma_pitch *= 2; + for (i = 1; i < format->planes; ++i) { - if (mode_cmd->pitches[i] != mode_cmd->pitches[0]) { + if (mode_cmd->pitches[i] != chroma_pitch) { dev_dbg(dev->dev, - "luma and chroma pitches do not match\n"); + "luma and chroma pitches are not compatible\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.h b/drivers/gpu/drm/rcar-du/rcar_du_kms.h index 0346504d8c59f..8f5fff176754b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.h @@ -22,6 +22,7 @@ struct rcar_du_format_info { u32 v4l2; unsigned int bpp; unsigned int planes; + unsigned int hsub; unsigned int pnmr; unsigned int edf; }; -- GitLab From f4dfa76d73f76eb0b0016d8ebacebb85db743018 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Date: Sat, 8 Aug 2020 00:07:21 +0300 Subject: [PATCH 1360/1494] drm: rcar-du: Fix crash when enabling a non-visible plane The DU driver handles non-visible planes (fully clipped by the display's boundaries) by considering them as disabled. It thus disables the plane at the hardware level when the plane is moved off-screen. However, if the plane was previously disabled and is non-visible when it gets enabled, the attempt to disable it crashes, as the plane wasn't previously enabled. Fix it. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index f1a81c9b184d4..ff233a7b398d3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -279,7 +279,7 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane, if (plane->state->visible) rcar_du_vsp_plane_setup(rplane); - else + else if (old_state->crtc) vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe, rplane->index, NULL); } -- GitLab From 709b66b4b745bca5324941cd4d7a34ffeba87cf0 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Date: Fri, 11 Sep 2020 11:07:41 +0100 Subject: [PATCH 1361/1494] drm: rcar-du: Update description for DRM_RCAR_DW_HDMI Kconfig entry The rcar_dw_hdmi driver is also used on Renesas RZ/G2 SoCs. Update the Kconfig entry description to reflect this. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Chris Paterson <Chris.Paterson2@renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 49b590aa69be1..b47e74421e347 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -22,11 +22,11 @@ config DRM_RCAR_CMM Enable support for R-Car Color Management Module (CMM). config DRM_RCAR_DW_HDMI - tristate "R-Car DU Gen3 HDMI Encoder Support" + tristate "R-Car Gen3 and RZ/G2 DU HDMI Encoder Support" depends on DRM && OF select DRM_DW_HDMI help - Enable support for R-Car Gen3 internal HDMI encoder. + Enable support for R-Car Gen3 or RZ/G2 internal HDMI encoder. config DRM_RCAR_LVDS tristate "R-Car DU LVDS Encoder Support" -- GitLab From 2a32dbdc2c7db5463483fa01fb220fd1b770c6bc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Date: Wed, 16 Sep 2020 02:23:47 +0300 Subject: [PATCH 1362/1494] drm: rcar-du: Put reference to VSP device The reference to the VSP device acquired with of_find_device_by_node() in rcar_du_vsp_init() is never released. Fix it with a drmm action, which gets run both in the probe error path and in the remove path. Fixes: 6d62ef3ac30b ("drm: rcar-du: Expose the VSP1 compositor through KMS planes") Reported-by: Yu Kuai <yukuai3@huawei.com> Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index ff233a7b398d3..f4db9dca5135c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -13,6 +13,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_managed.h> #include <drm/drm_plane_helper.h> #include <drm/drm_vblank.h> @@ -341,6 +342,13 @@ static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = { .atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state, }; +static void rcar_du_vsp_cleanup(struct drm_device *dev, void *res) +{ + struct rcar_du_vsp *vsp = res; + + put_device(vsp->vsp); +} + int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, unsigned int crtcs) { @@ -357,6 +365,10 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, vsp->vsp = &pdev->dev; + ret = drmm_add_action(rcdu->ddev, rcar_du_vsp_cleanup, vsp); + if (ret < 0) + return ret; + ret = vsp1_du_init(vsp->vsp); if (ret < 0) return ret; -- GitLab From 9d8baa2bf224f6f010644b2a60a3ca73d829663e Mon Sep 17 00:00:00 2001 From: Akhil P Oommen <akhilpo@codeaurora.org> Date: Tue, 22 Sep 2020 20:25:26 +0530 Subject: [PATCH 1363/1494] drm/msm: Fix premature purging of BO In the case where we have a back-to-back submission that shares the same BO, this BO will be prematurely moved to inactive_list while retiring the first submit. But it will be still part of the second submit which is being processed by the GPU. Now, if the shrinker happens to be triggered at this point, it will result in a premature purging of this BO. To fix this, we need to refcount BO while doing submit and retire. Then, it should be moved to inactive list when this refcount becomes 0. Signed-off-by: Akhil P Oommen <akhilpo@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/msm_drv.h | 5 ++--- drivers/gpu/drm/msm/msm_gem.c | 32 ++++++++++++++++---------------- drivers/gpu/drm/msm/msm_gem.h | 4 +++- drivers/gpu/drm/msm/msm_gpu.c | 11 +++++++---- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 319327462b29e..28e3c8d628cb1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -309,9 +309,8 @@ void msm_gem_put_vaddr(struct drm_gem_object *obj); int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive); -void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence); -void msm_gem_move_to_inactive(struct drm_gem_object *obj); +void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu); +void msm_gem_active_put(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); void msm_gem_free_object(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 76a6c5271e578..14e14caf90f98 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -743,31 +743,31 @@ int msm_gem_sync_object(struct drm_gem_object *obj, return 0; } -void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence) +void msm_gem_active_get(struct drm_gem_object *obj, struct msm_gpu *gpu) { struct msm_gem_object *msm_obj = to_msm_bo(obj); + WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); - msm_obj->gpu = gpu; - if (exclusive) - dma_resv_add_excl_fence(obj->resv, fence); - else - dma_resv_add_shared_fence(obj->resv, fence); - list_del_init(&msm_obj->mm_list); - list_add_tail(&msm_obj->mm_list, &gpu->active_list); + + if (!atomic_fetch_inc(&msm_obj->active_count)) { + msm_obj->gpu = gpu; + list_del_init(&msm_obj->mm_list); + list_add_tail(&msm_obj->mm_list, &gpu->active_list); + } } -void msm_gem_move_to_inactive(struct drm_gem_object *obj) +void msm_gem_active_put(struct drm_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct msm_drm_private *priv = dev->dev_private; struct msm_gem_object *msm_obj = to_msm_bo(obj); + struct msm_drm_private *priv = obj->dev->dev_private; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); - msm_obj->gpu = NULL; - list_del_init(&msm_obj->mm_list); - list_add_tail(&msm_obj->mm_list, &priv->inactive_list); + if (!atomic_dec_return(&msm_obj->active_count)) { + msm_obj->gpu = NULL; + list_del_init(&msm_obj->mm_list); + list_add_tail(&msm_obj->mm_list, &priv->inactive_list); + } } int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 7b1c7a5f8eef4..a1bf741b9b896 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -88,12 +88,14 @@ struct msm_gem_object { struct mutex lock; /* Protects resources associated with bo */ char name[32]; /* Identifier to print for the debugfs files */ + + atomic_t active_count; }; #define to_msm_bo(x) container_of(x, struct msm_gem_object, base) static inline bool is_active(struct msm_gem_object *msm_obj) { - return msm_obj->gpu != NULL; + return atomic_read(&msm_obj->active_count); } static inline bool is_purgeable(struct msm_gem_object *msm_obj) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 29c8d73c9a039..55d16489d0f3f 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -698,8 +698,8 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_ringbuffer *ring, for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; - /* move to inactive: */ - msm_gem_move_to_inactive(&msm_obj->base); + + msm_gem_active_put(&msm_obj->base); msm_gem_unpin_iova(&msm_obj->base, submit->aspace); drm_gem_object_put_locked(&msm_obj->base); } @@ -774,6 +774,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; + struct drm_gem_object *drm_obj = &msm_obj->base; uint64_t iova; /* can't happen yet.. but when we add 2d support we'll have @@ -786,9 +787,11 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) msm_gem_get_and_pin_iova(&msm_obj->base, submit->aspace, &iova); if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) - msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); + dma_resv_add_excl_fence(drm_obj->resv, submit->fence); else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ) - msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence); + dma_resv_add_shared_fence(drm_obj->resv, submit->fence); + + msm_gem_active_get(drm_obj, gpu); } gpu->funcs->submit(gpu, submit); -- GitLab From 63ca94adc03cff509d20b1306e48afccb44d5bdf Mon Sep 17 00:00:00 2001 From: Akhil P Oommen <akhilpo@codeaurora.org> Date: Tue, 22 Sep 2020 20:25:27 +0530 Subject: [PATCH 1364/1494] drm/msm: Leave inuse count intact on map failure Leave the inuse count intact on map failure to keep the accounting accurate. Signed-off-by: Akhil P Oommen <akhilpo@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/msm_gem_vma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 80a8a266d68f9..f914ddbaea89b 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -88,8 +88,10 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace, ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, size, prot); - if (ret) + if (ret) { vma->mapped = false; + vma->inuse--; + } return ret; } -- GitLab From 341a361c46368fe7af30035f379071945931793e Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Sat, 19 Sep 2020 10:51:58 +0800 Subject: [PATCH 1365/1494] drm/msm/dpu: Convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 15 +--------- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 ++------------------ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 15 ++-------- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 17 ++---------- 4 files changed, 8 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c index f1bc6a1af7a71..84ea09d9692f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c @@ -288,19 +288,6 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) } #ifdef CONFIG_DEBUG_FS -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} - static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) { struct dpu_irq *irq_obj = s->private; @@ -328,7 +315,7 @@ static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) return 0; } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_core_irq); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_core_irq); void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms, struct dentry *parent) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index 6169148b31700..f56414a06ec41 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1177,23 +1177,7 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data) return 0; } -static int _dpu_debugfs_status_open(struct inode *inode, struct file *file) -{ - return single_open(file, _dpu_debugfs_status_show, inode->i_private); -} - -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} +DEFINE_SHOW_ATTRIBUTE(_dpu_debugfs_status); static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) { @@ -1210,25 +1194,18 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v) return 0; } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_crtc_debugfs_state); +DEFINE_SHOW_ATTRIBUTE(dpu_crtc_debugfs_state); static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc) { struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc); - static const struct file_operations debugfs_status_fops = { - .open = _dpu_debugfs_status_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - }; - dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name, crtc->dev->primary->debugfs_root); debugfs_create_file("status", 0400, dpu_crtc->debugfs_root, - dpu_crtc, &debugfs_status_fops); + dpu_crtc, &_dpu_debugfs_status_fops); debugfs_create_file("state", 0600, dpu_crtc->debugfs_root, &dpu_crtc->base, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 761a007e71692..f7f5c258b5537 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -1912,24 +1912,13 @@ static int _dpu_encoder_status_show(struct seq_file *s, void *data) return 0; } -static int _dpu_encoder_debugfs_status_open(struct inode *inode, - struct file *file) -{ - return single_open(file, _dpu_encoder_status_show, inode->i_private); -} +DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status); static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc) { struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc); int i; - static const struct file_operations debugfs_status_fops = { - .open = _dpu_encoder_debugfs_status_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - }; - char name[DPU_NAME_SIZE]; if (!drm_enc->dev) { @@ -1945,7 +1934,7 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc) /* don't error check these */ debugfs_create_file("status", 0600, - dpu_enc->debugfs_root, dpu_enc, &debugfs_status_fops); + dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops); for (i = 0; i < dpu_enc->num_phys_encs; i++) if (dpu_enc->phys_encs[i]->ops.late_register) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 89b33b39087f5..d93c44f6996db 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -85,30 +85,17 @@ static int _dpu_danger_signal_status(struct seq_file *s, return 0; } -#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \ -static int __prefix ## _open(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, __prefix ## _show, inode->i_private); \ -} \ -static const struct file_operations __prefix ## _fops = { \ - .owner = THIS_MODULE, \ - .open = __prefix ## _open, \ - .release = single_release, \ - .read = seq_read, \ - .llseek = seq_lseek, \ -} - static int dpu_debugfs_danger_stats_show(struct seq_file *s, void *v) { return _dpu_danger_signal_status(s, true); } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_danger_stats); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_danger_stats); static int dpu_debugfs_safe_stats_show(struct seq_file *s, void *v) { return _dpu_danger_signal_status(s, false); } -DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_debugfs_safe_stats); +DEFINE_SHOW_ATTRIBUTE(dpu_debugfs_safe_stats); static void dpu_debugfs_danger_init(struct dpu_kms *dpu_kms, struct dentry *parent) -- GitLab From 3c0f462da069af12211901ddf26f7e16e6951d9b Mon Sep 17 00:00:00 2001 From: Luo Jiaxing <luojiaxing@huawei.com> Date: Wed, 16 Sep 2020 16:51:38 +0800 Subject: [PATCH 1366/1494] drm/msm/dpu: remove unused variables new_cnt and old_cnt in dpu_encoder_phys_vid_vblank_irq() We found two unused variables new_cnt and old_cnt when build kernel with W=1. So delete it. Signed-off-by: Luo Jiaxing <luojiaxing@huawei.com> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 be11a0c5e60c6..805e059b50b71 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 @@ -306,7 +306,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) struct dpu_hw_ctl *hw_ctl; unsigned long lock_flags; u32 flush_register = 0; - int new_cnt = -1, old_cnt = -1; hw_ctl = phys_enc->hw_ctl; @@ -316,7 +315,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) phys_enc->parent_ops->handle_vblank_virt(phys_enc->parent, phys_enc); - old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); + atomic_read(&phys_enc->pending_kickoff_cnt); /* * only decrement the pending flush count if we've actually flushed @@ -328,8 +327,7 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx) flush_register = hw_ctl->ops.get_flush_register(hw_ctl); if (!(flush_register & hw_ctl->ops.get_pending_flush(hw_ctl))) - new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, - -1, 0); + atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags); /* Signal any waiting atomic commit thread */ -- GitLab From c7651b73586600ddf483de51806eada02cb1616e Mon Sep 17 00:00:00 2001 From: Felix Kuehling <Felix.Kuehling@amd.com> Date: Wed, 16 Sep 2020 21:19:34 -0400 Subject: [PATCH 1367/1494] drm/amdgpu: Fix handling of KFD initialization failures Remember KFD module initializaton status in a global variable. Skip KFD device probing when the module was not initialized. Other amdgpu_amdkfd calls are then protected by the adev->kfd.dev check. Also print a clear error message when KFD disables itself. Amdgpu continues its initialization even when KFD failed. Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Reviewed-by: Kent Russell <kent.russell@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 11 ++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_module.c | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index edff1b7f282a7..53d5aa2d96bfa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -36,6 +36,8 @@ */ uint64_t amdgpu_amdkfd_total_mem_size; +bool kfd_initialized; + int amdgpu_amdkfd_init(void) { struct sysinfo si; @@ -51,19 +53,26 @@ int amdgpu_amdkfd_init(void) #else ret = -ENOENT; #endif + kfd_initialized = !ret; return ret; } void amdgpu_amdkfd_fini(void) { - kgd2kfd_exit(); + if (kfd_initialized) { + kgd2kfd_exit(); + kfd_initialized = false; + } } void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev) { bool vf = amdgpu_sriov_vf(adev); + if (!kfd_initialized) + return; + adev->kfd.dev = kgd2kfd_probe((struct kgd_dev *)adev, adev->pdev, adev->asic_type, vf); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index b7b16adb0615d..297484ca7d193 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -97,6 +97,7 @@ void kfd_chardev_exit(void) device_destroy(kfd_class, MKDEV(kfd_char_dev_major, 0)); class_destroy(kfd_class); unregister_chrdev(kfd_char_dev_major, kfd_dev_name); + kfd_device = NULL; } struct device *kfd_chardev(void) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index f4b7f7e6c40e4..5e90fe6421924 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -70,6 +70,7 @@ static int kfd_init(void) err_topology: kfd_chardev_exit(); err_ioctl: + pr_err("KFD is disabled due to module initialization failure\n"); return err; } -- GitLab From b7b6c38529c9ea8ebab287d84f27fca2472a5737 Mon Sep 17 00:00:00 2001 From: Kent Russell <kent.russell@amd.com> Date: Fri, 18 Sep 2020 07:42:57 -0400 Subject: [PATCH 1368/1494] drm/amdkfd: Calculate CPU VCRAT size dynamically (v2) Instead of guessing at a sufficient size for the CPU VCRAT, base the size on the number of online NUMA nodes. v2: fix warning Signed-off-by: Kent Russell <kent.russell@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 3fac06b281ce0..f76aa5603d2d8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -809,11 +809,10 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size) /* Memory required to create Virtual CRAT. * Since there is no easy way to predict the amount of memory required, the - * following amount are allocated for CPU and GPU Virtual CRAT. This is + * following amount is allocated for GPU Virtual CRAT. This is * expected to cover all known conditions. But to be safe additional check * is put in the code to ensure we don't overwrite. */ -#define VCRAT_SIZE_FOR_CPU (2 * PAGE_SIZE) #define VCRAT_SIZE_FOR_GPU (4 * PAGE_SIZE) /* kfd_fill_cu_for_cpu - Fill in Compute info for the given CPU NUMA node @@ -964,7 +963,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size) #endif int ret = 0; - if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU) + if (!pcrat_image) return -EINVAL; /* Fill in CRAT Header. @@ -1364,24 +1363,31 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size, uint32_t proximity_domain) { void *pcrat_image = NULL; - int ret = 0; + int ret = 0, num_nodes; + size_t dyn_size; if (!crat_image) return -EINVAL; *crat_image = NULL; - /* Allocate one VCRAT_SIZE_FOR_CPU for CPU virtual CRAT image and - * VCRAT_SIZE_FOR_GPU for GPU virtual CRAT image. This should cover - * all the current conditions. A check is put not to overwrite beyond - * allocated size + /* Allocate the CPU Virtual CRAT size based on the number of online + * nodes. Allocate VCRAT_SIZE_FOR_GPU for GPU virtual CRAT image. + * This should cover all the current conditions. A check is put not + * to overwrite beyond allocated size for GPUs */ switch (flags) { case COMPUTE_UNIT_CPU: - pcrat_image = kmalloc(VCRAT_SIZE_FOR_CPU, GFP_KERNEL); + num_nodes = num_online_nodes(); + dyn_size = sizeof(struct crat_header) + + num_nodes * (sizeof(struct crat_subtype_computeunit) + + sizeof(struct crat_subtype_memory) + + (num_nodes - 1) * sizeof(struct crat_subtype_iolink)); + pcrat_image = kmalloc(dyn_size, GFP_KERNEL); if (!pcrat_image) return -ENOMEM; - *size = VCRAT_SIZE_FOR_CPU; + *size = dyn_size; + pr_debug("CRAT size is %ld", dyn_size); ret = kfd_create_vcrat_image_cpu(pcrat_image, size); break; case COMPUTE_UNIT_GPU: -- GitLab From 59d7115dae02c9eea9f44e5a0081e8a62a13b12c Mon Sep 17 00:00:00 2001 From: Mukul Joshi <mukul.joshi@amd.com> Date: Fri, 18 Sep 2020 16:45:45 -0400 Subject: [PATCH 1369/1494] drm/amdkfd: Move process doorbell allocation into kfd device Move doorbell allocation for a process into kfd device and allocate doorbell space in each PDD during process creation. Currently, KFD manages its own doorbell space but for some devices, amdgpu would allocate the complete doorbell space instead of leaving a chunk of doorbell space for KFD to manage. In a system with mix of such devices, KFD would need to request process doorbell space based on the type of device, either from amdgpu or from its own doorbell space. Signed-off-by: Mukul Joshi <mukul.joshi@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 30 ++++++++------ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 ++ .../drm/amd/amdkfd/kfd_device_queue_manager.c | 3 +- drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 40 +++++++++---------- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 17 ++++---- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 21 +++++----- 6 files changed, 64 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 297484ca7d193..222f1df1a6b6d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1291,18 +1291,6 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, return -EINVAL; } - if (flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { - if (args->size != kfd_doorbell_process_slice(dev)) - return -EINVAL; - offset = kfd_get_process_doorbells(dev, p); - } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { - if (args->size != PAGE_SIZE) - return -EINVAL; - offset = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd); - if (!offset) - return -ENOMEM; - } - mutex_lock(&p->mutex); pdd = kfd_bind_process_to_device(dev, p); @@ -1311,6 +1299,24 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, goto err_unlock; } + if (flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { + if (args->size != kfd_doorbell_process_slice(dev)) { + err = -EINVAL; + goto err_unlock; + } + offset = kfd_get_process_doorbells(pdd); + } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { + if (args->size != PAGE_SIZE) { + err = -EINVAL; + goto err_unlock; + } + offset = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd); + if (!offset) { + err = -ENOMEM; + goto err_unlock; + } + } + err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( dev->kgd, args->va_addr, args->size, pdd->vm, (struct kgd_mem **) &mem, &offset, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index e3fc6ed7b79c3..135001a404bc7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -583,6 +583,8 @@ struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, atomic_set(&kfd->sram_ecc_flag, 0); + ida_init(&kfd->doorbell_ida); + return kfd; } @@ -798,6 +800,7 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) kfd_interrupt_exit(kfd); kfd_topology_remove_device(kfd); kfd_doorbell_fini(kfd); + ida_destroy(&kfd->doorbell_ida); kfd_gtt_sa_fini(kfd); amdgpu_amdkfd_free_gtt_mem(kfd->kgd, kfd->gtt_mem); if (kfd->gws) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index ed362ab8ec21a..62504d5fa42b1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -191,9 +191,8 @@ static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) } q->properties.doorbell_off = - kfd_get_doorbell_dw_offset_in_bar(dev, q->process, + kfd_get_doorbell_dw_offset_in_bar(dev, qpd_to_pdd(qpd), q->doorbell_id); - return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c index 8e0c00b9555ed..768d153acff42 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c @@ -31,9 +31,6 @@ * kernel queues using the first doorbell page reserved for the kernel. */ -static DEFINE_IDA(doorbell_ida); -static unsigned int max_doorbell_slices; - /* * Each device exposes a doorbell aperture, a PCI MMIO aperture that * receives 32-bit writes that are passed to queues as wptr values. @@ -84,9 +81,9 @@ int kfd_doorbell_init(struct kfd_dev *kfd) else return -ENOSPC; - if (!max_doorbell_slices || - doorbell_process_limit < max_doorbell_slices) - max_doorbell_slices = doorbell_process_limit; + if (!kfd->max_doorbell_slices || + doorbell_process_limit < kfd->max_doorbell_slices) + kfd->max_doorbell_slices = doorbell_process_limit; kfd->doorbell_base = kfd->shared_resources.doorbell_physical_address + doorbell_start_offset; @@ -130,6 +127,7 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process, struct vm_area_struct *vma) { phys_addr_t address; + struct kfd_process_device *pdd; /* * For simplicitly we only allow mapping of the entire doorbell @@ -138,9 +136,12 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process, if (vma->vm_end - vma->vm_start != kfd_doorbell_process_slice(dev)) return -EINVAL; - /* Calculate physical address of doorbell */ - address = kfd_get_process_doorbells(dev, process); + pdd = kfd_get_process_device_data(dev, process); + if (!pdd) + return -EINVAL; + /* Calculate physical address of doorbell */ + address = kfd_get_process_doorbells(pdd); vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE | VM_DONTDUMP | VM_PFNMAP; @@ -226,7 +227,7 @@ void write_kernel_doorbell64(void __iomem *db, u64 value) } unsigned int kfd_get_doorbell_dw_offset_in_bar(struct kfd_dev *kfd, - struct kfd_process *process, + struct kfd_process_device *pdd, unsigned int doorbell_id) { /* @@ -236,7 +237,7 @@ unsigned int kfd_get_doorbell_dw_offset_in_bar(struct kfd_dev *kfd, * units regardless of the ASIC-dependent doorbell size. */ return kfd->doorbell_base_dw_offset + - process->doorbell_index + pdd->doorbell_index * kfd_doorbell_process_slice(kfd) / sizeof(u32) + doorbell_id * kfd->device_info->doorbell_size / sizeof(u32); } @@ -251,25 +252,24 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd) } -phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, - struct kfd_process *process) +phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd) { - return dev->doorbell_base + - process->doorbell_index * kfd_doorbell_process_slice(dev); + return pdd->dev->doorbell_base + + pdd->doorbell_index * kfd_doorbell_process_slice(pdd->dev); } -int kfd_alloc_process_doorbells(struct kfd_process *process) +int kfd_alloc_process_doorbells(struct kfd_dev *kfd, unsigned int *doorbell_index) { - int r = ida_simple_get(&doorbell_ida, 1, max_doorbell_slices, + int r = ida_simple_get(&kfd->doorbell_ida, 1, kfd->max_doorbell_slices, GFP_KERNEL); if (r > 0) - process->doorbell_index = r; + *doorbell_index = r; return r; } -void kfd_free_process_doorbells(struct kfd_process *process) +void kfd_free_process_doorbells(struct kfd_dev *kfd, unsigned int doorbell_index) { - if (process->doorbell_index) - ida_simple_remove(&doorbell_ida, process->doorbell_index); + if (doorbell_index) + ida_simple_remove(&kfd->doorbell_ida, doorbell_index); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 8c2b8ccd27fb7..739db04080d0f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -314,6 +314,9 @@ struct kfd_dev { spinlock_t smi_lock; uint32_t reset_seq_num; + + struct ida doorbell_ida; + unsigned int max_doorbell_slices; }; enum kfd_mempool { @@ -699,6 +702,7 @@ struct kfd_process_device { struct attribute attr_evict; struct kobject *kobj_stats; + unsigned int doorbell_index; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) @@ -736,7 +740,6 @@ struct kfd_process { struct mmu_notifier mmu_notifier; uint16_t pasid; - unsigned int doorbell_index; /* * List of kfd_process_device structures, @@ -869,13 +872,13 @@ u32 read_kernel_doorbell(u32 __iomem *db); void write_kernel_doorbell(void __iomem *db, u32 value); void write_kernel_doorbell64(void __iomem *db, u64 value); unsigned int kfd_get_doorbell_dw_offset_in_bar(struct kfd_dev *kfd, - struct kfd_process *process, + struct kfd_process_device *pdd, unsigned int doorbell_id); -phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev, - struct kfd_process *process); -int kfd_alloc_process_doorbells(struct kfd_process *process); -void kfd_free_process_doorbells(struct kfd_process *process); - +phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd); +int kfd_alloc_process_doorbells(struct kfd_dev *kfd, + unsigned int *doorbell_index); +void kfd_free_process_doorbells(struct kfd_dev *kfd, + unsigned int doorbell_index); /* GTT Sub-Allocator */ int kfd_gtt_sa_allocate(struct kfd_dev *kfd, unsigned int size, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ad53b2668221f..e2b6d31d93ce8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -876,6 +876,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) kfree(pdd->qpd.doorbell_bitmap); idr_destroy(&pdd->alloc_idr); + kfd_free_process_doorbells(pdd->dev, pdd->doorbell_index); + /* * before destroying pdd, make sure to report availability * for auto suspend @@ -932,8 +934,6 @@ static void kfd_process_wq_release(struct work_struct *work) kfd_event_free_process(p); kfd_pasid_free(p->pasid); - kfd_free_process_doorbells(p); - mutex_destroy(&p->mutex); put_task_struct(p->lead_thread); @@ -1111,9 +1111,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) if (process->pasid == 0) goto err_alloc_pasid; - if (kfd_alloc_process_doorbells(process) < 0) - goto err_alloc_doorbells; - err = pqm_init(&process->pqm, process); if (err != 0) goto err_process_pqm_init; @@ -1141,8 +1138,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) err_init_apertures: pqm_uninit(&process->pqm); err_process_pqm_init: - kfd_free_process_doorbells(process); -err_alloc_doorbells: kfd_pasid_free(process->pasid); err_alloc_pasid: mutex_destroy(&process->mutex); @@ -1205,10 +1200,14 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, if (!pdd) return NULL; + if (kfd_alloc_process_doorbells(dev, &pdd->doorbell_index) < 0) { + pr_err("Failed to alloc doorbell for pdd\n"); + goto err_free_pdd; + } + if (init_doorbell_bitmap(&pdd->qpd, dev)) { pr_err("Failed to init doorbell for process\n"); - kfree(pdd); - return NULL; + goto err_free_pdd; } pdd->dev = dev; @@ -1231,6 +1230,10 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, idr_init(&pdd->alloc_idr); return pdd; + +err_free_pdd: + kfree(pdd); + return NULL; } /** -- GitLab From 9de9a54aba76ae6b3eb5da221114619977872ec6 Mon Sep 17 00:00:00 2001 From: Shirish S <shirish.s@amd.com> Date: Thu, 17 Sep 2020 14:07:32 +0530 Subject: [PATCH 1370/1494] drm/amd/display: fix crash/reboot while accessing sysfs files read/writes to aux_dpcd_* sysfs entries leads to system reboot or hang. Hence fix the handling of input data and reporting of errors appropriately to the user space. Signed-off-by: Shirish S <shirish.s@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 004cd8d382145..8cd646eef096c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -908,7 +908,7 @@ static ssize_t dp_dpcd_address_write(struct file *f, const char __user *buf, struct amdgpu_dm_connector *connector = file_inode(f)->i_private; if (size < sizeof(connector->debugfs_dpcd_address)) - return 0; + return -EINVAL; r = copy_from_user(&connector->debugfs_dpcd_address, buf, sizeof(connector->debugfs_dpcd_address)); @@ -923,7 +923,7 @@ static ssize_t dp_dpcd_size_write(struct file *f, const char __user *buf, struct amdgpu_dm_connector *connector = file_inode(f)->i_private; if (size < sizeof(connector->debugfs_dpcd_size)) - return 0; + return -EINVAL; r = copy_from_user(&connector->debugfs_dpcd_size, buf, sizeof(connector->debugfs_dpcd_size)); @@ -943,8 +943,8 @@ static ssize_t dp_dpcd_data_write(struct file *f, const char __user *buf, struct dc_link *link = connector->dc_link; uint32_t write_size = connector->debugfs_dpcd_size; - if (size < write_size) - return 0; + if (!write_size || size < write_size) + return -EINVAL; data = kzalloc(write_size, GFP_KERNEL); if (!data) @@ -967,7 +967,7 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, struct dc_link *link = connector->dc_link; uint32_t read_size = connector->debugfs_dpcd_size; - if (size < read_size) + if (!read_size || size < read_size) return 0; data = kzalloc(read_size, GFP_KERNEL); -- GitLab From 36499e4c776ad2e51bb6d0075acdfba9f728b8c2 Mon Sep 17 00:00:00 2001 From: "Emily.Deng" <Emily.Deng@amd.com> Date: Mon, 14 Sep 2020 17:57:01 +0800 Subject: [PATCH 1371/1494] drm/amdgpu: Fix dead lock issue for vblank Always start vblank timer, but only calls vblank function when vblank is enabled. This is used to fix the dead lock issue. When drm_crtc_vblank_off want to disable vblank, it first get event_lock, and then call hrtimer_cancel, but hrtimer_cancel want to wait timer handler function finished. Timer handler also want to aquire event_lock in drm_handle_vblank. Signed-off-by: Emily.Deng <Emily.Deng@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 35 ++++++++++++------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index cc93577dee03f..469c05fd43d54 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -47,6 +47,9 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, int index); +static int dce_virtual_pageflip(struct amdgpu_device *adev, + unsigned crtc_id); +static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer); static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, int crtc, enum amdgpu_interrupt_state state); @@ -247,6 +250,11 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); + hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD); + amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle; + hrtimer_start(&amdgpu_crtc->vblank_timer, + DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); return 0; } @@ -476,7 +484,7 @@ static int dce_virtual_hw_fini(void *handle) for (i = 0; i<adev->mode_info.num_crtc; i++) if (adev->mode_info.crtcs[i]) - dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE); + hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); return 0; } @@ -698,9 +706,15 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla struct amdgpu_crtc, vblank_timer); struct drm_device *ddev = amdgpu_crtc->base.dev; struct amdgpu_device *adev = drm_to_adev(ddev); + struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources + [VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER]; + int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, + amdgpu_crtc->crtc_id); - drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); - dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); + if (amdgpu_irq_enabled(adev, source, irq_type)) { + drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); + dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); + } hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); @@ -716,21 +730,6 @@ static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *ad return; } - if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { - DRM_DEBUG("Enable software vsync timer\n"); - hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, - CLOCK_MONOTONIC, HRTIMER_MODE_REL); - hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer, - DCE_VIRTUAL_VBLANK_PERIOD); - adev->mode_info.crtcs[crtc]->vblank_timer.function = - dce_virtual_vblank_timer_handle; - hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, - DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); - } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { - DRM_DEBUG("Disable software vsync timer\n"); - hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer); - } - adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); } -- GitLab From e8f58ee143edff15894b132d86797fe06891ddd0 Mon Sep 17 00:00:00 2001 From: Philip Cox <Philip.Cox@amd.com> Date: Mon, 21 Sep 2020 06:45:45 -0400 Subject: [PATCH 1372/1494] drm/amdkfd: Fix kfd init stack dump amdkfd is dumping a stack during initialization. kfd_procfs_add_sysfs_stats is being called twice. This removes one of them. Fixes: 4327bed2ff8e3d ("drm/amdkfd: Add process eviction counters to sysfs") Reviewed-by: Kent Russell <kent.russell@amd.com> Signed-off-by: Philip Cox <Philip.Cox@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index e2b6d31d93ce8..17d909c86f508 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -750,11 +750,6 @@ struct kfd_process *kfd_create_process(struct file *filep) pr_warn("Creating sysfs stats dir for pid %d failed", (int)process->lead_thread->pid); - ret = kfd_procfs_add_sysfs_stats(process); - if (ret) - pr_warn("Creating sysfs stats dir for pid %d failed", - (int)process->lead_thread->pid); - ret = kfd_procfs_add_sysfs_files(process); if (ret) pr_warn("Creating sysfs usage file for pid %d failed", -- GitLab From d0e63b343e575e8b74c185565b0d79a93494bcaa Mon Sep 17 00:00:00 2001 From: Kent Russell <kent.russell@amd.com> Date: Fri, 18 Sep 2020 14:47:47 -0400 Subject: [PATCH 1373/1494] drm/amdkfd: Use kvmalloc instead of kmalloc for VCRAT Since we're dynamically allocating the CPU VCRAT, use kvmalloc in case the allocation size is huge. Signed-off-by: Kent Russell <kent.russell@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index f76aa5603d2d8..d2981524dba0b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -797,7 +797,8 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size) return -ENODATA; } - pcrat_image = kmemdup(crat_table, crat_table->length, GFP_KERNEL); + pcrat_image = kvmalloc(crat_table->length, GFP_KERNEL); + memcpy(pcrat_image, crat_table, crat_table->length); if (!pcrat_image) return -ENOMEM; @@ -1383,7 +1384,7 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size, num_nodes * (sizeof(struct crat_subtype_computeunit) + sizeof(struct crat_subtype_memory) + (num_nodes - 1) * sizeof(struct crat_subtype_iolink)); - pcrat_image = kmalloc(dyn_size, GFP_KERNEL); + pcrat_image = kvmalloc(dyn_size, GFP_KERNEL); if (!pcrat_image) return -ENOMEM; *size = dyn_size; @@ -1393,7 +1394,7 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size, case COMPUTE_UNIT_GPU: if (!kdev) return -EINVAL; - pcrat_image = kmalloc(VCRAT_SIZE_FOR_GPU, GFP_KERNEL); + pcrat_image = kvmalloc(VCRAT_SIZE_FOR_GPU, GFP_KERNEL); if (!pcrat_image) return -ENOMEM; *size = VCRAT_SIZE_FOR_GPU; @@ -1412,7 +1413,7 @@ int kfd_create_crat_image_virtual(void **crat_image, size_t *size, if (!ret) *crat_image = pcrat_image; else - kfree(pcrat_image); + kvfree(pcrat_image); return ret; } -- GitLab From 651111be24aa4c8b62c10f6fff51d9ad82411249 Mon Sep 17 00:00:00 2001 From: David Galiffi <David.Galiffi@amd.com> Date: Thu, 3 Sep 2020 19:20:36 -0400 Subject: [PATCH 1374/1494] drm/amd/display: Fix incorrect backlight register offset for DCN [Why] Typo in backlight refactor introduced wrong register offset. [How] SR(BIOS_SCRATCH_2) to NBIO_SR(BIOS_SCRATCH_2). Signed-off-by: David Galiffi <David.Galiffi@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: <stable@vger.kernel.org> --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 99c68ca9c7e00..967d04d75b989 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -54,7 +54,7 @@ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ SR(BL_PWM_GRP1_REG_LOCK), \ - SR(BIOS_SCRATCH_2) + NBIO_SR(BIOS_SCRATCH_2) #define DCE_PANEL_CNTL_SF(reg_name, field_name, post_fix)\ .field_name = reg_name ## __ ## field_name ## post_fix -- GitLab From e4b37eec1767468a14b7418a41a857a5b6eca66d Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Mon, 7 Sep 2020 13:01:02 -0400 Subject: [PATCH 1375/1494] drm/amd/display: [FW Promotion] Release 0.0.33 Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index f74c7fabd0a95..bbcb8ed60bb63 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x82f998da6 +#define DMUB_FW_VERSION_GIT_HASH 0xd0772ca1b #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 32 +#define DMUB_FW_VERSION_REVISION 33 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 -- GitLab From c15bc8d285fe052bc3a30ae5ea0919c3101981ef Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Tue, 8 Sep 2020 10:35:37 -0400 Subject: [PATCH 1376/1494] drm/amd/display: 3.2.103 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d9b22d6a985a7..d65483483d051 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.102" +#define DC_VER "3.2.103" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From cbf229bbcb7fcc5f4f75f64eee7e224aa1b31ad2 Mon Sep 17 00:00:00 2001 From: Peikang Zhang <peikang.zhang@amd.com> Date: Thu, 3 Sep 2020 13:45:07 -0400 Subject: [PATCH 1377/1494] drm/amd/display: Bug in dce_is_panel_backlight_on() [Why] dce_is_panel_backlight_on() will return wrong value if LVTMA_BLON_OVRD is 0 [How] When LVTMA_BLON_OVRD is 0, read LVTMA_PWRSEQ_TARGET_STATE instead Signed-off-by: Peikang Zhang <peikang.zhang@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 10 +++++++--- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index df7f826eebd86..74f7619d4154b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -159,11 +159,15 @@ static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) static bool dce_is_panel_backlight_on(struct panel_cntl *panel_cntl) { struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); - uint32_t value; + uint32_t blon, blon_ovrd, pwrseq_target_state; - REG_GET(PWRSEQ_CNTL, LVTMA_BLON, &value); + REG_GET_2(PWRSEQ_CNTL, LVTMA_BLON, &blon, LVTMA_BLON_OVRD, &blon_ovrd); + REG_GET(PWRSEQ_CNTL, LVTMA_PWRSEQ_TARGET_STATE, &pwrseq_target_state); - return value; + if (blon_ovrd) + return blon; + else + return pwrseq_target_state; } static bool dce_is_panel_powered_on(struct panel_cntl *panel_cntl) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 967d04d75b989..6bd1196083a39 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -61,8 +61,10 @@ #define DCE_PANEL_CNTL_MASK_SH_LIST(mask_sh) \ DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_BLON_OVRD, mask_sh),\ DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, mask_sh),\ DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON_OVRD, mask_sh),\ + DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_CNTL, LVTMA_PWRSEQ_TARGET_STATE, mask_sh), \ DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh), \ DCE_PANEL_CNTL_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \ DCE_PANEL_CNTL_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, mask_sh), \ @@ -76,8 +78,10 @@ #define DCE_PANEL_CNTL_REG_FIELD_LIST(type) \ type LVTMA_BLON;\ + type LVTMA_BLON_OVRD;\ type LVTMA_DIGON;\ type LVTMA_DIGON_OVRD;\ + type LVTMA_PWRSEQ_TARGET_STATE; \ type LVTMA_PWRSEQ_TARGET_STATE_R; \ type BL_PWM_REF_DIV; \ type BL_PWM_EN; \ -- GitLab From 099303e9a9bd77f66a1f7a8b3f447c572b532796 Mon Sep 17 00:00:00 2001 From: Peikang Zhang <peikang.zhang@amd.com> Date: Tue, 8 Sep 2020 11:27:25 -0400 Subject: [PATCH 1378/1494] drm/amd/display: eDP intermittent black screen during PnP [Why] We dont's turn off backlight before power off eDP (VDD), which is a violation of eDP specs. [How] Power off eDP backlight before power off eDP Signed-off-by: Peikang Zhang <peikang.zhang@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 ++ drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 1 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 1 + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 1 + 6 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 81c026319ccdd..dba338c882561 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -229,6 +229,8 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dp_receiver_power_ctrl(link, false); if (signal == SIGNAL_TYPE_EDP) { + if (link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control(link, false); link->link_enc->funcs->disable_output(link->link_enc, signal); link->dc->hwss.edp_power_control(link, false); } else { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 1002ce9979dce..27a1262a20f60 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2890,6 +2890,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .setup_stereo = NULL, .set_avmute = dce110_set_avmute, .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dce110_set_cursor_position, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index a1d1559bb5d73..b24c8ae8b1ece 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -66,6 +66,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 966e1790b9bfd..072193c5ffe66 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -68,6 +68,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 2ba880c3943c3..2b7396c9fcb48 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -69,6 +69,7 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 19daa456e3bfe..7c90c22225062 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -69,6 +69,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, + .edp_backlight_control = dce110_edp_backlight_control, .edp_power_control = dce110_edp_power_control, .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready, .set_cursor_position = dcn10_set_cursor_position, -- GitLab From 25b315817216eaac93ca880d736b359ababae61a Mon Sep 17 00:00:00 2001 From: Wesley Chalmers <Wesley.Chalmers@amd.com> Date: Tue, 8 Sep 2020 16:22:25 -0400 Subject: [PATCH 1379/1494] drm/amd/display: Fix ODM policy implementation [WHY] Only the leftmost ODM pipe should be offset when scaling. A previous code change was intended to implement this policy, but a section of code was overlooked. Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: <stable@vger.kernel.org> --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 4cea9344d8aae..e430148e47cf4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -785,14 +785,15 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) /* * Only the leftmost ODM pipe should be offset by a nonzero distance */ - if (!pipe_ctx->prev_odm_pipe) + if (!pipe_ctx->prev_odm_pipe) { data->recout.x = stream->dst.x; - else - data->recout.x = 0; - if (stream->src.x < surf_clip.x) - data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width + if (stream->src.x < surf_clip.x) + data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; + } else + data->recout.x = 0; + data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; -- GitLab From 37b7cb10f07c1174522faafc1d51c6591b1501d4 Mon Sep 17 00:00:00 2001 From: Wesley Chalmers <Wesley.Chalmers@amd.com> Date: Wed, 9 Sep 2020 17:41:53 -0400 Subject: [PATCH 1380/1494] drm/amd/display: Increase timeout for DP Disable [WHY] When disabling DP video, the current REG_WAIT timeout of 50ms is too low for certain cases with very high VSYNC intervals. [HOW] Increase the timeout to 102ms, so that refresh rates as low as 10Hz can be handled properly. Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: <stable@vger.kernel.org> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 9cf139be3f40e..f70fcadf1ee55 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -896,10 +896,10 @@ void enc1_stream_encoder_dp_blank( */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2); /* Larger delay to wait until VBLANK - use max retry of - * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode + + * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode + * a little more because we may not trust delay accuracy. */ - max_retries = DP_BLANK_MAX_RETRY * 250; + max_retries = DP_BLANK_MAX_RETRY * 501; /* disable DP stream */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); -- GitLab From f43dc909aa7f4516b5eaccbc8608d9bbe450f43e Mon Sep 17 00:00:00 2001 From: Gary Li <gary.li@amd.com> Date: Thu, 10 Sep 2020 14:32:13 -0400 Subject: [PATCH 1381/1494] drm/amd/display: Enable DP YCbCr420 mode support for DCN10 [WHY] In DCN10 when a panel with YCbCr420 capability is connected via USB-C to HDMI active dongle, no YCbCr420 option is listed in Radeon settings. [HOW] Enable DP YCbCr420 mode support for DCN10 Signed-off-by: Gary Li <gary.li@amd.com> Reviewed-by: Eric Yang <eric.yang2@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 1abd81e17f09d..a78712caf1244 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -798,7 +798,7 @@ static const struct encoder_feature_support link_enc_feature = { .max_hdmi_deep_color = COLOR_DEPTH_121212, .max_hdmi_pixel_clock = 600000, .hdmi_ycbcr420_supported = true, - .dp_ycbcr420_supported = false, + .dp_ycbcr420_supported = true, .flags.bits.IS_HBR2_CAPABLE = true, .flags.bits.IS_HBR3_CAPABLE = true, .flags.bits.IS_TPS3_CAPABLE = true, -- GitLab From b50d55517da2c79cb9045bc175bcbf99098a0e28 Mon Sep 17 00:00:00 2001 From: Wenjing Liu <wenjing.liu@amd.com> Date: Thu, 10 Sep 2020 14:11:37 -0400 Subject: [PATCH 1382/1494] drm/amd/display: allow DP RX to use more cr aux rd interval delay [why] Regression is caused by previous change with attempt to correct the extended cr aux rd interval delay due to mis interpretation of the DP specs. The change turns out not working well with certain RXs. So we decided to keep the cr aux rd interval logic as before. Signed-off-by: Wenjing Liu <wenjing.liu@amd.com> Reviewed-by: George Shen <George.Shen@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index b9b66db8332b9..ff1e9963ec7a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -49,6 +49,23 @@ static struct dc_link_settings get_common_supported_link_settings( struct dc_link_settings link_setting_a, struct dc_link_settings link_setting_b); +static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, + const struct dc_link_settings *link_settings) +{ + union training_aux_rd_interval training_rd_interval; + uint32_t wait_in_micro_secs = 100; + + memset(&training_rd_interval, 0, sizeof(training_rd_interval)); + core_link_read_dpcd( + link, + DP_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + return wait_in_micro_secs; +} + static uint32_t get_eq_training_aux_rd_interval( struct dc_link *link, const struct dc_link_settings *link_settings) @@ -1247,7 +1264,7 @@ static void initialize_training_settings( if (overrides->cr_pattern_time != NULL) lt_settings->cr_pattern_time = *overrides->cr_pattern_time; else - lt_settings->cr_pattern_time = 100; + lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting); if (overrides->eq_pattern_time != NULL) lt_settings->eq_pattern_time = *overrides->eq_pattern_time; -- GitLab From a9edc81564c92b4d86670b722bbe8906e0dfd934 Mon Sep 17 00:00:00 2001 From: Wyatt Wood <wyatt.wood@amd.com> Date: Thu, 10 Sep 2020 21:50:52 -0400 Subject: [PATCH 1383/1494] drm/amd/display: Implement PSR wait for enable/disable [Why] For DMUB implementation of PSR, the 'wait' parameter, used to determine if driver should wait for PSR enable/disable, is not implemented correctly. [How] Implement wait for PSR enable/disable. Signed-off-by: Wyatt Wood <wyatt.wood@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 27 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1871ff6119ae0..f13396254b5d2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2566,7 +2566,7 @@ bool dc_link_set_psr_allow_active(struct dc_link *link, bool allow_active, bool link->psr_settings.psr_allow_active = allow_active; if (psr != NULL && link->psr_settings.psr_feature_enabled) - psr->funcs->psr_enable(psr, allow_active); + psr->funcs->psr_enable(psr, allow_active, wait); else if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu)) && link->psr_settings.psr_feature_enabled) dmcu->funcs->set_psr_enable(dmcu, allow_active, wait); else diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 5167d6b8a48de..bf24f1029547b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -119,10 +119,11 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * /** * Enable/Disable PSR. */ -static void dmub_psr_enable(struct dmub_psr *dmub, bool enable) +static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait) { union dmub_rb_cmd cmd; struct dc_context *dc = dmub->ctx; + uint32_t retry_count, psr_state = 0; cmd.psr_enable.header.type = DMUB_CMD__PSR; @@ -136,6 +137,30 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable) dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); dc_dmub_srv_wait_idle(dc->dmub_srv); + + /* Below loops 1000 x 500us = 500 ms. + * Exit PSR may need to wait 1-2 frames to power up. Timeout after at + * least a few frames. Should never hit the max retry assert below. + */ + if (wait) { + for (retry_count = 0; retry_count <= 1000; retry_count++) { + dmub_psr_get_state(dmub, &psr_state); + + if (enable) { + if (psr_state != 0) + break; + } else { + if (psr_state == 0) + break; + } + + udelay(500); + } + + /* assert if max retry hit */ + if (retry_count >= 1000) + ASSERT(0); + } } /** diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index f404fecd6410d..dc121ed92d2e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -36,7 +36,7 @@ struct dmub_psr { struct dmub_psr_funcs { bool (*psr_copy_settings)(struct dmub_psr *dmub, struct dc_link *link, struct psr_context *psr_context); - void (*psr_enable)(struct dmub_psr *dmub, bool enable); + void (*psr_enable)(struct dmub_psr *dmub, bool enable, bool wait); void (*psr_get_state)(struct dmub_psr *dmub, uint32_t *psr_state); void (*psr_set_level)(struct dmub_psr *dmub, uint16_t psr_level); }; -- GitLab From 99d1437aa0ac1f598e9aabca8bf0e8a40c38f8a1 Mon Sep 17 00:00:00 2001 From: Taimur Hassan <syed.hassan@amd.com> Date: Thu, 10 Sep 2020 10:13:42 -0400 Subject: [PATCH 1384/1494] drm/amd/display: Check for flip pending before locking pipes. [Why] When running a game/benchmark with v-sync disabled, disabling a plane (which is v-sync) can cause an underflow. This is due to flips that are pending before pipe locking being applied after locks are released and pipes have been re-arranged or disconnected. This can potentially apply a flip on the incorrect pipe. [How] Check that any pending flips are cleared before locking any pipes to ensure flips are applied on the correct pipes. Signed-off-by: Taimur Hassan <syed.hassan@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 ++--------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++++++++++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 83ce55edb3aa0..1efc823c2a14c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2324,7 +2324,6 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { - bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2355,14 +2354,8 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && - dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ - dc->hwss.interdependent_update_lock(dc, context, true); - mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); - dc->hwss.interdependent_update_lock(dc, context, false); - if (mpcc_disconnected) - dc->hwss.wait_for_pending_cleared(dc, context); - } + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && dc->hwss.wait_for_pending_cleared) + dc->hwss.disconnect_pipes(dc, context); for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index d0f3bf953d027..79fe9571cf5d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2761,7 +2761,7 @@ static struct pipe_ctx *dcn10_find_top_pipe_for_stream( return NULL; } -bool dcn10_disconnect_pipes( +void dcn10_disconnect_pipes( struct dc *dc, struct dc_state *context) { @@ -2772,6 +2772,10 @@ bool dcn10_disconnect_pipes( bool mpcc_disconnected = false; struct pipe_ctx *old_pipe; struct pipe_ctx *new_pipe; + + dc->hwss.wait_for_pending_cleared(dc, context); + dc->hwss.interdependent_update_lock(dc, context, true); + DC_LOGGER_INIT(dc->ctx->logger); /* Set pipe update flags and lock pipes */ @@ -2874,7 +2878,11 @@ bool dcn10_disconnect_pipes( } } } - return mpcc_disconnected; + + dc->hwss.interdependent_update_lock(dc, context, false); + + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); } void dcn10_wait_for_pending_cleared(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index e5691e4990231..9a0f7a8a85cd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -194,7 +194,7 @@ void dcn10_get_surface_visual_confirm_color( void dcn10_get_hdr_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); -bool dcn10_disconnect_pipes( +void dcn10_disconnect_pipes( struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 64c1be818b0e8..f48ee24d42f92 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,7 +67,7 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); - bool (*disconnect_pipes)(struct dc *dc, + void (*disconnect_pipes)(struct dc *dc, struct dc_state *context); void (*wait_for_pending_cleared)(struct dc *dc, struct dc_state *context); -- GitLab From fb0fe920469ac52acc315069ca9a3aa56ebd5395 Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Sat, 12 Sep 2020 13:06:59 -0400 Subject: [PATCH 1385/1494] drm/amd/display: TMDS Fallback transition [Why] HDMI requires fallback to TMDS by redetection in order to switch PHY settings. This avoids black out when link training fail during mode setting, link quality update, disable driver sequence. [How] Allow driver to redetect HDMI displays based on retraining or fallback mechanism. Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 13 +++++++++++++ drivers/gpu/drm/amd/display/dc/dc_link.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 9d7333a36facf..db741e47d194b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -159,7 +159,20 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto u8 dsc_caps[16] = { 0 }; aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); +#if defined(CONFIG_HP_HOOK_WORKAROUND) + /* + * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs + * because it only check the dsc/fec caps of the "port variable" and not the dock + * + * This case will return NULL: DSC capabe MST dock connected to a non fec/dsc capable display + * + * Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux + * + */ + if (!aconnector->dsc_aux && !port->parent->port_parent) + aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; +#endif if (!aconnector->dsc_aux) return false; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index e002ef706e1de..266b93a705d55 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -237,6 +237,8 @@ enum dc_detect_reason { DETECT_REASON_BOOT, DETECT_REASON_HPD, DETECT_REASON_HPDRX, + DETECT_REASON_FALLBACK, + DETECT_REASON_RETRAIN }; bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); -- GitLab From 3b37260be5d7686ca87d69eff1faf3e0acb384c2 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Sun, 13 Sep 2020 16:41:57 -0400 Subject: [PATCH 1386/1494] drm/amd/display: [FW Promotion] Release 0.0.34 [Header Changes] - Add new SCRATCH0 status bits for detecting restore state Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index bbcb8ed60bb63..0051b10002644 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xd0772ca1b +#define DMUB_FW_VERSION_GIT_HASH 0xf547f0b9d #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 33 +#define DMUB_FW_VERSION_REVISION 34 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -170,7 +170,7 @@ union dmub_fw_boot_status { uint32_t dal_fw : 1; uint32_t mailbox_rdy : 1; uint32_t optimized_init_done : 1; - uint32_t reserved : 29; + uint32_t restore_required : 1; } bits; uint32_t all; }; @@ -179,6 +179,7 @@ enum dmub_fw_boot_status_bit { DMUB_FW_BOOT_STATUS_BIT_DAL_FIRMWARE = (1 << 0), DMUB_FW_BOOT_STATUS_BIT_MAILBOX_READY = (1 << 1), DMUB_FW_BOOT_STATUS_BIT_OPTIMIZED_INIT_DONE = (1 << 2), + DMUB_FW_BOOT_STATUS_BIT_RESTORE_REQUIRED = (1 << 3), }; /* Register bit definition for SCRATCH15 */ @@ -301,6 +302,10 @@ enum dmub_cmd_type { DMUB_CMD__VBIOS = 128, }; +enum dmub_out_cmd_type { + DMUB_OUT_CMD__NULL = 0, +}; + #pragma pack(push, 1) struct dmub_cmd_header { -- GitLab From 3a83d33e18f3f61657528ae017581a4d697a88cd Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Mon, 14 Sep 2020 11:40:19 -0400 Subject: [PATCH 1387/1494] drm/amd/display: 3.2.104 Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d65483483d051..061ca15660ac6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.103" +#define DC_VER "3.2.104" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- GitLab From 12dbd1f7578feb51bc95e5a90eb617889cc0b04e Mon Sep 17 00:00:00 2001 From: Lewis Huang <Lewis.Huang@amd.com> Date: Wed, 16 Sep 2020 17:13:11 -0400 Subject: [PATCH 1388/1494] drm/amd/display: [FIX] update clock under two conditions [Why] Update clock only when non-seamless boot stream exists creates regression on multiple scenerios. [How] Update clock in two conditions 1. Non-seamless boot stream exist. 2. Stream_count = 0 Fixes: 598c13b21e25 ("drm/amd/display: update clock when non-seamless boot stream exist") Signed-off-by: Lewis Huang <Lewis.Huang@amd.com> Reviewed-by: Martin Leung <Martin.Leung@amd.com> Acked-by: Qingqing Zhuo <Qingqing.zhuo@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: <stable@vger.kernel.org> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1efc823c2a14c..7e74ddc1c708c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1286,7 +1286,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->optimize_seamless_boot_streams++; } - if (context->stream_count > dc->optimize_seamless_boot_streams) + if (context->stream_count > dc->optimize_seamless_boot_streams || + context->stream_count == 0) dc->hwss.prepare_bandwidth(dc, context); disable_dangling_plane(dc, context); @@ -1368,7 +1369,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc_enable_stereo(dc, context, dc_streams, context->stream_count); - if (context->stream_count > dc->optimize_seamless_boot_streams) { + if (context->stream_count > dc->optimize_seamless_boot_streams || + context->stream_count == 0) { /* Must wait for no flips to be pending before doing optimize bw */ wait_for_no_pipes_pending(dc, context); /* pplib is notified if disp_num changed */ -- GitLab From d94c8250c6ca97851678b7d87efc24b41ee58dbf Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 21 Sep 2020 21:10:11 +0800 Subject: [PATCH 1389/1494] drm/amdgpu/mes: simplify the return expression of mes_v10_1_ring_init Simplify the return expression. Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/mes_v10_1.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index 4b746584a7979..1c22d8393b21d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -832,7 +832,6 @@ static int mes_v10_1_queue_init(struct amdgpu_device *adev) static int mes_v10_1_ring_init(struct amdgpu_device *adev) { struct amdgpu_ring *ring; - int r; ring = &adev->mes.ring; @@ -849,11 +848,7 @@ static int mes_v10_1_ring_init(struct amdgpu_device *adev) ring->no_scheduler = true; sprintf(ring->name, "mes_%d.%d.%d", ring->me, ring->pipe, ring->queue); - r = amdgpu_ring_init(adev, ring, 1024, NULL, 0, AMDGPU_RING_PRIO_DEFAULT); - if (r) - return r; - - return 0; + return amdgpu_ring_init(adev, ring, 1024, NULL, 0, AMDGPU_RING_PRIO_DEFAULT); } static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev) -- GitLab From da51e50d454dbfd92f1426b5674fef5f3e229ab1 Mon Sep 17 00:00:00 2001 From: Qinglang Miao <miaoqinglang@huawei.com> Date: Mon, 21 Sep 2020 21:10:13 +0800 Subject: [PATCH 1390/1494] drm/amdgpu: simplify the return expression Simplify the return expression. Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/cik_ih.c | 7 +------ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 ++-------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index 401c99f0b2d00..db953e95f3d27 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -316,14 +316,9 @@ static int cik_ih_sw_fini(void *handle) static int cik_ih_hw_init(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = cik_ih_irq_init(adev); - if (r) - return r; - - return 0; + return cik_ih_irq_init(adev); } static int cik_ih_hw_fini(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index d898c9ff35269..9b1b5c2265d2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2196,7 +2196,6 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) static int gfx_v9_0_compute_ring_init(struct amdgpu_device *adev, int ring_id, int mec, int pipe, int queue) { - int r; unsigned irq_type; struct amdgpu_ring *ring = &adev->gfx.compute_ring[ring_id]; unsigned int hw_prio; @@ -2221,13 +2220,8 @@ static int gfx_v9_0_compute_ring_init(struct amdgpu_device *adev, int ring_id, hw_prio = amdgpu_gfx_is_high_priority_compute_queue(adev, ring->queue) ? AMDGPU_GFX_PIPE_PRIO_HIGH : AMDGPU_GFX_PIPE_PRIO_NORMAL; /* type-2 packets are deprecated on MEC, use type-3 instead */ - r = amdgpu_ring_init(adev, ring, 1024, - &adev->gfx.eop_irq, irq_type, hw_prio); - if (r) - return r; - - - return 0; + return amdgpu_ring_init(adev, ring, 1024, + &adev->gfx.eop_irq, irq_type, hw_prio); } static int gfx_v9_0_sw_init(void *handle) -- GitLab From 4a78f15fb6c906c3f8c9330ed4cc0af7a24016c4 Mon Sep 17 00:00:00 2001 From: Liu Shixin <liushixin2@huawei.com> Date: Mon, 21 Sep 2020 16:24:30 +0800 Subject: [PATCH 1391/1494] drm/amd/pm: simplify the return expression of smu_hw_fini Simplify the return expression. Signed-off-by: Liu Shixin <liushixin2@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 5c4b74f964fca..3612841d40dc9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1214,7 +1214,6 @@ static int smu_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct smu_context *smu = &adev->smu; - int ret = 0; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1230,11 +1229,7 @@ static int smu_hw_fini(void *handle) adev->pm.dpm_enabled = false; - ret = smu_smc_hw_cleanup(smu); - if (ret) - return ret; - - return 0; + return smu_smc_hw_cleanup(smu); } int smu_reset(struct smu_context *smu) -- GitLab From c24a3c0505987bc1e26723a1f1aedc6452b2a281 Mon Sep 17 00:00:00 2001 From: Liu Shixin <liushixin2@huawei.com> Date: Mon, 21 Sep 2020 16:24:29 +0800 Subject: [PATCH 1392/1494] drm/amdgpu/gmc9: simplify the return expression of gmc_v9_0_suspend Simplify the return expression. Signed-off-by: Liu Shixin <liushixin2@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 5400cac020876..cb9e9e5afa5a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1683,14 +1683,9 @@ static int gmc_v9_0_hw_fini(void *handle) static int gmc_v9_0_suspend(void *handle) { - int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = gmc_v9_0_hw_fini(adev); - if (r) - return r; - - return 0; + return gmc_v9_0_hw_fini(adev); } static int gmc_v9_0_resume(void *handle) -- GitLab From 8d89b96fe79713fc5fc2b8d9c9b9f93842b55695 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 18 Jun 2020 15:26:08 +0800 Subject: [PATCH 1393/1494] drm/amd/powerplay: optimize the mclk dpm policy settings Different mclk dpm policy will be applied based on the VRAM width. Signed-off-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index 4a3b64aa21ceb..3bf8be4d107be 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -1585,9 +1585,19 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->current_profile_setting.sclk_down_hyst = 100; data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT; data->current_profile_setting.bupdate_mclk = 1; - data->current_profile_setting.mclk_up_hyst = 0; - data->current_profile_setting.mclk_down_hyst = 100; - data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT; + if (adev->gmc.vram_width == 256) { + data->current_profile_setting.mclk_up_hyst = 10; + data->current_profile_setting.mclk_down_hyst = 60; + data->current_profile_setting.mclk_activity = 25; + } else if (adev->gmc.vram_width == 128) { + data->current_profile_setting.mclk_up_hyst = 5; + data->current_profile_setting.mclk_down_hyst = 16; + data->current_profile_setting.mclk_activity = 20; + } else if (adev->gmc.vram_width == 64) { + data->current_profile_setting.mclk_up_hyst = 3; + data->current_profile_setting.mclk_down_hyst = 16; + data->current_profile_setting.mclk_activity = 20; + } hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; -- GitLab From d117413f5e1be245b7b3e0cd6afda402609b2572 Mon Sep 17 00:00:00 2001 From: Sudheesh Mavila <sudheesh.mavila@amd.com> Date: Tue, 15 Sep 2020 12:48:20 +0530 Subject: [PATCH 1394/1494] drm/amd/pm: Removed fixed clock in auto mode DPM SMU10_UMD_PSTATE_PEAK_FCLK value should not be used to set the DPM. Suggested-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index a5d1a32ab160f..e0ac54608e88e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -563,6 +563,8 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, struct smu10_hwmgr *data = hwmgr->backend; uint32_t min_sclk = hwmgr->display_config->min_core_set_clock; uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100; + uint32_t index_fclk = data->clock_vol_info.vdd_dep_on_fclk->count - 1; + uint32_t index_socclk = data->clock_vol_info.vdd_dep_on_socclk->count - 1; if (hwmgr->smu_version < 0x1E3700) { pr_info("smu firmware version too old, can not set dpm level\n"); @@ -676,13 +678,13 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinFclkByFreq, hwmgr->display_config->num_display > 3 ? - SMU10_UMD_PSTATE_PEAK_FCLK : + data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk : min_mclk, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinSocclkByFreq, - SMU10_UMD_PSTATE_MIN_SOCCLK, + data->clock_vol_info.vdd_dep_on_socclk->entries[0].clk, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinVcn, @@ -695,11 +697,11 @@ static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMaxFclkByFreq, - SMU10_UMD_PSTATE_PEAK_FCLK, + data->clock_vol_info.vdd_dep_on_fclk->entries[index_fclk].clk, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMaxSocclkByFreq, - SMU10_UMD_PSTATE_PEAK_SOCCLK, + data->clock_vol_info.vdd_dep_on_socclk->entries[index_socclk].clk, NULL); smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMaxVcn, -- GitLab From 3f975d0f71d384825f47c3598d1d5358e40a57f5 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Tue, 15 Sep 2020 16:15:05 +0800 Subject: [PATCH 1395/1494] drm/amdgpu: update athub interrupt harvesting handle GCEA/MMHUB EA error should not result to DF freeze, this is fixed in next generation, but for some reasons the GCEA/MMHUB EA error will result to DF freeze in previous generation, diver should avoid to indicate GCEA/MMHUB EA error as hw fatal error in kernel message by read GCEA/MMHUB err status registers. Changed from V1: make query_ras_error_status function more general make read mmhub er status register more friendly Changed from V2: move ras error status query function into do_recovery workqueue Changed from V3: remove useless code from V2, print GCEA error status instance number Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 43 ++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 29 +++++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h | 2 + drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 29 +++++++++++++ .../amd/include/asic_reg/gc/gc_9_4_1_offset.h | 4 +- 8 files changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index a611e78dd4bac..258498cbf1eba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -217,6 +217,7 @@ struct amdgpu_gfx_funcs { int (*query_ras_error_count) (struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count) (struct amdgpu_device *adev); void (*init_spm_golden)(struct amdgpu_device *adev); + void (*query_ras_error_status) (struct amdgpu_device *adev); }; struct sq_work { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index 0c43d7fe893cc..1ae9bdae73114 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -40,6 +40,7 @@ struct amdgpu_mmhub_funcs { uint64_t page_table_base); void (*update_power_gating)(struct amdgpu_device *adev, bool enable); + void (*query_ras_error_status)(struct amdgpu_device *adev); }; struct amdgpu_mmhub { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e5ea14774c0cc..40614ac9a1117 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1498,6 +1498,45 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev) } } +/* Parse RdRspStatus and WrRspStatus */ +void amdgpu_ras_error_status_query(struct amdgpu_device *adev, + struct ras_query_if *info) +{ + /* + * Only two block need to query read/write + * RspStatus at current state + */ + switch (info->head.block) { + case AMDGPU_RAS_BLOCK__GFX: + if (adev->gfx.funcs->query_ras_error_status) + adev->gfx.funcs->query_ras_error_status(adev); + break; + case AMDGPU_RAS_BLOCK__MMHUB: + if (adev->mmhub.funcs->query_ras_error_status) + adev->mmhub.funcs->query_ras_error_status(adev); + break; + default: + break; + } +} + +static void amdgpu_ras_query_err_status(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_manager *obj; + + if (!con) + return; + + list_for_each_entry(obj, &con->head, node) { + struct ras_query_if info = { + .head = obj->head, + }; + + amdgpu_ras_error_status_query(adev, &info); + } +} + /* recovery begin */ /* return 0 on success. @@ -1568,8 +1607,10 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) } list_for_each_entry(remote_adev, - device_list_handle, gmc.xgmi.head) + device_list_handle, gmc.xgmi.head) { + amdgpu_ras_query_err_status(remote_adev); amdgpu_ras_log_on_err_counter(remote_adev); + } amdgpu_put_xgmi_hive(hive); } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 9b1b5c2265d2d..ed7638074085a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2075,6 +2075,7 @@ static const struct amdgpu_gfx_funcs gfx_v9_4_gfx_funcs = { .ras_error_inject = &gfx_v9_4_ras_error_inject, .query_ras_error_count = &gfx_v9_4_query_ras_error_count, .reset_ras_error_count = &gfx_v9_4_reset_ras_error_count, + .query_ras_error_status = &gfx_v9_4_query_ras_error_status, }; static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c index bd85aed3523a2..bc699d680ce8b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c @@ -992,3 +992,32 @@ int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev, void *inject_if) return ret; } + +static const struct soc15_reg_entry gfx_v9_4_rdrsp_status_regs = + { SOC15_REG_ENTRY(GC, 0, mmGCEA_ERR_STATUS), 0, 1, 32 }; + +void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev) +{ + uint32_t i, j; + uint32_t reg_value; + + if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) + return; + + mutex_lock(&adev->grbm_idx_mutex); + + for (i = 0; i < gfx_v9_4_rdrsp_status_regs.se_num; i++) { + for (j = 0; j < gfx_v9_4_rdrsp_status_regs.instance; + j++) { + gfx_v9_4_select_se_sh(adev, i, 0, j); + reg_value = RREG32(SOC15_REG_ENTRY_OFFSET( + gfx_v9_4_rdrsp_status_regs)); + if (reg_value) + dev_warn(adev->dev, "GCEA err detected at instance: %d, status: 0x%x!\n", + j, reg_value); + } + } + + gfx_v9_4_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); +} diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h index 1ffecc5c0f0a9..875f18473a981 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h @@ -34,4 +34,6 @@ int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev, void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev); +void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev); + #endif /* __GFX_V9_4_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index 6c6ad529c65c6..c2ef8142136e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -1624,6 +1624,34 @@ static void mmhub_v9_4_reset_ras_error_count(struct amdgpu_device *adev) } } +static const struct soc15_reg_entry mmhub_v9_4_err_status_regs[] = { + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA0_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA1_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA2_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA3_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA4_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA5_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA6_ERR_STATUS), 0, 0, 0 }, + { SOC15_REG_ENTRY(MMHUB, 0, mmMMEA7_ERR_STATUS), 0, 0, 0 }, +}; + +static void mmhub_v9_4_query_ras_error_status(struct amdgpu_device *adev) +{ + int i; + uint32_t reg_value; + + if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__MMHUB)) + return; + + for (i = 0; i < ARRAY_SIZE(mmhub_v9_4_err_status_regs); i++) { + reg_value = + RREG32(SOC15_REG_ENTRY_OFFSET(mmhub_v9_4_err_status_regs[i])); + if (reg_value) + dev_warn(adev->dev, "MMHUB EA err detected at instance: %d, status: 0x%x!\n", + i, reg_value); + } +} + const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = { .ras_late_init = amdgpu_mmhub_ras_late_init, .query_ras_error_count = mmhub_v9_4_query_ras_error_count, @@ -1636,4 +1664,5 @@ const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = { .set_clockgating = mmhub_v9_4_set_clockgating, .get_clockgating = mmhub_v9_4_get_clockgating, .setup_vm_pt_regs = mmhub_v9_4_setup_vm_pt_regs, + .query_ras_error_status = mmhub_v9_4_query_ras_error_status, }; diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_1_offset.h index f41556abfbbc8..629a8a3b55e92 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_1_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_4_1_offset.h @@ -205,6 +205,8 @@ #define mmGCEA_EDC_CNT2_BASE_IDX 0 #define mmGCEA_EDC_CNT3 0x071b #define mmGCEA_EDC_CNT3_BASE_IDX 0 +#define mmGCEA_ERR_STATUS 0x0712 +#define mmGCEA_ERR_STATUS_BASE_IDX 0 // addressBlock: gc_gfxudec // base address: 0x30000 @@ -261,4 +263,4 @@ #define mmRLC_EDC_CNT2 0x4d41 #define mmRLC_EDC_CNT2_BASE_IDX 1 -#endif \ No newline at end of file +#endif -- GitLab From b226ef95b6229d5c5a01f2ac220226a92f387587 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 18 Sep 2020 11:34:17 +0800 Subject: [PATCH 1396/1494] drm/amd/pm: correct the pmfw version check for Navi14 Otherwise, that will be always true for Navi14. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 985c70615944a..1695b36dc23c9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2279,13 +2279,14 @@ static int navi10_run_umc_cdr_workaround(struct smu_context *smu) } /* - * The messages below are only supported by 42.53.0 and later - * PMFWs. + * The messages below are only supported by Navi10 42.53.0 and later + * PMFWs and Navi14 53.29.0 and later PMFWs. * - PPSMC_MSG_SetDriverDummyTableDramAddrHigh * - PPSMC_MSG_SetDriverDummyTableDramAddrLow * - PPSMC_MSG_GetUMCFWWA */ - if (pmfw_version >= 0x2a3500) { + if (((adev->asic_type == CHIP_NAVI10) && (pmfw_version >= 0x2a3500)) || + ((adev->asic_type == CHIP_NAVI14) && (pmfw_version >= 0x351D00))) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GET_UMC_FW_WA, 0, -- GitLab From d152986c5189ba213d2faf8958e5b4c7a3b78682 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Fri, 18 Sep 2020 16:39:13 +0800 Subject: [PATCH 1397/1494] drm/amd/pm: decouple the watermark table setting from socclk/uclk dpms As they have no real dependence. And for Navi1x, the socclk/uclk dpms are enabled after DAL initialization. Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3612841d40dc9..7859f1911a723 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1818,17 +1818,16 @@ int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (smu->disable_watermark) + return 0; + mutex_lock(&smu->mutex); - if (!smu->disable_watermark && - smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_set_watermarks_table(smu, clock_ranges); + ret = smu_set_watermarks_table(smu, clock_ranges); - if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { - smu->watermarks_bitmap |= WATERMARKS_EXIST; - smu->watermarks_bitmap &= ~WATERMARKS_LOADED; - } + if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { + smu->watermarks_bitmap |= WATERMARKS_EXIST; + smu->watermarks_bitmap &= ~WATERMARKS_LOADED; } mutex_unlock(&smu->mutex); -- GitLab From 227e011f37d6eb621457bf9ecbf948f5daee8b12 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Mon, 21 Sep 2020 10:14:06 +0800 Subject: [PATCH 1398/1494] drm/amd/pm: drop redundant watermarks bitmap setting As this is already set inside the implementation of smu_set_watermarks_table(). Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7859f1911a723..538e6f5e19eb6 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1825,11 +1825,6 @@ int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, ret = smu_set_watermarks_table(smu, clock_ranges); - if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { - smu->watermarks_bitmap |= WATERMARKS_EXIST; - smu->watermarks_bitmap &= ~WATERMARKS_LOADED; - } - mutex_unlock(&smu->mutex); return ret; -- GitLab From b362a18ada43c4d69dd5346b96f9c7bb5f61b794 Mon Sep 17 00:00:00 2001 From: Likun Gao <Likun.Gao@amd.com> Date: Tue, 22 Sep 2020 11:10:37 +0800 Subject: [PATCH 1399/1494] drm/amd/pm: update driver if file for sienna cichlid Update driver if file for sienna cichlid. Signed-off-by: Likun Gao <Likun.Gao@amd.com> Reviewed-by: Jiansong Chen <Jiansong.Chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h | 4 ++-- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h index 11a6cf96fe0c0..1275246769d95 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x37 +#define SMU11_DRIVER_IF_VERSION 0x39 #define PPTABLE_Sienna_Cichlid_SMU_VERSION 6 @@ -962,7 +962,7 @@ typedef struct { uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; uint16_t MaxOpTemp; // Degree Celcius - uint16_t Padding_16[1]; + int16_t VddGfxOffset; // in mV uint8_t FanZeroRpmEnable; uint8_t FanZeroRpmStopTemp; uint8_t FanMode; diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 7ae83df83edbd..03198d214bbaa 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -30,7 +30,7 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x37 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x39 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x5 /* MP Apertures */ -- GitLab From 78f0aef11fdee20abfd0deec2e2ae37c72406bde Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" <Stanley.Yang@amd.com> Date: Tue, 22 Sep 2020 16:56:54 +0800 Subject: [PATCH 1400/1494] drm/amdgpu: fix hdp register access error mmHDP_READ_CACHE_INVALIDATE register is in HDP not in NBIO Signed-off-by: Stanley.Yang <Stanley.Yang@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 0ec66030bd119..bc894cfba60c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -621,7 +621,7 @@ static void nv_invalidate_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring) { if (!ring || !ring->funcs->emit_wreg) { - WREG32_SOC15_NO_KIQ(NBIO, 0, mmHDP_READ_CACHE_INVALIDATE, 1); + WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1); } else { amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET( HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1); -- GitLab From 52ef3a1a6f079727d9c66feedcadd85d4f808549 Mon Sep 17 00:00:00 2001 From: Ryan Taylor <Ryan.Taylor@amd.com> Date: Tue, 15 Sep 2020 14:16:34 -0700 Subject: [PATCH 1401/1494] drm/amdgpu: Add initial kernel documentation for the amd_ip_block_type structure. v3 Added IP block section to amdgpu.rst. Added more documentation to amd_ip_funcs. Created documentation for amd_ip_block_type. v2: Provides a more detailed DOC section on IP blocks v3: Clarifies the IP block list. Adds info on IP block enumeration. Signed-off-by: Ryan Taylor <ryan.taylor@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- Documentation/gpu/amdgpu.rst | 9 +++ drivers/gpu/drm/amd/include/amd_shared.h | 87 +++++++++++++++++------- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/Documentation/gpu/amdgpu.rst b/Documentation/gpu/amdgpu.rst index 29ca5f5feb35d..57047dcb8d19f 100644 --- a/Documentation/gpu/amdgpu.rst +++ b/Documentation/gpu/amdgpu.rst @@ -70,6 +70,15 @@ Interrupt Handling .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c :internal: +IP Blocks +------------------ + +.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h + :doc: IP Blocks + +.. kernel-doc:: drivers/gpu/drm/amd/include/amd_shared.h + :identifiers: amd_ip_block_type amd_ip_funcs + AMDGPU XGMI Support =================== diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index e98c84ef206fe..6b8a40051f417 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -47,6 +47,40 @@ enum amd_apu_flags { AMD_APU_IS_RENOIR = 0x00000008UL, }; +/** +* DOC: IP Blocks +* +* GPUs are composed of IP (intellectual property) blocks. These +* IP blocks provide various functionalities: display, graphics, +* video decode, etc. The IP blocks that comprise a particular GPU +* are listed in the GPU's respective SoC file. amdgpu_device.c +* acquires the list of IP blocks for the GPU in use on initialization. +* It can then operate on this list to perform standard driver operations +* such as: init, fini, suspend, resume, etc. +* +* +* IP block implementations are named using the following convention: +* <functionality>_v<version> (E.g.: gfx_v6_0). +*/ + +/** +* enum amd_ip_block_type - Used to classify IP blocks by functionality. +* +* @AMD_IP_BLOCK_TYPE_COMMON: GPU Family +* @AMD_IP_BLOCK_TYPE_GMC: Graphics Memory Controller +* @AMD_IP_BLOCK_TYPE_IH: Interrupt Handler +* @AMD_IP_BLOCK_TYPE_SMC: System Management Controller +* @AMD_IP_BLOCK_TYPE_PSP: Platform Security Processor +* @AMD_IP_BLOCK_TYPE_DCE: Display and Compositing Engine +* @AMD_IP_BLOCK_TYPE_GFX: Graphics and Compute Engine +* @AMD_IP_BLOCK_TYPE_SDMA: System DMA Engine +* @AMD_IP_BLOCK_TYPE_UVD: Unified Video Decoder +* @AMD_IP_BLOCK_TYPE_VCE: Video Compression Engine +* @AMD_IP_BLOCK_TYPE_ACP: Audio Co-Processor +* @AMD_IP_BLOCK_TYPE_VCN: Video Core/Codec Next +* @AMD_IP_BLOCK_TYPE_MES: Micro-Engine Scheduler +* @AMD_IP_BLOCK_TYPE_JPEG: JPEG Engine +*/ enum amd_ip_block_type { AMD_IP_BLOCK_TYPE_COMMON, AMD_IP_BLOCK_TYPE_GMC, @@ -165,56 +199,59 @@ enum DC_DEBUG_MASK { }; enum amd_dpm_forced_level; + /** * struct amd_ip_funcs - general hooks for managing amdgpu IP Blocks + * @name: Name of IP block + * @early_init: sets up early driver state (pre sw_init), + * does not configure hw - Optional + * @late_init: sets up late driver/hw state (post hw_init) - Optional + * @sw_init: sets up driver state, does not configure hw + * @sw_fini: tears down driver state, does not configure hw + * @hw_init: sets up the hw state + * @hw_fini: tears down the hw state + * @late_fini: final cleanup + * @suspend: handles IP specific hw/sw changes for suspend + * @resume: handles IP specific hw/sw changes for resume + * @is_idle: returns current IP block idle status + * @wait_for_idle: poll for idle + * @check_soft_reset: check soft reset the IP block + * @pre_soft_reset: pre soft reset the IP block + * @soft_reset: soft reset the IP block + * @post_soft_reset: post soft reset the IP block + * @set_clockgating_state: enable/disable cg for the IP block + * @set_powergating_state: enable/disable pg for the IP block + * @get_clockgating_state: get current clockgating status + * @enable_umd_pstate: enable UMD powerstate + * + * These hooks provide an interface for controlling the operational state + * of IP blocks. After acquiring a list of IP blocks for the GPU in use, + * the driver can make chip-wide state changes by walking this list and + * making calls to hooks from each IP block. This list is ordered to ensure + * that the driver initializes the IP blocks in a safe sequence. */ struct amd_ip_funcs { - /** @name: Name of IP block */ char *name; - /** - * @early_init: - * - * sets up early driver state (pre sw_init), - * does not configure hw - Optional - */ int (*early_init)(void *handle); - /** @late_init: sets up late driver/hw state (post hw_init) - Optional */ int (*late_init)(void *handle); - /** @sw_init: sets up driver state, does not configure hw */ int (*sw_init)(void *handle); - /** @sw_fini: tears down driver state, does not configure hw */ int (*sw_fini)(void *handle); - /** @hw_init: sets up the hw state */ int (*hw_init)(void *handle); - /** @hw_fini: tears down the hw state */ int (*hw_fini)(void *handle); - /** @late_fini: final cleanup */ void (*late_fini)(void *handle); - /** @suspend: handles IP specific hw/sw changes for suspend */ int (*suspend)(void *handle); - /** @resume: handles IP specific hw/sw changes for resume */ int (*resume)(void *handle); - /** @is_idle: returns current IP block idle status */ bool (*is_idle)(void *handle); - /** @wait_for_idle: poll for idle */ int (*wait_for_idle)(void *handle); - /** @check_soft_reset: check soft reset the IP block */ bool (*check_soft_reset)(void *handle); - /** @pre_soft_reset: pre soft reset the IP block */ int (*pre_soft_reset)(void *handle); - /** @soft_reset: soft reset the IP block */ int (*soft_reset)(void *handle); - /** @post_soft_reset: post soft reset the IP block */ int (*post_soft_reset)(void *handle); - /** @set_clockgating_state: enable/disable cg for the IP block */ int (*set_clockgating_state)(void *handle, enum amd_clockgating_state state); - /** @set_powergating_state: enable/disable pg for the IP block */ int (*set_powergating_state)(void *handle, enum amd_powergating_state state); - /** @get_clockgating_state: get current clockgating status */ void (*get_clockgating_state)(void *handle, u32 *flags); - /** @enable_umd_pstate: enable UMD powerstate */ int (*enable_umd_pstate)(void *handle, enum amd_dpm_forced_level *level); }; -- GitLab From 027f2d27b73cfdf9a56f9821e275fd84d5ecebb8 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Tue, 22 Sep 2020 05:40:29 -0700 Subject: [PATCH 1402/1494] drm/radeon: fix typoes in comments Change the comment typo: "programm" -> "program". Signed-off-by: Bernard Zhao <bernard@vivo.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/uvd_v1_0.c | 4 ++-- drivers/gpu/drm/radeon/uvd_v2_2.c | 2 +- drivers/gpu/drm/radeon/uvd_v4_2.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index 800721153d51a..58557c2263a72 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -117,7 +117,7 @@ int uvd_v1_0_resume(struct radeon_device *rdev) if (r) return r; - /* programm the VCPU memory controller bits 0-27 */ + /* program the VCPU memory controller bits 0-27 */ addr = (rdev->uvd.gpu_addr >> 3) + 16; size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size) >> 3; WREG32(UVD_VCPU_CACHE_OFFSET0, addr); @@ -360,7 +360,7 @@ int uvd_v1_0_start(struct radeon_device *rdev) /* Set the write pointer delay */ WREG32(UVD_RBC_RB_WPTR_CNTL, 0); - /* programm the 4GB memory segment for rptr and ring buffer */ + /* program the 4GB memory segment for rptr and ring buffer */ WREG32(UVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) | (0x7 << 16) | (0x1 << 31)); diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c index 23b18edda20e4..6266167886d9a 100644 --- a/drivers/gpu/drm/radeon/uvd_v2_2.c +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c @@ -109,7 +109,7 @@ int uvd_v2_2_resume(struct radeon_device *rdev) if (r) return r; - /* programm the VCPU memory controller bits 0-27 */ + /* program the VCPU memory controller bits 0-27 */ addr = rdev->uvd.gpu_addr >> 3; size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3; WREG32(UVD_VCPU_CACHE_OFFSET0, addr); diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c index dc54fa4aaea82..f9e97fa63674b 100644 --- a/drivers/gpu/drm/radeon/uvd_v4_2.c +++ b/drivers/gpu/drm/radeon/uvd_v4_2.c @@ -40,7 +40,7 @@ int uvd_v4_2_resume(struct radeon_device *rdev) uint64_t addr; uint32_t size; - /* programm the VCPU memory controller bits 0-27 */ + /* program the VCPU memory controller bits 0-27 */ /* skip over the header of the new firmware format */ if (rdev->uvd.fw_header_present) -- GitLab From f349f772b05cafc5ab551f645e9051bcdae8ec86 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Tue, 22 Sep 2020 05:54:18 -0700 Subject: [PATCH 1403/1494] drm/amd: fix typoes in comments Change the comment typo: "programm" -> "program". Signed-off-by: Bernard Zhao <bernard@vivo.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 770025a5e5003..7c46937c1c0ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -98,7 +98,7 @@ struct amdgpu_bo_list_entry; #define AMDGPU_PTE_MTYPE_NV10(a) ((uint64_t)(a) << 48) #define AMDGPU_PTE_MTYPE_NV10_MASK AMDGPU_PTE_MTYPE_NV10(7ULL) -/* How to programm VM fault handling */ +/* How to program VM fault handling */ #define AMDGPU_VM_FAULT_STOP_NEVER 0 #define AMDGPU_VM_FAULT_STOP_FIRST 1 #define AMDGPU_VM_FAULT_STOP_ALWAYS 2 diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 3cafba7265876..b0c0c438fc93c 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -348,7 +348,7 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) /* Set the write pointer delay */ WREG32(mmUVD_RBC_RB_WPTR_CNTL, 0); - /* programm the 4GB memory segment for rptr and ring buffer */ + /* program the 4GB memory segment for rptr and ring buffer */ WREG32(mmUVD_LMI_EXT40_ADDR, upper_32_bits(ring->gpu_addr) | (0x7 << 16) | (0x1 << 31)); @@ -541,7 +541,7 @@ static void uvd_v4_2_mc_resume(struct amdgpu_device *adev) uint64_t addr; uint32_t size; - /* programm the VCPU memory controller bits 0-27 */ + /* program the VCPU memory controller bits 0-27 */ addr = (adev->uvd.inst->gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3; size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3; WREG32(mmUVD_VCPU_CACHE_OFFSET0, addr); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index a566ff926e90d..6e57001f6d0ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -253,7 +253,7 @@ static void uvd_v5_0_mc_resume(struct amdgpu_device *adev) uint64_t offset; uint32_t size; - /* programm memory controller bits 0-27 */ + /* program memory controller bits 0-27 */ WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, lower_32_bits(adev->uvd.inst->gpu_addr)); WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, @@ -404,7 +404,7 @@ static int uvd_v5_0_start(struct amdgpu_device *adev) /* set the wb address */ WREG32(mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index ed30fb48b9dbf..666bfa4a0b8ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -583,7 +583,7 @@ static void uvd_v6_0_mc_resume(struct amdgpu_device *adev) uint64_t offset; uint32_t size; - /* programm memory controller bits 0-27 */ + /* program memory controller bits 0-27 */ WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, lower_32_bits(adev->uvd.inst->gpu_addr)); WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH, @@ -825,7 +825,7 @@ static int uvd_v6_0_start(struct amdgpu_device *adev) /* set the wb address */ WREG32(mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index e07e3fae99b5b..b44c8677ce8d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1073,7 +1073,7 @@ static int uvd_v7_0_start(struct amdgpu_device *adev) WREG32_SOC15(UVD, k, mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(UVD, k, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(UVD, k, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 927c330fad21c..73699eafb51ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -910,7 +910,7 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, @@ -1068,7 +1068,7 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 23a9eb5b2c8af..e5d29dee0c882 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -900,7 +900,7 @@ static int vcn_v2_0_start_dpg_mode(struct amdgpu_device *adev, bool indirect) WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, @@ -1060,7 +1060,7 @@ static int vcn_v2_0_start(struct amdgpu_device *adev) WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_CNTL, tmp); fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET; - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 139fac0d8e76e..0f1d3ef8baa72 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -882,7 +882,7 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2)); - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(VCN, inst_idx, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(VCN, inst_idx, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, @@ -1062,7 +1062,7 @@ static int vcn_v2_5_start(struct amdgpu_device *adev) WREG32_SOC15(VCN, i, mmUVD_RBC_RB_CNTL, tmp); fw_shared->multi_queue.decode_queue_mode |= FW_QUEUE_RING_RESET; - /* programm the RB_BASE for ring buffer */ + /* program the RB_BASE for ring buffer */ WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr)); WREG32_SOC15(VCN, i, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH, -- GitLab From 28d76d48368ca0df9a4fa14e65965d01d42e9d52 Mon Sep 17 00:00:00 2001 From: Bernard Zhao <bernard@vivo.com> Date: Mon, 21 Sep 2020 19:11:03 -0700 Subject: [PATCH 1404/1494] drm/amd/display: optimize code runtime a bit In the function dal_ddc_service_query_ddc_data, get rid of dal_ddc_i2c_payloads_destroy, call dal_vector_destruct() directly. This change is to make the code run a bit fast. Signed-off-by: Bernard Zhao <bernard@vivo.com> Changes since V1: *get rid of dal_ddc_i2c_payloads_destroy, call dal_vector_destruct() directly. Link for V1: *https://lore.kernel.org/patchwork/patch/1309014/ Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index b984eecca58b1..dec12de376422 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -148,14 +148,6 @@ static uint32_t dal_ddc_i2c_payloads_get_count(struct i2c_payloads *p) return p->payloads.count; } -static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads *p) -{ - if (!p) - return; - - dal_vector_destruct(&p->payloads); -} - #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b)) void dal_ddc_i2c_payloads_add( @@ -582,7 +574,7 @@ bool dal_ddc_service_query_ddc_data( ddc->link, &command); - dal_ddc_i2c_payloads_destroy(&payloads); + dal_vector_destruct(&payloads.payloads); } return success; -- GitLab From 10e07ca312548f90d5e0fc1d862209285c9a858c Mon Sep 17 00:00:00 2001 From: Wang Qing <wangqing@vivo.com> Date: Tue, 22 Sep 2020 19:11:37 +0800 Subject: [PATCH 1405/1494] gpu/drm/radeon: fix spelling typo in comments Modify the comment typo: "definately" -> "definitely". Signed-off-by: Wang Qing <wangqing@vivo.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/radeon/radeon_vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 71e2c3785ab9d..010fb3b7a205b 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -188,7 +188,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, vm_id->last_id_use == rdev->vm_manager.active[vm_id->id]) return NULL; - /* we definately need to flush */ + /* we definitely need to flush */ vm_id->pd_gpu_addr = ~0ll; /* skip over VMID 0, since it is the system VM */ -- GitLab From de194561359788871f7d8f5f7797557a2a166b4e Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Fri, 18 Sep 2020 16:59:17 +0200 Subject: [PATCH 1406/1494] drm/vc4: kms: Assign a FIFO to enabled CRTCs instead of active The HVS has three FIFOs that can be assigned to a number of PixelValves through a mux. However, changing that FIFO requires that we disable and then enable the pixelvalve, so we want to assign FIFOs to all the enabled CRTCs, and not just the active ones. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200918145918.101068-1-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index af3ee3dcdab61..01fa60844695f 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -643,7 +643,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); unsigned int matching_channels; - if (!crtc_state->active) + if (!crtc_state->enable) continue; /* -- GitLab From 427c4a0680a28f87bb9c7bbfeac26b39ef8682ad Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Wed, 23 Sep 2020 10:40:31 +0200 Subject: [PATCH 1407/1494] drm/vc4: crtc: Rework a bit the CRTC state code The current CRTC state reset hook in vc4 allocates a vc4_crtc_state structure as a drm_crtc_state, and relies on the fact that vc4_crtc_state embeds drm_crtc_state as its first member, and therefore can be safely cast. However, this is pretty fragile especially since there's no check for this in place, and we're going to need to access vc4_crtc_state member at reset so this looks like a good occasion to make it more robust. Fixes: 6d6e50039187 ("drm/vc4: Allocate the right amount of space for boot-time CRTC state.") Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200923084032.218619-1-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index a393f93390a2e..7ef20adedee52 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -852,11 +852,18 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, void vc4_crtc_reset(struct drm_crtc *crtc) { + struct vc4_crtc_state *vc4_crtc_state; + if (crtc->state) vc4_crtc_destroy_state(crtc, crtc->state); - crtc->state = kzalloc(sizeof(struct vc4_crtc_state), GFP_KERNEL); - if (crtc->state) - __drm_atomic_helper_crtc_reset(crtc, crtc->state); + + vc4_crtc_state = kzalloc(sizeof(*vc4_crtc_state), GFP_KERNEL); + if (!vc4_crtc_state) { + crtc->state = NULL; + return; + } + + __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base); } static const struct drm_crtc_funcs vc4_crtc_funcs = { -- GitLab From 8ba0b6d196315f68c271f549e8585129caefce97 Mon Sep 17 00:00:00 2001 From: Maxime Ripard <maxime@cerno.tech> Date: Wed, 23 Sep 2020 10:40:32 +0200 Subject: [PATCH 1408/1494] drm/vc4: crtc: Keep the previously assigned HVS FIFO The HVS FIFOs are currently assigned each time we have an atomic_check for all the enabled CRTCs. However, if we are running multiple outputs in parallel and we happen to disable the first (by index) CRTC, we end up changing the assigned FIFO of the second CRTC without disabling and reenabling the pixelvalve which ends up in a stall and eventually a VBLANK timeout. In order to fix this, we can create a special value for our assigned channel to mark it as disabled, and if our CRTC already had an assigned channel in its previous state, we keep on using it. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard <maxime@cerno.tech> Tested-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200923084032.218619-2-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 1 + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ drivers/gpu/drm/vc4/vc4_kms.c | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7ef20adedee52..482219fb4db21 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -863,6 +863,7 @@ void vc4_crtc_reset(struct drm_crtc *crtc) return; } + vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base); } diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 8c8d96b6289f4..90b911fd2a7f3 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -532,6 +532,8 @@ struct vc4_crtc_state { } margins; }; +#define VC4_HVS_CHANNEL_DISABLED ((unsigned int)-1) + static inline struct vc4_crtc_state * to_vc4_crtc_state(struct drm_crtc_state *crtc_state) { diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 01fa60844695f..149825ff5df8d 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -616,7 +616,7 @@ static int vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; int i, ret; @@ -629,6 +629,8 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) * modified. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_state *crtc_state; + if (!crtc->state->enable) continue; @@ -637,14 +639,22 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) return PTR_ERR(crtc_state); } - for_each_new_crtc_in_state(state, crtc, crtc_state, i) { - struct vc4_crtc_state *vc4_crtc_state = - to_vc4_crtc_state(crtc_state); + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct vc4_crtc_state *new_vc4_crtc_state = + to_vc4_crtc_state(new_crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); unsigned int matching_channels; - if (!crtc_state->enable) + if (old_crtc_state->enable && !new_crtc_state->enable) + new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; + + if (!new_crtc_state->enable) + continue; + + if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) { + unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel); continue; + } /* * The problem we have to solve here is that we have @@ -674,7 +684,7 @@ vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) if (matching_channels) { unsigned int channel = ffs(matching_channels) - 1; - vc4_crtc_state->assigned_channel = channel; + new_vc4_crtc_state->assigned_channel = channel; unassigned_channels &= ~BIT(channel); } else { return -EINVAL; -- GitLab From 84d244a364d3e9e115f3d189b8bd3098968eac1d Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 23 Sep 2020 11:58:23 +0800 Subject: [PATCH 1409/1494] drm/amdgpu: remove gpu_info fw support for sienna_cichlid etc. Remove gpu_info fw support for sienna_cichlid etc., since the information can be retrieved from discovery binary. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Likun Gao <Likun.Gao@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2ff43a3d52fc2..352b0a9773bee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -80,8 +80,6 @@ MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin"); -MODULE_FIRMWARE("amdgpu/sienna_cichlid_gpu_info.bin"); -MODULE_FIRMWARE("amdgpu/navy_flounder_gpu_info.bin"); #define AMDGPU_RESUME_MS 2000 @@ -1669,6 +1667,8 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) case CHIP_CARRIZO: case CHIP_STONEY: case CHIP_VEGA20: + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: default: return 0; case CHIP_VEGA10: @@ -1700,12 +1700,6 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) case CHIP_NAVI12: chip_name = "navi12"; break; - case CHIP_SIENNA_CICHLID: - chip_name = "sienna_cichlid"; - break; - case CHIP_NAVY_FLOUNDER: - chip_name = "navy_flounder"; - break; } snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name); -- GitLab From 3704cdd30aa99a4fa2551e164fe074da0e1bc1fd Mon Sep 17 00:00:00 2001 From: Flora Cui <flora.cui@amd.com> Date: Wed, 23 Sep 2020 14:42:59 +0800 Subject: [PATCH 1410/1494] drm/amd/display: fix return value check for hdcp_work max_caps might be 0, thus hdcp_work might be ZERO_SIZE_PTR Signed-off-by: Flora Cui <flora.cui@amd.com> Reviewed-by: Feifei Xu <Feifei.Xu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 694c5bc93665b..c2cd184f0bbd4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -604,7 +604,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct int i = 0; hdcp_work = kcalloc(max_caps, sizeof(*hdcp_work), GFP_KERNEL); - if (hdcp_work == NULL) + if (ZERO_OR_NULL_PTR(hdcp_work)) return NULL; hdcp_work->srm = kcalloc(PSP_HDCP_SRM_FIRST_GEN_MAX_SIZE, sizeof(*hdcp_work->srm), GFP_KERNEL); -- GitLab From 7c67d74d101324bf75a671316b6d0d861788edc9 Mon Sep 17 00:00:00 2001 From: Jingwen Chen <Jingwen.Chen2@amd.com> Date: Fri, 18 Sep 2020 11:23:09 +0800 Subject: [PATCH 1411/1494] drm/amd/pm: Skip use smc fw data in SRIOV smc fw is not needed in SRIOV, thus driver should not try to get smc fw data. Signed-off-by: Jingwen Chen <Jingwen.Chen2@amd.com> Reviewed-by: Emily.Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index b53872eb43983..d8ca6d968813d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -322,39 +322,42 @@ int smu_v11_0_setup_pptable(struct smu_context *smu) void *table; uint16_t version_major, version_minor; - hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; - version_major = le16_to_cpu(hdr->header.header_version_major); - version_minor = le16_to_cpu(hdr->header.header_version_minor); - if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || - adev->asic_type == CHIP_NAVY_FLOUNDER) { - dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); - switch (version_minor) { - case 0: - ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size); - break; - case 1: - ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size, - smu->smu_table.boot_values.pp_table_id); - break; - default: - ret = -EINVAL; - break; + if (!amdgpu_sriov_vf(adev)) { + hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; + version_major = le16_to_cpu(hdr->header.header_version_major); + version_minor = le16_to_cpu(hdr->header.header_version_minor); + if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || + adev->asic_type == CHIP_NAVY_FLOUNDER) { + dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); + switch (version_minor) { + case 0: + ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size); + break; + case 1: + ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size, + smu->smu_table.boot_values.pp_table_id); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + return ret; + goto out; } - if (ret) - return ret; + } - } else { - dev_info(adev->dev, "use vbios provided pptable\n"); - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - powerplayinfo); + dev_info(adev->dev, "use vbios provided pptable\n"); + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + powerplayinfo); - ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev, - (uint8_t **)&table); - if (ret) - return ret; - size = atom_table_size; - } + ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev, + (uint8_t **)&table); + if (ret) + return ret; + size = atom_table_size; +out: if (!smu->smu_table.power_play_table) smu->smu_table.power_play_table = table; if (!smu->smu_table.power_play_table_size) -- GitLab From 162b786f0fdac97afe27879c9120ff59b383f8f3 Mon Sep 17 00:00:00 2001 From: Jingwen Chen <Jingwen.Chen2@amd.com> Date: Fri, 18 Sep 2020 17:43:49 +0800 Subject: [PATCH 1412/1494] drm/amd: Skip not used microcode loading in SRIOV smc, sdma, sos, ta and asd fw is not used in SRIOV. Skip them to accelerate sw_init for navi12. v2: skip above fw in SRIOV for vega10 and sienna_cichlid v3: directly skip psp fw loading in SRIOV Signed-off-by: Jingwen Chen <Jingwen.Chen2@amd.com> Reviewed-by: Emily.Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 10 ++++++---- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 3 +++ drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 3 +++ drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 3 +++ .../gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c | 12 +++++++----- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 11 +++++++---- 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 2c66e20b2ed9a..18be544d8c1ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -161,10 +161,12 @@ static int psp_sw_init(void *handle) struct psp_context *psp = &adev->psp; int ret; - ret = psp_init_microcode(psp); - if (ret) { - DRM_ERROR("Failed to load psp firmware!\n"); - return ret; + if (!amdgpu_sriov_vf(adev)) { + ret = psp_init_microcode(psp); + if (ret) { + DRM_ERROR("Failed to load psp firmware!\n"); + return ret; + } } ret = psp_memory_training_init(psp); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 810635cbf4c15..86fb1eddf5a6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -592,6 +592,9 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev) struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL; + if (amdgpu_sriov_vf(adev)) + return 0; + DRM_DEBUG("\n"); switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 48c95a78a1739..9c72b95b74639 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -203,6 +203,9 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) const struct common_firmware_header *header = NULL; const struct sdma_firmware_header_v1_0 *hdr; + if (amdgpu_sriov_vf(adev)) + return 0; + DRM_DEBUG("\n"); switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 34ccf376ee45e..9f3952723c63c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -148,6 +148,9 @@ static int sdma_v5_2_init_microcode(struct amdgpu_device *adev) struct amdgpu_firmware_info *info = NULL; const struct common_firmware_header *header = NULL; + if (amdgpu_sriov_vf(adev)) + return 0; + DRM_DEBUG("\n"); switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c index 1e222c5d91a45..daf122f24f230 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c @@ -209,11 +209,13 @@ static int vega10_smu_init(struct pp_hwmgr *hwmgr) int ret; struct cgs_firmware_info info = {0}; - ret = cgs_get_firmware_info(hwmgr->device, - CGS_UCODE_ID_SMU, - &info); - if (ret || !info.kptr) - return -EINVAL; + if (!amdgpu_sriov_vf((struct amdgpu_device *)hwmgr->adev)) { + ret = cgs_get_firmware_info(hwmgr->device, + CGS_UCODE_ID_SMU, + &info); + if (ret || !info.kptr) + return -EINVAL; + } priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 538e6f5e19eb6..3010cb31324ab 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -832,10 +832,13 @@ static int smu_sw_init(void *handle) smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - ret = smu_init_microcode(smu); - if (ret) { - dev_err(adev->dev, "Failed to load smu firmware!\n"); - return ret; + + if (!amdgpu_sriov_vf(adev)) { + ret = smu_init_microcode(smu); + if (ret) { + dev_err(adev->dev, "Failed to load smu firmware!\n"); + return ret; + } } ret = smu_smc_table_sw_init(smu); -- GitLab From 884dcf3c8788a977842733bbac5f5c5f349724ac Mon Sep 17 00:00:00 2001 From: "Emily.Deng" <Emily.Deng@amd.com> Date: Wed, 23 Sep 2020 16:36:35 +0800 Subject: [PATCH 1413/1494] drm/amdgpu: Remove some useless code Signed-off-by: Emily.Deng <Emily.Deng@amd.com> Reviewed-by: Frank Min <Frank.Min@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 5 ----- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 5 ----- drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h | 13 ------------- .../gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c | 7 ------- 4 files changed, 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index b882ac59879a0..0905d63979724 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -153,11 +153,6 @@ static void gfxhub_v2_0_init_system_aperture_regs(struct amdgpu_device *adev) uint64_t value; if (!amdgpu_sriov_vf(adev)) { - /* - * the new L1 policy will block SRIOV guest from writing - * these regs, and they will be programed at host. - * so skip programing these regs. - */ /* Disable AGP. */ WREG32_SOC15(GC, 0, mmGCMC_VM_AGP_BASE, 0); WREG32_SOC15(GC, 0, mmGCMC_VM_AGP_TOP, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 2d88278c50bf7..5241fa9912485 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -201,11 +201,6 @@ static void mmhub_v2_0_init_system_aperture_regs(struct amdgpu_device *adev) WREG32_SOC15(MMHUB, 0, mmMMMC_VM_AGP_BOT, 0x00FFFFFF); if (!amdgpu_sriov_vf(adev)) { - /* - * the new L1 policy will block SRIOV guest from writing - * these regs, and they will be programed at host. - * so skip programing these regs. - */ /* Program the system aperture low logical page number. */ WREG32_SOC15(MMHUB, 0, mmMMMC_VM_SYSTEM_APERTURE_LOW_ADDR, adev->gmc.vram_start >> 18); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h index cbc04a5c0fe1d..1ef2f5b1d8284 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h @@ -83,19 +83,6 @@ struct psp_gfx_ctrl */ #define GFX_FLAG_RESPONSE 0x80000000 -/* Gbr IH registers ID */ -enum ih_reg_id { - IH_RB = 0, // IH_RB_CNTL - IH_RB_RNG1 = 1, // IH_RB_CNTL_RING1 - IH_RB_RNG2 = 2, // IH_RB_CNTL_RING2 -}; - -/* Command to setup Gibraltar IH register */ -struct psp_gfx_cmd_gbr_ih_reg { - uint32_t reg_value; /* Value to be set to the IH_RB_CNTL... register*/ - enum ih_reg_id reg_id; /* ID of the register */ -}; - /* TEE Gfx Command IDs for the ring buffer interface. */ enum psp_gfx_cmd_id { diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c index adfbcbe5d113a..8a9aee85043ec 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c @@ -61,9 +61,6 @@ static uint32_t smu9_wait_for_response(struct pp_hwmgr *hwmgr) uint32_t reg; uint32_t ret; - /* Due to the L1 policy problem under SRIOV, we have to use - * mmMP1_SMN_C2PMSG_103 as the driver response register - */ if (hwmgr->pp_one_vf) { reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_103); @@ -148,10 +145,6 @@ int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, smu9_wait_for_response(hwmgr); - /* Due to the L1 policy problem under SRIOV, we have to use - * mmMP1_SMN_C2PMSG_101 as the driver message register and - * mmMP1_SMN_C2PMSG_102 as the driver parameter register. - */ if (hwmgr->pp_one_vf) { WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0); WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102, parameter); -- GitLab From 2fbb84ff160cb9418d5768b5d9422baadcb6cbf8 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 22 Sep 2020 11:34:16 -0400 Subject: [PATCH 1414/1494] drm/amdgpu/display: fix CFLAGS setup for DCN30 Properly handle clang and older versions of gcc. Fixes: e77165bf7b02a3 ("drm/amd/display: Add DCN3 blocks to Makefile") Acked-by: Nirmoy Das <nirmoy.das@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index 025637a83c3ba..bd2a068f98635 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -31,9 +31,21 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \ dcn30_dio_link_encoder.o dcn30_resource.o -CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse -mpreferred-stack-boundary=4 - +ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -msse +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse +endif + +ifdef CONFIG_PPC64 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec +endif + +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mgeneral-regs-only +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -45,8 +57,10 @@ ifdef IS_OLD_GCC # GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 # (8B stack alignment). CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4 else CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2 endif AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30)) -- GitLab From 9b498efae29f86d53fbd44845324f0f0faae5ff2 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 23 Sep 2020 09:37:39 -0400 Subject: [PATCH 1415/1494] drm/amdgpu: store noretry parameter per driver instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow us to have different defaults per asic in a future patch. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 7 +++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 14 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 ++ .../drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 ++ 16 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 53d5aa2d96bfa..3c0e43f548fbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -581,6 +581,13 @@ uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd) return adev->rev_id; } +int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)kgd; + + return adev->gmc.noretry; +} + int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, uint32_t vmid, uint64_t gpu_addr, uint32_t *ib_cmd, uint32_t ib_len) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index a10507ecb7508..bc9f0e42e0a29 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -181,6 +181,7 @@ uint64_t amdgpu_amdkfd_get_unique_id(struct kgd_dev *kgd); uint64_t amdgpu_amdkfd_get_mmio_remap_phys_addr(struct kgd_dev *kgd); uint32_t amdgpu_amdkfd_get_num_gws(struct kgd_dev *kgd); uint32_t amdgpu_amdkfd_get_asic_rev_id(struct kgd_dev *kgd); +int amdgpu_amdkfd_get_noretry(struct kgd_dev *kgd); uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *src); /* Read user wptr from a specified user address space with page fault diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 352b0a9773bee..de3608902bd8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1265,6 +1265,8 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n"); } + amdgpu_gmc_noretry_set(adev); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 213ef090bb0e8..3572629fef0a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -413,6 +413,20 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) } } +/** + * amdgpu_noretry_set -- set per asic noretry defaults + * @adev: amdgpu_device pointer + * + * Set a per asic default for the no-retry parameter. + * + */ +void amdgpu_gmc_noretry_set(struct amdgpu_device *adev) +{ + struct amdgpu_gmc *gmc = &adev->gmc; + + gmc->noretry = amdgpu_noretry; +} + void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, bool enable) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index d61bbde4c7d2c..aa0c83776ce0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -239,6 +239,7 @@ struct amdgpu_gmc { struct amdgpu_xgmi xgmi; struct amdgpu_irq_src ecc_irq; + int noretry; }; #define amdgpu_gmc_flush_gpu_tlb(adev, vmid, vmhub, type) ((adev)->gmc.gmc_funcs->flush_gpu_tlb((adev), (vmid), (vmhub), (type))) @@ -300,6 +301,7 @@ void amdgpu_gmc_ras_fini(struct amdgpu_device *adev); int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev); extern void amdgpu_gmc_tmz_set(struct amdgpu_device *adev); +extern void amdgpu_gmc_noretry_set(struct amdgpu_device *adev); extern void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index bccaf4f77647a..a5aaff15f7ec0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -177,7 +177,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) break; case CHIP_VEGA10: /* turn runpm on if noretry=0 */ - if (!amdgpu_noretry) + if (!adev->gmc.noretry) adev->runpm = true; break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ed7638074085a..346d8288f6ab1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2555,14 +2555,14 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev) tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, ALIGNMENT_MODE, SH_MEM_ALIGNMENT_MODE_UNALIGNED); tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, RETRY_DISABLE, - !!amdgpu_noretry); + !!adev->gmc.noretry); WREG32_SOC15_RLC(GC, 0, mmSH_MEM_CONFIG, tmp); WREG32_SOC15_RLC(GC, 0, mmSH_MEM_BASES, 0); } else { tmp = REG_SET_FIELD(0, SH_MEM_CONFIG, ALIGNMENT_MODE, SH_MEM_ALIGNMENT_MODE_UNALIGNED); tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, RETRY_DISABLE, - !!amdgpu_noretry); + !!adev->gmc.noretry); WREG32_SOC15_RLC(GC, 0, mmSH_MEM_CONFIG, tmp); tmp = REG_SET_FIELD(0, SH_MEM_BASES, PRIVATE_BASE, (adev->gmc.private_aperture_start >> 48)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 529e46386a507..40b17da6a357e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -245,7 +245,7 @@ static void gfxhub_v1_0_setup_vmid_config(struct amdgpu_device *adev) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_CNTL, i * hub->ctx_distance, tmp); WREG32_SOC15_OFFSET(GC, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 0905d63979724..d623aeba08d5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -313,7 +313,7 @@ static void gfxhub_v2_0_setup_vmid_config(struct amdgpu_device *adev) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i * hub->ctx_distance, tmp); WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 237a9ff5afa0b..6dc7a040ed7f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -319,7 +319,7 @@ static void gfxhub_v2_1_setup_vmid_config(struct amdgpu_device *adev) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_CNTL, i * hub->ctx_distance, tmp); WREG32_SOC15_OFFSET(GC, 0, mmGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 45a902b1acb77..f84701c562bf2 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -268,7 +268,7 @@ static void mmhub_v1_0_setup_vmid_config(struct amdgpu_device *adev) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_CNTL, i * hub->ctx_distance, tmp); WREG32_SOC15_OFFSET(MMHUB, 0, mmVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 5241fa9912485..2063700f0bc62 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -369,7 +369,7 @@ static void mmhub_v2_0_setup_vmid_config(struct amdgpu_device *adev) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, MMVM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_CNTL, i * hub->ctx_distance, tmp); WREG32_SOC15_OFFSET(MMHUB, 0, mmMMVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index c2ef8142136e9..66748bb01b525 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -330,7 +330,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid) /* Send no-retry XNACK on fault to suppress VM fault storm. */ tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL, RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, - !amdgpu_noretry); + !adev->gmc.noretry); WREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT1_CNTL, hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i * hub->ctx_distance, tmp); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 135001a404bc7..903170e59342c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -718,6 +718,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd); + kfd->noretry = amdgpu_amdkfd_get_noretry(kfd->kgd); + if (kfd_interrupt_init(kfd)) { dev_err(kfd_device, "Error initializing interrupts\n"); goto kfd_interrupt_error; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 309f63a0b34a1..eca6331efa949 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -61,7 +61,7 @@ static int update_qpd_v9(struct device_queue_manager *dqm, qpd->sh_mem_config = SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; - if (amdgpu_noretry && + if (dqm->dev->noretry && !dqm->dev->use_iommu_v2) qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 739db04080d0f..56f92cfff591a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -317,6 +317,8 @@ struct kfd_dev { struct ida doorbell_ida; unsigned int max_doorbell_slices; + + int noretry; }; enum kfd_mempool { -- GitLab From d5cc02d97ab125b62075ad296e4dca9a7fc54c9b Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Wed, 23 Sep 2020 09:50:24 -0400 Subject: [PATCH 1416/1494] drm/amdgpu: add an auto setting to the noretry parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to set different defaults on a per asic basis. This way we can enable noretry on dGPUs where it can increase performance in certain cases and disable it on chips where it can be problematic. For now the default is 0 for all asics, but we may want to try and enable it again for newer dGPUs. Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 26 ++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a4b518211b1f8..f3e2fbcfadfbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -147,7 +147,7 @@ int amdgpu_async_gfx_ring = 1; int amdgpu_mcbp = 0; int amdgpu_discovery = -1; int amdgpu_mes = 0; -int amdgpu_noretry; +int amdgpu_noretry = -1; int amdgpu_force_asic_type = -1; int amdgpu_tmz = 0; int amdgpu_reset_method = -1; /* auto */ @@ -596,8 +596,13 @@ MODULE_PARM_DESC(mes, "Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)"); module_param_named(mes, amdgpu_mes, int, 0444); +/** + * DOC: noretry (int) + * Disable retry faults in the GPU memory controller. + * (0 = retry enabled, 1 = retry disabled, -1 auto (default)) + */ MODULE_PARM_DESC(noretry, - "Disable retry faults (0 = retry enabled (default), 1 = retry disabled)"); + "Disable retry faults (0 = retry enabled, 1 = retry disabled, -1 auto (default))"); module_param_named(noretry, amdgpu_noretry, int, 0644); /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 3572629fef0a3..36604d751d622 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -424,7 +424,31 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev) { struct amdgpu_gmc *gmc = &adev->gmc; - gmc->noretry = amdgpu_noretry; + switch (adev->asic_type) { + case CHIP_RAVEN: + /* Raven currently has issues with noretry + * regardless of what we decide for other + * asics, we should leave raven with + * noretry = 0 until we root cause the + * issues. + */ + if (amdgpu_noretry == -1) + gmc->noretry = 0; + else + gmc->noretry = amdgpu_noretry; + break; + default: + /* default this to 0 for now, but we may want + * to change this in the future for certain + * GPUs as it can increase performance in + * certain cases. + */ + if (amdgpu_noretry == -1) + gmc->noretry = 0; + else + gmc->noretry = amdgpu_noretry; + break; + } } void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, -- GitLab From 265c280a4807419249644156654e5c40a235ea84 Mon Sep 17 00:00:00 2001 From: John Clements <john.clements@amd.com> Date: Thu, 24 Sep 2020 22:20:31 +0800 Subject: [PATCH 1417/1494] drm/amdgpu: disable sienna chichlid UMC RAS disable UMC RAS in lieu of stability issues on certain sku Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: John Clements <john.clements@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 40614ac9a1117..7f79d25fbccc2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2008,8 +2008,7 @@ static int amdgpu_ras_check_asic_type(struct amdgpu_device *adev) { if (adev->asic_type != CHIP_VEGA10 && adev->asic_type != CHIP_VEGA20 && - adev->asic_type != CHIP_ARCTURUS && - adev->asic_type != CHIP_SIENNA_CICHLID) + adev->asic_type != CHIP_ARCTURUS) return 1; else return 0; @@ -2053,6 +2052,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = amdgpu_ras_enable == 0 ? 0 : *hw_supported & amdgpu_ras_mask; + adev->ras_features = *supported; } -- GitLab From 549750a383bf1c6a4a8ba3634c85e00e7f4585da Mon Sep 17 00:00:00 2001 From: Ryan Taylor <ryan.taylor@amd.com> Date: Thu, 17 Sep 2020 17:19:33 -0700 Subject: [PATCH 1418/1494] drm/include: add PP_FEATURE_MASK comments (v3) Documents PP_FEATURE_MASK enum. Provides instructions on how to use ppfeaturemasks. v2: improve enum definitions and add kernel command line parameters to ppfeaturemask instructions v3: fix alignment issues Signed-off-by: Ryan Taylor <ryan.taylor@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/include/amd_shared.h | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 6b8a40051f417..10dc481ecbc4b 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -162,6 +162,34 @@ enum amd_powergating_state { #define AMD_PG_SUPPORT_ATHUB (1 << 16) #define AMD_PG_SUPPORT_JPEG (1 << 17) +/** + * enum PP_FEATURE_MASK - Used to mask power play features. + * + * @PP_SCLK_DPM_MASK: Dynamic adjustment of the system (graphics) clock. + * @PP_MCLK_DPM_MASK: Dynamic adjustment of the memory clock. + * @PP_PCIE_DPM_MASK: Dynamic adjustment of PCIE clocks and lanes. + * @PP_SCLK_DEEP_SLEEP_MASK: System (graphics) clock deep sleep. + * @PP_POWER_CONTAINMENT_MASK: Power containment. + * @PP_UVD_HANDSHAKE_MASK: Unified video decoder handshake. + * @PP_SMC_VOLTAGE_CONTROL_MASK: Dynamic voltage control. + * @PP_VBI_TIME_SUPPORT_MASK: Vertical blank interval support. + * @PP_ULV_MASK: Ultra low voltage. + * @PP_ENABLE_GFX_CG_THRU_SMU: SMU control of GFX engine clockgating. + * @PP_CLOCK_STRETCH_MASK: Clock stretching. + * @PP_OD_FUZZY_FAN_CONTROL_MASK: Overdrive fuzzy fan control. + * @PP_SOCCLK_DPM_MASK: Dynamic adjustment of the SoC clock. + * @PP_DCEFCLK_DPM_MASK: Dynamic adjustment of the Display Controller Engine Fabric clock. + * @PP_OVERDRIVE_MASK: Over- and under-clocking support. + * @PP_GFXOFF_MASK: Dynamic graphics engine power control. + * @PP_ACG_MASK: Adaptive clock generator. + * @PP_STUTTER_MODE: Stutter mode. + * @PP_AVFS_MASK: Adaptive voltage and frequency scaling. + * + * To override these settings on boot, append amdgpu.ppfeaturemask=<mask> to + * the kernel's command line parameters. This is usually done through a system's + * boot loader (E.g. GRUB). If manually loading the driver, pass + * ppfeaturemask=<mask> as a modprobe parameter. + */ enum PP_FEATURE_MASK { PP_SCLK_DPM_MASK = 0x1, PP_MCLK_DPM_MASK = 0x2, -- GitLab From 1721bc1b2afaefbd880b4606f5147b4ff487904c Mon Sep 17 00:00:00 2001 From: Bokun Zhang <Bokun.Zhang@amd.com> Date: Wed, 15 Jul 2020 19:46:26 -0400 Subject: [PATCH 1419/1494] drm/amdgpu: Update VF2PF interface - Update guest side VF2PF interface header file Signed-off-by: Bokun Zhang <Bokun.Zhang@amd.com> Reviewed-by: Monk Liu <monk.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 29 +- drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 276 ++++++++++++++++++++ 2 files changed, 285 insertions(+), 20 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index b2046c3a404de..082fb0736645c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -24,6 +24,8 @@ #ifndef AMDGPU_VIRT_H #define AMDGPU_VIRT_H +#include "amdgv_sriovmsg.h" + #define AMDGPU_SRIOV_CAPS_SRIOV_VBIOS (1 << 0) /* vBIOS is sr-iov ready */ #define AMDGPU_SRIOV_CAPS_ENABLE_IOV (1 << 1) /* sr-iov is enabled on this GPU */ #define AMDGPU_SRIOV_CAPS_IS_VF (1 << 2) /* this GPU is a virtual function */ @@ -79,7 +81,10 @@ struct amdgpu_virt_fw_reserve { struct amd_sriov_msg_vf2pf_info_header *p_vf2pf; unsigned int checksum_key; }; + /* + * Legacy GIM header + * * Defination between PF and VF * Structures forcibly aligned to 4 to keep the same style as PF. */ @@ -101,15 +106,7 @@ enum AMDGIM_FEATURE_FLAG { AMDGIM_FEATURE_PP_ONE_VF = (1 << 4), }; -struct amd_sriov_msg_pf2vf_info_header { - /* the total structure size in byte. */ - uint32_t size; - /* version of this structure, written by the GIM */ - uint32_t version; - /* reserved */ - uint32_t reserved[2]; -} __aligned(4); -struct amdgim_pf2vf_info_v1 { +struct amdgim_pf2vf_info_v1 { /* header contains size and version */ struct amd_sriov_msg_pf2vf_info_header header; /* max_width * max_height */ @@ -128,6 +125,7 @@ struct amdgim_pf2vf_info_v1 { unsigned int checksum; } __aligned(4); +/* TODO: below struct is duplicated to amd_sriov_msg_pf2vf_info */ struct amdgim_pf2vf_info_v2 { /* header contains size and version */ struct amd_sriov_msg_pf2vf_info_header header; @@ -166,16 +164,6 @@ struct amdgim_pf2vf_info_v2 { uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (18 + sizeof(struct amd_sriov_msg_pf2vf_info_header)/sizeof(uint32_t)), 0)]; } __aligned(4); - -struct amd_sriov_msg_vf2pf_info_header { - /* the total structure size in byte. */ - uint32_t size; - /*version of this structure, written by the guest */ - uint32_t version; - /* reserved */ - uint32_t reserved[2]; -} __aligned(4); - struct amdgim_vf2pf_info_v1 { /* header contains size and version */ struct amd_sriov_msg_vf2pf_info_header header; @@ -237,8 +225,9 @@ struct amdgim_vf2pf_info_v2 { uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amd_sriov_msg_vf2pf_info_header)/sizeof(uint32_t)), 0)]; } __aligned(4); +/* TODO: below macro and typedef will cause compile error, need to remove */ #define AMDGPU_FW_VRAM_VF2PF_VER 2 -typedef struct amdgim_vf2pf_info_v2 amdgim_vf2pf_info ; +typedef struct amd_sriov_msg_vf2pf_info amdgim_vf2pf_info; #define AMDGPU_FW_VRAM_VF2PF_WRITE(adev, field, val) \ do { \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h new file mode 100644 index 0000000000000..5355827ed0ae6 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -0,0 +1,276 @@ +/* + * Copyright 2018-2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef AMDGV_SRIOV_MSG__H_ +#define AMDGV_SRIOV_MSG__H_ + +/* unit in kilobytes */ +#define AMD_SRIOV_MSG_VBIOS_OFFSET 0 +#define AMD_SRIOV_MSG_VBIOS_SIZE_KB 64 +#define AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB AMD_SRIOV_MSG_VBIOS_SIZE_KB +#define AMD_SRIOV_MSG_DATAEXCHANGE_SIZE_KB 4 + +/* + * layout + * 0 64KB 65KB 66KB + * | VBIOS | PF2VF | VF2PF | Bad Page | ... + * | 64KB | 1KB | 1KB | + */ +#define AMD_SRIOV_MSG_SIZE_KB 1 +#define AMD_SRIOV_MSG_PF2VF_OFFSET_KB AMD_SRIOV_MSG_DATAEXCHANGE_OFFSET_KB +#define AMD_SRIOV_MSG_VF2PF_OFFSET_KB (AMD_SRIOV_MSG_PF2VF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB) +#define AMD_SRIOV_MSG_BAD_PAGE_OFFSET_KB (AMD_SRIOV_MSG_VF2PF_OFFSET_KB + AMD_SRIOV_MSG_SIZE_KB) + +/* + * PF2VF history log: + * v1 defined in amdgim + * v2 current + * + * VF2PF history log: + * v1 defined in amdgim + * v2 defined in amdgim + * v3 current + */ +#define AMD_SRIOV_MSG_FW_VRAM_PF2VF_VER 2 +#define AMD_SRIOV_MSG_FW_VRAM_VF2PF_VER 3 + +#define AMD_SRIOV_MSG_RESERVE_UCODE 24 + +enum amd_sriov_ucode_engine_id { + AMD_SRIOV_UCODE_ID_VCE = 0, + AMD_SRIOV_UCODE_ID_UVD, + AMD_SRIOV_UCODE_ID_MC, + AMD_SRIOV_UCODE_ID_ME, + AMD_SRIOV_UCODE_ID_PFP, + AMD_SRIOV_UCODE_ID_CE, + AMD_SRIOV_UCODE_ID_RLC, + AMD_SRIOV_UCODE_ID_RLC_SRLC, + AMD_SRIOV_UCODE_ID_RLC_SRLG, + AMD_SRIOV_UCODE_ID_RLC_SRLS, + AMD_SRIOV_UCODE_ID_MEC, + AMD_SRIOV_UCODE_ID_MEC2, + AMD_SRIOV_UCODE_ID_SOS, + AMD_SRIOV_UCODE_ID_ASD, + AMD_SRIOV_UCODE_ID_TA_RAS, + AMD_SRIOV_UCODE_ID_TA_XGMI, + AMD_SRIOV_UCODE_ID_SMC, + AMD_SRIOV_UCODE_ID_SDMA, + AMD_SRIOV_UCODE_ID_SDMA2, + AMD_SRIOV_UCODE_ID_VCN, + AMD_SRIOV_UCODE_ID_DMCU, + AMD_SRIOV_UCODE_ID__MAX +}; + +#pragma pack(push, 1) // PF2VF / VF2PF data areas are byte packed + +union amd_sriov_msg_feature_flags { + struct { + uint32_t error_log_collect : 1; + uint32_t host_load_ucodes : 1; + uint32_t host_flr_vramlost : 1; + uint32_t mm_bw_management : 1; + uint32_t pp_one_vf_mode : 1; + uint32_t reserved : 27; + } flags; + uint32_t all; +}; + +union amd_sriov_msg_os_info { + struct { + uint32_t windows : 1; + uint32_t reserved : 31; + } info; + uint32_t all; +}; + +struct amd_sriov_msg_pf2vf_info_header { + /* the total structure size in byte */ + uint32_t size; + /* version of this structure, written by the HOST */ + uint32_t version; + /* reserved */ + uint32_t reserved[2]; +}; + +struct amd_sriov_msg_pf2vf_info { + /* header contains size and version */ + struct amd_sriov_msg_pf2vf_info_header header; + /* use private key from mailbox 2 to create checksum */ + uint32_t checksum; + /* The features flags of the HOST driver supports */ + union amd_sriov_msg_feature_flags feature_flags; + /* (max_width * max_height * fps) / (16 * 16) */ + uint32_t hevc_enc_max_mb_per_second; + /* (max_width * max_height) / (16 * 16) */ + uint32_t hevc_enc_max_mb_per_frame; + /* (max_width * max_height * fps) / (16 * 16) */ + uint32_t avc_enc_max_mb_per_second; + /* (max_width * max_height) / (16 * 16) */ + uint32_t avc_enc_max_mb_per_frame; + /* MEC FW position in BYTE from the start of VF visible frame buffer */ + uint64_t mecfw_offset; + /* MEC FW size in BYTE */ + uint32_t mecfw_size; + /* UVD FW position in BYTE from the start of VF visible frame buffer */ + uint64_t uvdfw_offset; + /* UVD FW size in BYTE */ + uint32_t uvdfw_size; + /* VCE FW position in BYTE from the start of VF visible frame buffer */ + uint64_t vcefw_offset; + /* VCE FW size in BYTE */ + uint32_t vcefw_size; + /* Bad pages block position in BYTE */ + uint32_t bp_block_offset_low; + uint32_t bp_block_offset_high; + /* Bad pages block size in BYTE */ + uint32_t bp_block_size; + /* frequency for VF to update the VF2PF area in msec, 0 = manual */ + uint32_t vf2pf_update_interval_ms; + /* identification in ROCm SMI */ + uint64_t uuid; + uint32_t fcn_idx; + /* reserved */ + uint32_t reserved[256-26]; +}; + +struct amd_sriov_msg_vf2pf_info_header { + /* the total structure size in byte */ + uint32_t size; + /* version of this structure, written by the guest */ + uint32_t version; + /* reserved */ + uint32_t reserved[2]; +}; + +struct amd_sriov_msg_vf2pf_info { + /* header contains size and version */ + struct amd_sriov_msg_vf2pf_info_header header; + uint32_t checksum; + /* driver version */ + uint8_t driver_version[64]; + /* driver certification, 1=WHQL, 0=None */ + uint32_t driver_cert; + /* guest OS type and version */ + union amd_sriov_msg_os_info os_info; + /* guest fb information in the unit of MB */ + uint32_t fb_usage; + /* guest gfx engine usage percentage */ + uint32_t gfx_usage; + /* guest gfx engine health percentage */ + uint32_t gfx_health; + /* guest compute engine usage percentage */ + uint32_t compute_usage; + /* guest compute engine health percentage */ + uint32_t compute_health; + /* guest avc engine usage percentage. 0xffff means N/A */ + uint32_t avc_enc_usage; + /* guest avc engine health percentage. 0xffff means N/A */ + uint32_t avc_enc_health; + /* guest hevc engine usage percentage. 0xffff means N/A */ + uint32_t hevc_enc_usage; + /* guest hevc engine usage percentage. 0xffff means N/A */ + uint32_t hevc_enc_health; + /* combined encode/decode usage */ + uint32_t encode_usage; + uint32_t decode_usage; + /* Version of PF2VF that VF understands */ + uint32_t pf2vf_version_required; + /* additional FB usage */ + uint32_t fb_vis_usage; + uint32_t fb_vis_size; + uint32_t fb_size; + /* guest ucode data, each one is 1.25 Dword */ + struct { + uint8_t id; + uint32_t version; + } ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE]; + + /* reserved */ + uint32_t reserved[256-68]; +}; + +/* mailbox message send from guest to host */ +enum amd_sriov_mailbox_request_message { + MB_REQ_MSG_REQ_GPU_INIT_ACCESS = 1, + MB_REQ_MSG_REL_GPU_INIT_ACCESS, + MB_REQ_MSG_REQ_GPU_FINI_ACCESS, + MB_REQ_MSG_REL_GPU_FINI_ACCESS, + MB_REQ_MSG_REQ_GPU_RESET_ACCESS, + MB_REQ_MSG_REQ_GPU_INIT_DATA, + + MB_REQ_MSG_LOG_VF_ERROR = 200, +}; + +/* mailbox message send from host to guest */ +enum amd_sriov_mailbox_response_message { + MB_RES_MSG_CLR_MSG_BUF = 0, + MB_RES_MSG_READY_TO_ACCESS_GPU = 1, + MB_RES_MSG_FLR_NOTIFICATION, + MB_RES_MSG_FLR_NOTIFICATION_COMPLETION, + MB_RES_MSG_SUCCESS, + MB_RES_MSG_FAIL, + MB_RES_MSG_QUERY_ALIVE, + MB_RES_MSG_GPU_INIT_DATA_READY, + + MB_RES_MSG_TEXT_MESSAGE = 255 +}; + +/* version data stored in MAILBOX_MSGBUF_RCV_DW1 for future expansion */ +enum amd_sriov_gpu_init_data_version { + GPU_INIT_DATA_READY_V1 = 1, +}; + +#pragma pack(pop) // Restore previous packing option + +/* checksum function between host and guest */ +unsigned int amd_sriov_msg_checksum(void *obj, + unsigned long obj_size, + unsigned int key, + unsigned int checksum); + +/* assertion at compile time */ +#ifdef __linux__ +#define stringification(s) _stringification(s) +#define _stringification(s) #s + +_Static_assert( + sizeof(struct amd_sriov_msg_vf2pf_info) == AMD_SRIOV_MSG_SIZE_KB << 10, + "amd_sriov_msg_vf2pf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB) " KB"); + +_Static_assert( + sizeof(struct amd_sriov_msg_pf2vf_info) == AMD_SRIOV_MSG_SIZE_KB << 10, + "amd_sriov_msg_pf2vf_info must be " stringification(AMD_SRIOV_MSG_SIZE_KB) " KB"); + +_Static_assert( + AMD_SRIOV_MSG_RESERVE_UCODE % 4 == 0, + "AMD_SRIOV_MSG_RESERVE_UCODE must be multiple of 4"); + +_Static_assert( + AMD_SRIOV_MSG_RESERVE_UCODE > AMD_SRIOV_UCODE_ID__MAX, + "AMD_SRIOV_MSG_RESERVE_UCODE must be bigger than AMD_SRIOV_UCODE_ID__MAX"); + +#undef _stringification +#undef stringification +#endif + +#endif /* AMDGV_SRIOV_MSG__H_ */ -- GitLab From 519b8b76f0b62a0be0d9fcee39819d2461fc3cb0 Mon Sep 17 00:00:00 2001 From: Bokun Zhang <Bokun.Zhang@amd.com> Date: Tue, 28 Jul 2020 15:29:12 -0400 Subject: [PATCH 1420/1494] drm/amdgpu: Implement new guest side VF2PF message transaction (v2) - Refactor the driver code to use amdgpu_virt_read_pf2vf_data and amdgpu_virt_write_vf2pf_data instead of writing all code in one function (which is the old amdgpu_virt_init_data_exchange) - Adding a new transaction method for VF2PF message between host and guest driver. Guest side will periodically update VF2PF message in the framebuffer. In the new header, we include guest ucode information, guest framebuffer usage, and engine usage - Clean up the old macros since they will cause compile error if the new transaction method is used v2: squash in build fix Signed-off-by: Bokun Zhang <Bokun.Zhang@amd.com> Reviewed-by: Monk Liu <monk.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 243 ++++++++++++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 75 +------ 3 files changed, 198 insertions(+), 124 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index de3608902bd8f..da9aa019de720 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3441,8 +3441,10 @@ void amdgpu_device_fini(struct amdgpu_device *adev) /* make sure IB test finished before entering exclusive mode * to avoid preemption on IB test * */ - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev)) { amdgpu_virt_request_full_gpu(adev, false); + amdgpu_virt_fini_data_exchange(adev); + } /* disable all interrupts */ amdgpu_irq_disable_all(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index f76961d172460..d0aea5e395315 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -31,6 +31,12 @@ #include "soc15.h" #include "nv.h" +#define POPULATE_UCODE_INFO(vf2pf_info, ucode, ver) \ + do { \ + vf2pf_info->ucode_info[ucode].id = ucode; \ + vf2pf_info->ucode_info[ucode].version = ver; \ + } while (0) + bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev) { /* By now all MMIO pages except mailbox are blocked */ @@ -239,10 +245,10 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) } -int amdgpu_virt_fw_reserve_get_checksum(void *obj, - unsigned long obj_size, - unsigned int key, - unsigned int chksum) +unsigned int amd_sriov_msg_checksum(void *obj, + unsigned long obj_size, + unsigned int key, + unsigned int checksum) { unsigned int ret = key; unsigned long i = 0; @@ -252,9 +258,9 @@ int amdgpu_virt_fw_reserve_get_checksum(void *obj, /* calculate checksum */ for (i = 0; i < obj_size; ++i) ret += *(pos + i); - /* minus the chksum itself */ - pos = (char *)&chksum; - for (i = 0; i < sizeof(chksum); ++i) + /* minus the checksum itself */ + pos = (char *)&checksum; + for (i = 0; i < sizeof(checksum); ++i) ret -= *(pos + i); return ret; } @@ -415,33 +421,188 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev, } } -void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) +static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) { - uint32_t pf2vf_size = 0; - uint32_t checksum = 0; + struct amd_sriov_msg_pf2vf_info_header *pf2vf_info = adev->virt.fw_reserve.p_pf2vf; + uint32_t checksum; uint32_t checkval; - char *str; + + if (adev->virt.fw_reserve.p_pf2vf == NULL) + return -EINVAL; + + if (pf2vf_info->size > 1024) { + DRM_ERROR("invalid pf2vf message size\n"); + return -EINVAL; + } + + switch (pf2vf_info->version) { + case 1: + checksum = ((struct amdgim_pf2vf_info_v1 *)pf2vf_info)->checksum; + checkval = amd_sriov_msg_checksum( + adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, + adev->virt.fw_reserve.checksum_key, checksum); + if (checksum != checkval) { + DRM_ERROR("invalid pf2vf message\n"); + return -EINVAL; + } + + adev->virt.gim_feature = + ((struct amdgim_pf2vf_info_v1 *)pf2vf_info)->feature_flags; + break; + case 2: + /* TODO: missing key, need to add it later */ + checksum = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->checksum; + checkval = amd_sriov_msg_checksum( + adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, + 0, checksum); + if (checksum != checkval) { + DRM_ERROR("invalid pf2vf message\n"); + return -EINVAL; + } + + adev->virt.vf2pf_update_interval_ms = + ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->vf2pf_update_interval_ms; + adev->virt.gim_feature = + ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->feature_flags.all; + + break; + default: + DRM_ERROR("invalid pf2vf version\n"); + return -EINVAL; + } + + /* correct too large or too little interval value */ + if (adev->virt.vf2pf_update_interval_ms < 200 || adev->virt.vf2pf_update_interval_ms > 10000) + adev->virt.vf2pf_update_interval_ms = 2000; + + return 0; +} + +static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) +{ + struct amd_sriov_msg_vf2pf_info *vf2pf_info; + vf2pf_info = (struct amd_sriov_msg_vf2pf_info *) adev->virt.fw_reserve.p_vf2pf; + + if (adev->virt.fw_reserve.p_vf2pf == NULL) + return; + + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_VCE, adev->vce.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_UVD, adev->uvd.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MC, adev->gmc.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ME, adev->gfx.me_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_PFP, adev->gfx.pfp_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_CE, adev->gfx.ce_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC, adev->gfx.rlc_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLC, adev->gfx.rlc_srlc_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLG, adev->gfx.rlc_srlg_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_RLC_SRLS, adev->gfx.rlc_srls_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd_fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ta_ras_ucode_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.ta_xgmi_ucode_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_VCN, adev->vcn.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_DMCU, adev->dm.dmcu_fw_version); +} + +static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev) +{ + struct amd_sriov_msg_vf2pf_info *vf2pf_info; + struct ttm_resource_manager *vram_man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + + vf2pf_info = (struct amd_sriov_msg_vf2pf_info *) adev->virt.fw_reserve.p_vf2pf; + + if (adev->virt.fw_reserve.p_vf2pf == NULL) + return -EINVAL; + + memset(vf2pf_info, 0, sizeof(struct amd_sriov_msg_vf2pf_info)); + + vf2pf_info->header.size = sizeof(struct amd_sriov_msg_vf2pf_info); + vf2pf_info->header.version = AMD_SRIOV_MSG_FW_VRAM_VF2PF_VER; + +#ifdef MODULE + if (THIS_MODULE->version != NULL) + strcpy(vf2pf_info->driver_version, THIS_MODULE->version); + else +#endif + strcpy(vf2pf_info->driver_version, "N/A"); + + vf2pf_info->pf2vf_version_required = 0; // no requirement, guest understands all + vf2pf_info->driver_cert = 0; + vf2pf_info->os_info.all = 0; + + vf2pf_info->fb_usage = amdgpu_vram_mgr_usage(vram_man) >> 20; + vf2pf_info->fb_vis_usage = amdgpu_vram_mgr_vis_usage(vram_man) >> 20; + vf2pf_info->fb_size = adev->gmc.real_vram_size >> 20; + vf2pf_info->fb_vis_size = adev->gmc.visible_vram_size >> 20; + + amdgpu_virt_populate_vf2pf_ucode_info(adev); + + /* TODO: read dynamic info */ + vf2pf_info->gfx_usage = 0; + vf2pf_info->compute_usage = 0; + vf2pf_info->encode_usage = 0; + vf2pf_info->decode_usage = 0; + + vf2pf_info->checksum = + amd_sriov_msg_checksum( + vf2pf_info, vf2pf_info->header.size, 0, 0); + + return 0; +} + +void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work) +{ + struct amdgpu_device *adev = container_of(work, struct amdgpu_device, virt.vf2pf_work.work); + + amdgpu_virt_read_pf2vf_data(adev); + amdgpu_virt_write_vf2pf_data(adev); + + schedule_delayed_work(&(adev->virt.vf2pf_work), adev->virt.vf2pf_update_interval_ms); +} + +void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev) +{ + if (adev->virt.vf2pf_update_interval_ms != 0) { + DRM_INFO("clean up the vf2pf work item\n"); + flush_delayed_work(&adev->virt.vf2pf_work); + cancel_delayed_work_sync(&adev->virt.vf2pf_work); + } +} + +void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) +{ uint64_t bp_block_offset = 0; uint32_t bp_block_size = 0; - struct amdgim_pf2vf_info_v2 *pf2vf_v2 = NULL; + struct amd_sriov_msg_pf2vf_info *pf2vf_v2 = NULL; adev->virt.fw_reserve.p_pf2vf = NULL; adev->virt.fw_reserve.p_vf2pf = NULL; + adev->virt.vf2pf_update_interval_ms = 0; if (adev->mman.fw_vram_usage_va != NULL) { + adev->virt.vf2pf_update_interval_ms = 2000; + adev->virt.fw_reserve.p_pf2vf = - (struct amd_sriov_msg_pf2vf_info_header *)( - adev->mman.fw_vram_usage_va + AMDGIM_DATAEXCHANGE_OFFSET); - AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); - AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); - AMDGPU_FW_VRAM_PF2VF_READ(adev, feature_flags, &adev->virt.gim_feature); - - /* pf2vf message must be in 4K */ - if (pf2vf_size > 0 && pf2vf_size < 4096) { - if (adev->virt.fw_reserve.p_pf2vf->version == 2) { - pf2vf_v2 = (struct amdgim_pf2vf_info_v2 *)adev->virt.fw_reserve.p_pf2vf; - bp_block_offset = ((uint64_t)pf2vf_v2->bp_block_offset_L & 0xFFFFFFFF) | - ((((uint64_t)pf2vf_v2->bp_block_offset_H) << 32) & 0xFFFFFFFF00000000); + (struct amd_sriov_msg_pf2vf_info_header *) + (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); + adev->virt.fw_reserve.p_vf2pf = + (struct amd_sriov_msg_vf2pf_info_header *) + (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10)); + + amdgpu_virt_read_pf2vf_data(adev); + amdgpu_virt_write_vf2pf_data(adev); + + /* bad page handling for version 2 */ + if (adev->virt.fw_reserve.p_pf2vf->version == 2) { + pf2vf_v2 = (struct amd_sriov_msg_pf2vf_info *)adev->virt.fw_reserve.p_pf2vf; + + bp_block_offset = ((uint64_t)pf2vf_v2->bp_block_offset_low & 0xFFFFFFFF) | + ((((uint64_t)pf2vf_v2->bp_block_offset_high) << 32) & 0xFFFFFFFF00000000); bp_block_size = pf2vf_v2->bp_block_size; if (bp_block_size && !adev->virt.ras_init_done) @@ -450,37 +611,11 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) if (adev->virt.ras_init_done) amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size); } + } - checkval = amdgpu_virt_fw_reserve_get_checksum( - adev->virt.fw_reserve.p_pf2vf, pf2vf_size, - adev->virt.fw_reserve.checksum_key, checksum); - if (checkval == checksum) { - adev->virt.fw_reserve.p_vf2pf = - ((void *)adev->virt.fw_reserve.p_pf2vf + - pf2vf_size); - memset((void *)adev->virt.fw_reserve.p_vf2pf, 0, - sizeof(amdgim_vf2pf_info)); - AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.version, - AMDGPU_FW_VRAM_VF2PF_VER); - AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.size, - sizeof(amdgim_vf2pf_info)); - AMDGPU_FW_VRAM_VF2PF_READ(adev, driver_version, - &str); -#ifdef MODULE - if (THIS_MODULE->version != NULL) - strcpy(str, THIS_MODULE->version); - else -#endif - strcpy(str, "N/A"); - AMDGPU_FW_VRAM_VF2PF_WRITE(adev, driver_cert, - 0); - AMDGPU_FW_VRAM_VF2PF_WRITE(adev, checksum, - amdgpu_virt_fw_reserve_get_checksum( - adev->virt.fw_reserve.p_vf2pf, - pf2vf_size, - adev->virt.fw_reserve.checksum_key, 0)); - } - } + if (adev->virt.vf2pf_update_interval_ms != 0) { + INIT_DELAYED_WORK(&adev->virt.vf2pf_work, amdgpu_virt_update_vf2pf_work_item); + schedule_delayed_work(&(adev->virt.vf2pf_work), adev->virt.vf2pf_update_interval_ms); } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 082fb0736645c..8dd624c20f895 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -125,45 +125,6 @@ struct amdgim_pf2vf_info_v1 { unsigned int checksum; } __aligned(4); -/* TODO: below struct is duplicated to amd_sriov_msg_pf2vf_info */ -struct amdgim_pf2vf_info_v2 { - /* header contains size and version */ - struct amd_sriov_msg_pf2vf_info_header header; - /* use private key from mailbox 2 to create chueksum */ - uint32_t checksum; - /* The features flags of the GIM driver supports. */ - uint32_t feature_flags; - /* max_width * max_height */ - uint32_t uvd_enc_max_pixels_count; - /* 16x16 pixels/sec, codec independent */ - uint32_t uvd_enc_max_bandwidth; - /* max_width * max_height */ - uint32_t vce_enc_max_pixels_count; - /* 16x16 pixels/sec, codec independent */ - uint32_t vce_enc_max_bandwidth; - /* Bad pages block position in BYTE */ - uint32_t bp_block_offset_L; - uint32_t bp_block_offset_H; - /* Bad pages block size in BYTE */ - uint32_t bp_block_size; - /* MEC FW position in kb from the start of VF visible frame buffer */ - uint32_t mecfw_kboffset_L; - uint32_t mecfw_kboffset_H; - /* MEC FW size in KB */ - uint32_t mecfw_ksize; - /* UVD FW position in kb from the start of VF visible frame buffer */ - uint32_t uvdfw_kboffset_L; - uint32_t uvdfw_kboffset_H; - /* UVD FW size in KB */ - uint32_t uvdfw_ksize; - /* VCE FW position in kb from the start of VF visible frame buffer */ - uint32_t vcefw_kboffset_L; - uint32_t vcefw_kboffset_H; - /* VCE FW size in KB */ - uint32_t vcefw_ksize; - uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (18 + sizeof(struct amd_sriov_msg_pf2vf_info_header)/sizeof(uint32_t)), 0)]; -} __aligned(4); - struct amdgim_vf2pf_info_v1 { /* header contains size and version */ struct amd_sriov_msg_vf2pf_info_header header; @@ -225,32 +186,6 @@ struct amdgim_vf2pf_info_v2 { uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amd_sriov_msg_vf2pf_info_header)/sizeof(uint32_t)), 0)]; } __aligned(4); -/* TODO: below macro and typedef will cause compile error, need to remove */ -#define AMDGPU_FW_VRAM_VF2PF_VER 2 -typedef struct amd_sriov_msg_vf2pf_info amdgim_vf2pf_info; - -#define AMDGPU_FW_VRAM_VF2PF_WRITE(adev, field, val) \ - do { \ - ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field = (val); \ - } while (0) - -#define AMDGPU_FW_VRAM_VF2PF_READ(adev, field, val) \ - do { \ - (*val) = ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field; \ - } while (0) - -#define AMDGPU_FW_VRAM_PF2VF_READ(adev, field, val) \ - do { \ - if (!adev->virt.fw_reserve.p_pf2vf) \ - *(val) = 0; \ - else { \ - if (adev->virt.fw_reserve.p_pf2vf->version == 1) \ - *(val) = ((struct amdgim_pf2vf_info_v1 *)adev->virt.fw_reserve.p_pf2vf)->field; \ - if (adev->virt.fw_reserve.p_pf2vf->version == 2) \ - *(val) = ((struct amdgim_pf2vf_info_v2 *)adev->virt.fw_reserve.p_pf2vf)->field; \ - } \ - } while (0) - struct amdgpu_virt_ras_err_handler_data { /* point to bad page records array */ struct eeprom_table_record *bps; @@ -274,7 +209,7 @@ struct amdgpu_virt { struct work_struct flr_work; struct amdgpu_mm_table mm_table; const struct amdgpu_virt_ops *ops; - struct amdgpu_vf_error_buffer vf_errors; + struct amdgpu_vf_error_buffer vf_errors; struct amdgpu_virt_fw_reserve fw_reserve; uint32_t gim_feature; uint32_t reg_access_mode; @@ -282,6 +217,10 @@ struct amdgpu_virt { bool tdr_debug; struct amdgpu_virt_ras_err_handler_data *virt_eh_data; bool ras_init_done; + + /* vf2pf message */ + struct delayed_work vf2pf_work; + uint32_t vf2pf_update_interval_ms; }; #define amdgpu_sriov_enabled(adev) \ @@ -330,11 +269,9 @@ void amdgpu_virt_request_init_data(struct amdgpu_device *adev); int amdgpu_virt_wait_reset(struct amdgpu_device *adev); int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); -int amdgpu_virt_fw_reserve_get_checksum(void *obj, unsigned long obj_size, - unsigned int key, - unsigned int chksum); void amdgpu_virt_release_ras_err_handler_data(struct amdgpu_device *adev); void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev); +void amdgpu_virt_fini_data_exchange(struct amdgpu_device *adev); void amdgpu_detect_virtualization(struct amdgpu_device *adev); bool amdgpu_virt_can_access_debugfs(struct amdgpu_device *adev); -- GitLab From b602ca5f31fe69588aae9ee13fd50a49ef0a57dd Mon Sep 17 00:00:00 2001 From: Tiecheng Zhou <Tiecheng.Zhou@amd.com> Date: Wed, 19 Aug 2020 10:27:09 +0800 Subject: [PATCH 1421/1494] drm/amdgpu: stop data_exchange work thread before reset In FLR routine, init_data_exchange is called at reset_sriov while fini_data_exchange is not. This will duplicating work thread. So call fini_data_exchange before reset for SRIOV Signed-off-by: Tiecheng Zhou <Tiecheng.Zhou@amd.com> Signed-off-by: Bokun Zhang <Bokun.Zhang@amd.com> Reviewed-by: Monk Liu <monk.liu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index da9aa019de720..76581c59f196c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4078,6 +4078,11 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, amdgpu_debugfs_wait_dump(adev); + if (amdgpu_sriov_vf(adev)) { + /* stop the data exchange thread */ + amdgpu_virt_fini_data_exchange(adev); + } + /* block all schedulers and reset given job's ring */ for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i]; -- GitLab From c3d4d45db2fa05462629dbb0857146f5bedfc558 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Thu, 24 Sep 2020 18:09:44 +0800 Subject: [PATCH 1422/1494] drm/amdgpu: clean up ras sysfs creation (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge ras sysfs creation together by calling sysfs_create_group once, as sysfs_update_group may not work properly as expected. v2: improve commit message Signed-off-by: Guchun Chen <guchun.chen@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Reviewed-by: Dennis Li <Dennis.Li@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 87 +++++++++---------------- 1 file changed, 31 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 7f79d25fbccc2..49d10330bf645 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1027,58 +1027,6 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev, return scnprintf(buf, PAGE_SIZE, "feature mask: 0x%x\n", con->features); } -static void amdgpu_ras_sysfs_add_bad_page_node(struct amdgpu_device *adev) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct attribute_group group; - struct bin_attribute *bin_attrs[] = { - &con->badpages_attr, - NULL, - }; - - con->badpages_attr = (struct bin_attribute) { - .attr = { - .name = "gpu_vram_bad_pages", - .mode = S_IRUGO, - }, - .size = 0, - .private = NULL, - .read = amdgpu_ras_sysfs_badpages_read, - }; - - group.name = RAS_FS_NAME; - group.bin_attrs = bin_attrs; - - sysfs_bin_attr_init(bin_attrs[0]); - - sysfs_update_group(&adev->dev->kobj, &group); -} - -static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct attribute *attrs[] = { - &con->features_attr.attr, - NULL - }; - struct attribute_group group = { - .name = RAS_FS_NAME, - .attrs = attrs, - }; - - con->features_attr = (struct device_attribute) { - .attr = { - .name = "features", - .mode = S_IRUGO, - }, - .show = amdgpu_ras_sysfs_features_read, - }; - - sysfs_attr_init(attrs[0]); - - return sysfs_create_group(&adev->dev->kobj, &group); -} - static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -1300,13 +1248,40 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) /* debugfs end */ /* ras fs */ - +static BIN_ATTR(gpu_vram_bad_pages, S_IRUGO, + amdgpu_ras_sysfs_badpages_read, NULL, 0); +static DEVICE_ATTR(features, S_IRUGO, + amdgpu_ras_sysfs_features_read, NULL); static int amdgpu_ras_fs_init(struct amdgpu_device *adev) { - amdgpu_ras_sysfs_create_feature_node(adev); + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct attribute_group group = { + .name = RAS_FS_NAME, + }; + struct attribute *attrs[] = { + &con->features_attr.attr, + NULL + }; + struct bin_attribute *bin_attrs[] = { + NULL, + NULL, + }; - if (amdgpu_bad_page_threshold != 0) - amdgpu_ras_sysfs_add_bad_page_node(adev); + /* add features entry */ + con->features_attr = dev_attr_features; + group.attrs = attrs; + sysfs_attr_init(attrs[0]); + + if (amdgpu_bad_page_threshold != 0) { + /* add bad_page_features entry */ + bin_attr_gpu_vram_bad_pages.private = NULL; + con->badpages_attr = bin_attr_gpu_vram_bad_pages; + bin_attrs[0] = &con->badpages_attr; + group.bin_attrs = bin_attrs; + sysfs_bin_attr_init(bin_attrs[0]); + } + + sysfs_create_group(&adev->dev->kobj, &group); return 0; } -- GitLab From a069a9eb73f896b84d8cfda2f2d436c1844c4e92 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Fri, 25 Sep 2020 10:29:01 -0400 Subject: [PATCH 1423/1494] drm/amdgpu: fix a warning in amdgpu_ras.c (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c: In function ‘amdgpu_ras_fs_init’: drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1284:2: warning: ignoring return value of ‘sysfs_create_group’, declared with attribute warn_unused_result [-Wunused-result] 1284 | sysfs_create_group(&adev->dev->kobj, &group); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ v2: just print an error for sysfs group creation failure Acked-by: Nirmoy Das <nirmoy.das@amd.com> Reviewed-by: Luben Tuikov <luben.tuikov@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 49d10330bf645..8bf6a7c056bc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1266,6 +1266,7 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev) NULL, NULL, }; + int r; /* add features entry */ con->features_attr = dev_attr_features; @@ -1281,7 +1282,9 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev) sysfs_bin_attr_init(bin_attrs[0]); } - sysfs_create_group(&adev->dev->kobj, &group); + r = sysfs_create_group(&adev->dev->kobj, &group); + if (r) + dev_err(adev->dev, "Failed to create RAS sysfs group!"); return 0; } -- GitLab From c220ba6f6237ed3d83d547607f42073398571433 Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Thu, 24 Sep 2020 12:08:04 +0800 Subject: [PATCH 1424/1494] drm/amd/pm: fix screen flicker seen on Navi14 with 2*4K monitors Revert the guilty change introduced by the commit below: drm/amd/pm: postpone SOCCLK/UCLK enablement after DAL initialization(V2) Signed-off-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 43 ++++++------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 1695b36dc23c9..be44cb941e732 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -316,6 +316,18 @@ navi10_get_allowed_feature_mask(struct smu_context *smu, if (smu->dc_controlled_by_gpio) *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT); + if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + /* DPM UCLK enablement should be skipped for navi10 A0 secure board */ + if (!(is_asic_secure(smu) && + (adev->asic_type == CHIP_NAVI10) && + (adev->rev_id == 0)) && + (adev->pm.pp_feature & PP_MCLK_DPM_MASK)) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) + | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) + | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); + /* DS SOCCLK enablement should be skipped for navi10 A0 secure board */ if (is_asic_secure(smu) && (adev->asic_type == CHIP_NAVI10) && @@ -2629,43 +2641,12 @@ static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) static int navi10_post_smu_init(struct smu_context *smu) { - struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; - uint64_t feature_mask = 0; int ret = 0; if (amdgpu_sriov_vf(adev)) return 0; - /* For Naiv1x, enable these features only after DAL initialization */ - if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) - feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); - - /* DPM UCLK enablement should be skipped for navi10 A0 secure board */ - if (!(is_asic_secure(smu) && - (adev->asic_type == CHIP_NAVI10) && - (adev->rev_id == 0)) && - (adev->pm.pp_feature & PP_MCLK_DPM_MASK)) - feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); - - if (!feature_mask) - return 0; - - bitmap_or(feature->allowed, - feature->allowed, - (unsigned long *)(&feature_mask), - SMU_FEATURE_MAX); - - ret = smu_cmn_feature_update_enable_state(smu, - feature_mask, - true); - if (ret) { - dev_err(adev->dev, "Failed to post uclk/socclk dpm enablement!\n"); - return ret; - } - ret = navi10_run_umc_cdr_workaround(smu); if (ret) { dev_err(adev->dev, "Failed to apply umc cdr workaround!\n"); -- GitLab From d1ea914925856d397b0b3241428f20b945e31434 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar <abhinavk@codeaurora.org> Date: Fri, 25 Sep 2020 19:55:12 -0700 Subject: [PATCH 1425/1494] drm/msm/dp: fix incorrect function prototype of dp_debug_get() Fix the incorrect function prototype for dp_debug_get() in the dp_debug module to address compilation warning. Also add prototype for msm_dp_debugfs_init() for fixing compilation issue with other defconfigs. changes in v2: - add prototype for msm_dp_debugfs_init() Fixes: f913454aae8e ("drm/msm/dp: move debugfs node to /sys/kernel/debug/dri/*/") Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org> Signed-off-by: Rob Clark <robdclark@chromium.org> --- drivers/gpu/drm/msm/dp/dp_debug.h | 2 +- drivers/gpu/drm/msm/msm_drv.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h index 377e166fd0ead..7eaedfbb149c4 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.h +++ b/drivers/gpu/drm/msm/dp/dp_debug.h @@ -60,7 +60,7 @@ void dp_debug_put(struct dp_debug *dp_debug); static inline struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel, struct dp_usbpd *usbpd, struct dp_link *link, - struct drm_connector **connector) + struct drm_connector **connector, struct drm_minor *minor) { return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 28e3c8d628cb1..b9dd8f8f48872 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -434,6 +434,11 @@ static inline void msm_dp_irq_postinstall(struct msm_dp *dp_display) { } +static inline void msm_dp_debugfs_init(struct msm_dp *dp_display, + struct drm_minor *minor) +{ +} + #endif void __init msm_mdp_register(void); -- GitLab From 32e4d9df60f71d641fbe628a9afbe2f44d7e9a37 Mon Sep 17 00:00:00 2001 From: Julia Lawall <Julia.Lawall@inria.fr> Date: Sun, 27 Sep 2020 21:12:18 +0200 Subject: [PATCH 1426/1494] agp: use semicolons rather than commas to separate statements Replace commas with semicolons. What is done is essentially described by the following Coccinelle semantic patch (http://coccinelle.lip6.fr/): // <smpl> @@ expression e1,e2; @@ e1 -, +; e2 ... when any // </smpl> Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr> Signed-off-by: Dave Airlie <airlied@redhat.com> --- drivers/char/agp/amd-k7-agp.c | 2 +- drivers/char/agp/nvidia-agp.c | 2 +- drivers/char/agp/sworks-agp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 6914e4f0ce985..2b2095542816b 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -425,7 +425,7 @@ static int agp_amdk7_probe(struct pci_dev *pdev, return -ENOMEM; bridge->driver = &amd_irongate_driver; - bridge->dev_private_data = &amd_irongate_private, + bridge->dev_private_data = &amd_irongate_private; bridge->dev = pdev; bridge->capndx = cap_ptr; diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 623205bcd04ab..f78e756157db3 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -382,7 +382,7 @@ static int agp_nvidia_probe(struct pci_dev *pdev, return -ENOMEM; bridge->driver = &nvidia_driver; - bridge->dev_private_data = &nvidia_private, + bridge->dev_private_data = &nvidia_private; bridge->dev = pdev; bridge->capndx = cap_ptr; diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 7729414100ffa..f875970bda653 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -513,7 +513,7 @@ static int agp_serverworks_probe(struct pci_dev *pdev, return -ENOMEM; bridge->driver = &sworks_driver; - bridge->dev_private_data = &serverworks_private, + bridge->dev_private_data = &serverworks_private; bridge->dev = pci_dev_get(pdev); pci_set_drvdata(pdev, bridge); -- GitLab From ef80c1a1d21b2845e3a60dcb936264b123ebf41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> Date: Fri, 25 Sep 2020 16:16:48 +0300 Subject: [PATCH 1427/1494] drm/i915: Fix state checker hw.active/hw.enable readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously intel_dump_pipe_config() used to dump the full crtc state whether or not the crtc was logically enabled or not. As that meant occasionally dumping confusing stale garbage I changed it to check whether the crtc is logically enabled or not. However I did not realize that the state checker readout code does not populate crtc_state.hw.{active,enabled}. Hence the state checker dump would only give us a full dump of the sw state but not the hw state. Fix that by populating those bits of the hw state as well. Reviewed-by: Uma Shankar <uma.shankar@intel.com> Fixes: 10d75f5428fd ("drm/i915: Fix plane state dumps") Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200925131656.10022-2-ville.syrjala@linux.intel.com (cherry picked from commit 504c7bd85c6f9b14b6c7f03cb5885c0818e805ad) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/display/intel_display.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5a9d933e425a4..d64e46acfbbde 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14304,7 +14304,6 @@ verify_crtc_state(struct intel_crtc *crtc, struct intel_encoder *encoder; struct intel_crtc_state *pipe_config = old_crtc_state; struct drm_atomic_state *state = old_crtc_state->uapi.state; - bool active; __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi); intel_crtc_free_hw_state(old_crtc_state); @@ -14314,16 +14313,19 @@ verify_crtc_state(struct intel_crtc *crtc, drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s]\n", crtc->base.base.id, crtc->base.name); - active = dev_priv->display.get_pipe_config(crtc, pipe_config); + pipe_config->hw.enable = new_crtc_state->hw.enable; + + pipe_config->hw.active = + dev_priv->display.get_pipe_config(crtc, pipe_config); /* we keep both pipes enabled on 830 */ - if (IS_I830(dev_priv)) - active = new_crtc_state->hw.active; + if (IS_I830(dev_priv) && pipe_config->hw.active) + pipe_config->hw.active = new_crtc_state->hw.active; - I915_STATE_WARN(new_crtc_state->hw.active != active, + I915_STATE_WARN(new_crtc_state->hw.active != pipe_config->hw.active, "crtc active state doesn't match with hw state " "(expected %i, found %i)\n", - new_crtc_state->hw.active, active); + new_crtc_state->hw.active, pipe_config->hw.active); I915_STATE_WARN(crtc->active != new_crtc_state->hw.active, "transitional active state does not match atomic hw state " @@ -14332,6 +14334,7 @@ verify_crtc_state(struct intel_crtc *crtc, for_each_encoder_on_crtc(dev, &crtc->base, encoder) { enum pipe pipe; + bool active; active = encoder->get_hw_state(encoder, &pipe); I915_STATE_WARN(active != new_crtc_state->hw.active, -- GitLab From 200a2186b62714c099693dcb6444af373eaabf62 Mon Sep 17 00:00:00 2001 From: Rob Clark <robdclark@chromium.org> Date: Mon, 28 Sep 2020 17:19:12 -0700 Subject: [PATCH 1428/1494] drm/msm: fix 32b build warns Neither of these code-paths apply to older 32b devices, but it is rude to introduce warnings. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200929001925.2916984-1-robdclark@gmail.com --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index fd8f491f2e48e..458b5b26d3c26 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -209,7 +209,7 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu, size = iommu->geometry.aperture_end - start + 1; aspace = msm_gem_address_space_create(mmu, "gpu", - start & GENMASK(48, 0), size); + start & GENMASK_ULL(48, 0), size); if (IS_ERR(aspace) && !IS_ERR(mmu)) mmu->funcs->destroy(mmu); diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c index 029cc8bf5a046..de0dfb8151258 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_7nm.c @@ -879,7 +879,7 @@ struct msm_dsi_pll *msm_dsi_pll_7nm_init(struct platform_device *pdev, int id) pll->max_rate = 3500000000UL; if (pll->type == MSM_DSI_PHY_7NM_V4_1) { pll->min_rate = 600000000UL; - pll->max_rate = 5000000000UL; + pll->max_rate = (unsigned long)5000000000ULL; /* workaround for max rate overflowing on 32-bit builds: */ pll->max_rate = max(pll->max_rate, 0xffffffffUL); } -- GitLab From 4a3dea8932d3b1199680d2056dd91d31d94d70b7 Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Fri, 25 Sep 2020 10:54:47 -0400 Subject: [PATCH 1429/1494] drm/amd/display: Update NV1x SR latency values [Why] HW team measurement requires updating values [How] Update bounding box values Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 18b9465057fff..bf37a229a3424 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -298,8 +298,8 @@ static struct _vcs_dpi_soc_bounding_box_st dcn2_0_soc = { }, }, .num_states = 5, - .sr_exit_time_us = 8.6, - .sr_enter_plus_exit_time_us = 10.9, + .sr_exit_time_us = 11.6, + .sr_enter_plus_exit_time_us = 13.9, .urgent_latency_us = 4.0, .urgent_latency_pixel_data_only_us = 4.0, .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, -- GitLab From 4ab1edbc9da1509d8a2d775cf5aa295705d131d1 Mon Sep 17 00:00:00 2001 From: Eric Bernstein <eric.bernstein@amd.com> Date: Fri, 25 Sep 2020 10:54:48 -0400 Subject: [PATCH 1430/1494] drm/amd/display: Add dp_set_dsc_pps_info_packet to virtual stream encoder Signed-off-by: Eric Bernstein <eric.bernstein@amd.com> Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/core/dc_link_hwss.c | 21 ++++++++++--------- .../dc/virtual/virtual_stream_encoder.c | 7 +++++++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index dba338c882561..11a619befb425 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -493,13 +493,15 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) OPTC_DSC_DISABLED, 0, 0); /* disable DSC in stream encoder */ - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( - pipe_ctx->stream_res.stream_enc, - OPTC_DSC_DISABLED, 0, 0); - - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL); + if (dc_is_dp_signal(stream->signal)) { + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( + pipe_ctx->stream_res.stream_enc, + OPTC_DSC_DISABLED, 0, 0); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL); + } } /* disable DSC block */ @@ -536,7 +538,6 @@ bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) { struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; if (!pipe_ctx->stream->timing.flags.DSC || !dsc) @@ -559,7 +560,7 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) DC_LOG_DSC(" "); dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + if (dc_is_dp_signal(stream->signal)) { DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc, @@ -568,7 +569,7 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) } } else { /* disable DSC PPS in stream encoder */ - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + if (dc_is_dp_signal(stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc, false, NULL); } diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index f0a0d419e555c..1053b165c1391 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -99,6 +99,12 @@ static void virtual_setup_stereo_sync( bool enable) {} +static void virtual_stream_encoder_set_dsc_pps_info_packet( + struct stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps) +{} + static const struct stream_encoder_funcs virtual_str_enc_funcs = { .dp_set_odm_combine = virtual_enc_dp_set_odm_combine, @@ -128,6 +134,7 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { .hdmi_reset_stream_attribute = virtual_stream_encoder_reset_hdmi_stream_attribute, .dig_connect_to_otg = virtual_dig_connect_to_otg, .setup_stereo_sync = virtual_setup_stereo_sync, + .dp_set_dsc_pps_info_packet = virtual_stream_encoder_set_dsc_pps_info_packet, }; bool virtual_stream_encoder_construct( -- GitLab From 89b151ade71495ebe2e48923812571e8e6a92918 Mon Sep 17 00:00:00 2001 From: Wyatt Wood <wyatt.wood@amd.com> Date: Fri, 25 Sep 2020 10:54:49 -0400 Subject: [PATCH 1431/1494] drm/amd/display: Ensure all debug bits are passed to fw [Why] Some debug bits are not being copied from driver to fw. [How] Copy debug bits properly. Signed-off-by: Wyatt Wood <wyatt.wood@amd.com> Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index bf24f1029547b..67af67ef28659 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -256,10 +256,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->smu_optimizations_en = psr_context->allow_smu_optimizations; copy_settings_data->frame_delay = psr_context->frame_delay; copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; + copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; + copy_settings_data->debug.u32All = 0; copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR ? true : false; - copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; - copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; + copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); -- GitLab From ba578afd5a4f6139ffe564f07575875ca51a0f4f Mon Sep 17 00:00:00 2001 From: Chiawen Huang <chiawen.huang@amd.com> Date: Fri, 25 Sep 2020 10:54:50 -0400 Subject: [PATCH 1432/1494] drm/amd/display: disable stream if pixel clock changed with link active [Why] Vbios uses preferred timing to turn on edp but OS could use other timing. If change pixel clock when link active, there is unexpected garbage on monitor. [How] Once pixel clock changed, the driver needs to disable stream. Signed-off-by: Chiawen Huang <chiawen.huang@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 62 ++++++++++++++++++- .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7e74ddc1c708c..9fabe264cdea0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -842,6 +842,61 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context) dc_release_state(current_ctx); } +static void disable_vbios_mode_if_required( + struct dc *dc, + struct dc_state *context) +{ + unsigned int i; + + /* check if timing_changed, disable stream*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct dc_stream_state *stream = NULL; + struct dc_link *link = NULL; + struct pipe_ctx *pipe = NULL; + + pipe = &context->res_ctx.pipe_ctx[i]; + stream = pipe->stream; + if (stream == NULL) + continue; + + if (stream->link->local_sink && + stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { + link = stream->link; + break; + } + + if (link != NULL) { + unsigned int enc_inst, tg_inst = 0; + unsigned int pix_clk_100hz; + + enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); + if (enc_inst != ENGINE_ID_UNKNOWN) { + for (i = 0; i < dc->res_pool->stream_enc_count; i++) { + if (dc->res_pool->stream_enc[i]->id == enc_inst) { + tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg( + dc->res_pool->stream_enc[i]); + break; + } + } + + dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz( + dc->res_pool->dp_clock_source, + tg_inst, &pix_clk_100hz); + + if (link->link_status.link_active) { + uint32_t requested_pix_clk_100hz = + pipe->stream_res.pix_clk_params.requested_pix_clk_100hz; + + if (pix_clk_100hz != requested_pix_clk_100hz) { + core_link_disable_stream(pipe); + pipe->stream->dpms_off = false; + } + } + } + } + } +} + static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) { int i; @@ -1278,13 +1333,14 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; - if (!dcb->funcs->is_accelerated_mode(dcb)) + if (!dcb->funcs->is_accelerated_mode(dcb)) { + disable_vbios_mode_if_required(dc, context); dc->hwss.enable_accelerated_mode(dc, context); + } - for (i = 0; i < context->stream_count; i++) { + for (i = 0; i < context->stream_count; i++) if (context->streams[i]->apply_seamless_boot_optimization) dc->optimize_seamless_boot_streams++; - } if (context->stream_count > dc->optimize_seamless_boot_streams || context->stream_count == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 27a1262a20f60..c73768ed250e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1654,7 +1654,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) // enable fastboot if backend is enabled on eDP if (edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc)) { /* Set optimization flag on eDP stream*/ - if (edp_stream) { + if (edp_stream && edp_link->link_status.link_active) { edp_stream->apply_edp_fast_boot_optimization = true; can_apply_edp_fast_boot = true; } -- GitLab From 8e02c26a58f37cb35e730e01eae14f943fba4cf4 Mon Sep 17 00:00:00 2001 From: Joshua Aberback <joshua.aberback@amd.com> Date: Fri, 25 Sep 2020 10:54:51 -0400 Subject: [PATCH 1433/1494] drm/amd/display: Calc DLG from dummy p-state if full p-state unsupported [Why] Currently, when full p-state changes are not supported, DLG parameters are calculated for no p-state support at all. However, we are required to always support dummy p-state changes, so we should instead calculate DLG based on dummy p-state latency when full p-state is unsupported. This behaviour already exists for DCN2. [How] - move DLG calculation inside WM calculation - if p-state unsupported, do not recalculate for set A, instead copy from set C, and perform DLG calculation with dummy p-state latency Signed-off-by: Joshua Aberback <joshua.aberback@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 114 ++++++++++++------ .../drm/amd/display/dc/dcn30/dcn30_resource.h | 5 + .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- 3 files changed, 80 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index dde87baf1370b..7f3354b3512db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2127,7 +2127,7 @@ static bool dcn30_internal_validate_bw( return out; } -static void dcn30_calculate_wm( +void dcn30_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, @@ -2135,6 +2135,8 @@ static void dcn30_calculate_wm( { int i, pipe_idx; double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + bool pstate_en = context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] != + dm_dram_clock_change_unsupported; if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk) dcfclk = context->bw_ctx.dml.soc.min_dcfclk; @@ -2168,30 +2170,12 @@ static void dcn30_calculate_wm( pipes[0].clks_cfg.voltage = vlevel; pipes[0].clks_cfg.dcfclk_mhz = dcfclk; - /* Set C: - * DCFCLK: Min Required - * FCLK(proportional to UCLK): 1GHz or Max - * pstate latency overriden to 5us - */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - /* Set D: * DCFCLK: Min Required * FCLK(proportional to UCLK): 1GHz or Max * sr_enter_exit = 4, sr_exit = 2us */ + /* if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) { context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us; context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us; @@ -2205,29 +2189,72 @@ static void dcn30_calculate_wm( context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + */ - /* Set A: + /* Set C: * DCFCLK: Min Required * FCLK(proportional to UCLK): 1GHz or Max - * - * Set A calculated last so that following calculations are based on Set A + * pstate latency overridden to 5us */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us; + if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { + unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed; + unsigned int min_dram_speed_mts_margin = 160; + + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us; + + if (context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_unsupported) + min_dram_speed_mts = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz * 16; + + for (i = 3; i > 0; i--) { + if ((min_dram_speed_mts + min_dram_speed_mts_margin > dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts) && + (min_dram_speed_mts - min_dram_speed_mts_margin < dc->clk_mgr->bw_params->dummy_pstate_table[i].dram_speed_mts)) + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->dummy_pstate_table[i].dummy_pstate_latency_us; + } + + context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us; + context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us; } - context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - context->perf_params.stutter_period_us = - context->bw_ctx.dml.vba.StutterPeriod; + context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + if (!pstate_en) { + /* The only difference between A and C is p-state latency, if p-state is not supported we want to + * calculate DLG based on dummy p-state latency, and max out the set A p-state watermark + */ + context->bw_ctx.bw.dcn.watermarks.a = context->bw_ctx.bw.dcn.watermarks.c; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = 0x13FFFF; + } else { + /* Set A: + * DCFCLK: Min Required + * FCLK(proportional to UCLK): 1GHz or Max + * + * Set A calculated last so that following calculations are based on Set A + */ + if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid) { + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; + context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us; + context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us; + } + context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + } + + context->perf_params.stutter_period_us = context->bw_ctx.dml.vba.StutterPeriod; + + /* Make set D = set A until set D is enabled */ + context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a; for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) @@ -2247,6 +2274,13 @@ static void dcn30_calculate_wm( pipe_idx++; } + + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + + if (!pstate_en) + /* Restore full p-state latency */ + context->bw_ctx.dml.soc.dram_clock_change_latency_us = + dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us; } bool dcn30_validate_bandwidth(struct dc *dc, @@ -2279,8 +2313,7 @@ bool dcn30_validate_bandwidth(struct dc *dc, goto validate_out; } - dcn30_calculate_wm(dc, context, pipes, pipe_cnt, vlevel); - dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); BW_VAL_TRACE_END_WATERMARKS(); @@ -2448,6 +2481,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = { .link_enc_create = dcn30_link_encoder_create, .panel_cntl_create = dcn30_panel_cntl_create, .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, .add_stream_to_ctx = dcn30_add_stream_to_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h index c9d5f94092a04..d163812af8584 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -55,6 +55,11 @@ unsigned int dcn30_calc_max_scaled_time( bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +void dcn30_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); void dcn30_populate_dml_writeback_from_context( struct dc *dc, struct resource_context *res_ctx, display_e2e_pipe_params_st *pipes); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 1daa563c8ff44..6e6bc66e49f0a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -101,7 +101,7 @@ struct resource_funcs { struct dc *dc, struct dc_state *context, bool fast_validate); - void (*calculate_wm)( + void (*calculate_wm_and_dlg)( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, -- GitLab From ec30798a82964cd3f449720bc518ed61c46be425 Mon Sep 17 00:00:00 2001 From: Wesley Chalmers <Wesley.Chalmers@amd.com> Date: Fri, 25 Sep 2020 10:54:52 -0400 Subject: [PATCH 1434/1494] drm/amd/display: Add debug param to force dio disable [WHY] At the moment, some tests are failing because cur_link_settings is invalid. As a workaround, add an option to force dio disable. Signed-off-by: Wesley Chalmers <Wesley.Chalmers@amd.com> Reviewed-by: Martin Leung <Martin.Leung@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9fabe264cdea0..dc90d26e26631 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -735,6 +735,8 @@ static bool dc_construct(struct dc *dc, dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present; #endif + dc->debug.force_ignore_link_settings = init_params->force_ignore_link_settings; + if (dc->res_pool->funcs->update_bw_bounding_box) dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 061ca15660ac6..82fe0ab56e3a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -503,6 +503,7 @@ struct dc_debug_options { bool usbc_combo_phy_reset_wa; bool disable_dsc; bool enable_dram_clock_change_one_display_vactive; + bool force_ignore_link_settings; }; struct dc_debug_data { @@ -660,6 +661,7 @@ struct dc_init_data { #if defined(CONFIG_DRM_AMD_DC_DCN3_0) bool force_smu_not_present; #endif + bool force_ignore_link_settings; }; struct dc_callback_init { -- GitLab From cbd975d0b12fca62408157ecc07379da2da8e0a5 Mon Sep 17 00:00:00 2001 From: Aric Cyr <aric.cyr@amd.com> Date: Fri, 25 Sep 2020 10:54:53 -0400 Subject: [PATCH 1435/1494] drm/amd/display: Revert check for flip pending before locking pipes Signed-off-by: Aric Cyr <aric.cyr@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 +++++++++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 12 ++---------- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index dc90d26e26631..76946a7d47ca3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2384,6 +2384,7 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { + bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2414,8 +2415,14 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && dc->hwss.wait_for_pending_cleared) - dc->hwss.disconnect_pipes(dc, context); + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && + dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ + dc->hwss.interdependent_update_lock(dc, context, true); + mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); + } for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 79fe9571cf5d0..d0f3bf953d027 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2761,7 +2761,7 @@ static struct pipe_ctx *dcn10_find_top_pipe_for_stream( return NULL; } -void dcn10_disconnect_pipes( +bool dcn10_disconnect_pipes( struct dc *dc, struct dc_state *context) { @@ -2772,10 +2772,6 @@ void dcn10_disconnect_pipes( bool mpcc_disconnected = false; struct pipe_ctx *old_pipe; struct pipe_ctx *new_pipe; - - dc->hwss.wait_for_pending_cleared(dc, context); - dc->hwss.interdependent_update_lock(dc, context, true); - DC_LOGGER_INIT(dc->ctx->logger); /* Set pipe update flags and lock pipes */ @@ -2878,11 +2874,7 @@ void dcn10_disconnect_pipes( } } } - - dc->hwss.interdependent_update_lock(dc, context, false); - - if (mpcc_disconnected) - dc->hwss.wait_for_pending_cleared(dc, context); + return mpcc_disconnected; } void dcn10_wait_for_pending_cleared(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 9a0f7a8a85cd2..e5691e4990231 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -194,7 +194,7 @@ void dcn10_get_surface_visual_confirm_color( void dcn10_get_hdr_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); -void dcn10_disconnect_pipes( +bool dcn10_disconnect_pipes( struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index f48ee24d42f92..64c1be818b0e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,7 +67,7 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); - void (*disconnect_pipes)(struct dc *dc, + bool (*disconnect_pipes)(struct dc *dc, struct dc_state *context); void (*wait_for_pending_cleared)(struct dc *dc, struct dc_state *context); -- GitLab From d9beecfc79b71498e7f0bc40c550155f4e6b3c98 Mon Sep 17 00:00:00 2001 From: Anthony Koo <Anthony.Koo@amd.com> Date: Fri, 25 Sep 2020 10:54:54 -0400 Subject: [PATCH 1436/1494] drm/amd/display: [FW Promotion] Release 0.0.35 [Header Changes] - Definition for retaining ABM settings during disable - Addition of some new AUX interface definitions - Addition of some outbox definitions Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 132 +++++++++++++++++- 1 file changed, 126 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 0051b10002644..d103ec1eaa732 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xf547f0b9d +#define DMUB_FW_VERSION_GIT_HASH 0x9cf8f05fe #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 34 +#define DMUB_FW_VERSION_REVISION 35 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -57,6 +57,7 @@ #define SET_ABM_PIPE_GRADUALLY_DISABLE 0 #define SET_ABM_PIPE_IMMEDIATELY_DISABLE 255 +#define SET_ABM_PIPE_IMMEDIATE_KEEP_GAIN_DISABLE 254 #define SET_ABM_PIPE_NORMAL 1 /* Maximum number of streams on any ASIC. */ @@ -69,10 +70,6 @@ #define PHYSICAL_ADDRESS_LOC union large_integer #endif -#if defined(__cplusplus) -extern "C" { -#endif - #ifndef dmub_memcpy #define dmub_memcpy(dest, source, bytes) memcpy((dest), (source), (bytes)) #endif @@ -81,6 +78,10 @@ extern "C" { #define dmub_memset(dest, val, bytes) memset((dest), (val), (bytes)) #endif +#if defined(__cplusplus) +extern "C" { +#endif + #ifndef dmub_udelay #define dmub_udelay(microseconds) udelay(microseconds) #endif @@ -299,11 +300,15 @@ enum dmub_cmd_type { DMUB_CMD__PSR = 64, DMUB_CMD__ABM = 66, DMUB_CMD__HW_LOCK = 69, + DMUB_CMD__DP_AUX_ACCESS = 70, + DMUB_CMD__OUTBOX1_ENABLE = 71, DMUB_CMD__VBIOS = 128, }; enum dmub_out_cmd_type { DMUB_OUT_CMD__NULL = 0, + DMUB_OUT_CMD__DP_AUX_REPLY = 1, + DMUB_OUT_CMD__DP_HPD_NOTIFY = 2, }; #pragma pack(push, 1) @@ -461,6 +466,78 @@ struct dmub_rb_cmd_dpphy_init { uint8_t reserved[60]; }; +enum dp_aux_request_action { + DP_AUX_REQ_ACTION_I2C_WRITE = 0x00, + DP_AUX_REQ_ACTION_I2C_READ = 0x10, + DP_AUX_REQ_ACTION_I2C_STATUS_REQ = 0x20, + DP_AUX_REQ_ACTION_I2C_WRITE_MOT = 0x40, + DP_AUX_REQ_ACTION_I2C_READ_MOT = 0x50, + DP_AUX_REQ_ACTION_I2C_STATUS_REQ_MOT = 0x60, + DP_AUX_REQ_ACTION_DPCD_WRITE = 0x80, + DP_AUX_REQ_ACTION_DPCD_READ = 0x90 +}; + +/* DP AUX command */ +struct aux_transaction_parameters { + uint8_t is_i2c_over_aux; + uint8_t action; + uint8_t length; + uint8_t pad; + uint32_t address; + uint8_t data[16]; +}; + +struct dmub_cmd_dp_aux_control_data { + uint32_t handle; + uint8_t port_index; + uint8_t sw_crc_enabled; + uint16_t timeout; + struct aux_transaction_parameters dpaux; +}; + +struct dmub_rb_cmd_dp_aux_access { + struct dmub_cmd_header header; + struct dmub_cmd_dp_aux_control_data aux_control; +}; + +struct dmub_rb_cmd_outbox1_enable { + struct dmub_cmd_header header; + uint32_t enable; +}; + +/* DP AUX Reply command - OutBox Cmd */ +struct aux_reply_data { + uint8_t command; + uint8_t length; + uint8_t pad[2]; + uint8_t data[16]; +}; + +struct aux_reply_control_data { + uint32_t handle; + uint8_t phy_port_index; + uint8_t result; + uint16_t pad; +}; + +struct dmub_rb_cmd_dp_aux_reply { + struct dmub_cmd_header header; + struct aux_reply_control_data control; + struct aux_reply_data reply_data; +}; + +struct dp_hpd_data { + uint8_t phy_port_index; + uint8_t hpd_type; + uint8_t hpd_status; + uint8_t pad; +}; + +struct dmub_rb_cmd_dp_hpd_notify { + struct dmub_cmd_header header; + struct dp_hpd_data hpd_data; +}; + /* * Command IDs should be treated as stable ABI. * Do not reuse or modify IDs. @@ -690,8 +767,15 @@ union dmub_rb_cmd { struct dmub_rb_cmd_abm_set_ambient_level abm_set_ambient_level; struct dmub_rb_cmd_abm_set_pwm_frac abm_set_pwm_frac; struct dmub_rb_cmd_abm_init_config abm_init_config; + struct dmub_rb_cmd_dp_aux_access dp_aux_access; + struct dmub_rb_cmd_outbox1_enable outbox1_enable; }; +union dmub_rb_out_cmd { + struct dmub_rb_cmd_common cmd_common; + struct dmub_rb_cmd_dp_aux_reply dp_aux_reply; + struct dmub_rb_cmd_dp_hpd_notify dp_hpd_notify; +}; #pragma pack(pop) @@ -764,6 +848,25 @@ static inline bool dmub_rb_push_front(struct dmub_rb *rb, return true; } +static inline bool dmub_rb_out_push_front(struct dmub_rb *rb, + const union dmub_rb_out_cmd *cmd) +{ + uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt; + const uint8_t *src = (uint8_t *)cmd; + + if (dmub_rb_full(rb)) + return false; + + dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE); + + rb->wrpt += DMUB_RB_CMD_SIZE; + + if (rb->wrpt >= rb->capacity) + rb->wrpt %= rb->capacity; + + return true; +} + static inline bool dmub_rb_front(struct dmub_rb *rb, union dmub_rb_cmd *cmd) { @@ -777,6 +880,23 @@ static inline bool dmub_rb_front(struct dmub_rb *rb, return true; } +static inline bool dmub_rb_out_front(struct dmub_rb *rb, + union dmub_rb_out_cmd *cmd) +{ + const uint64_t volatile *src = (const uint64_t volatile *)(rb->base_address) + rb->rptr / sizeof(uint64_t); + uint64_t *dst = (uint64_t *)cmd; + int i; + + if (dmub_rb_empty(rb)) + return false; + + // copying data + for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++) + *dst++ = *src++; + + return true; +} + static inline bool dmub_rb_pop_front(struct dmub_rb *rb) { if (dmub_rb_empty(rb)) -- GitLab From 8353d30e747f4e5cdd867c6b054dbb85cdcc76a9 Mon Sep 17 00:00:00 2001 From: Chiawen Huang <chiawen.huang@amd.com> Date: Fri, 25 Sep 2020 10:54:55 -0400 Subject: [PATCH 1437/1494] drm/amd/display: disable stream if pixel clock changed with link active [Why] Vbios uses preferred timing to turn on edp but OS could use other timing. If change pixel clock when link active, there is unexpected garbage on monitor. [How] Once pixel clock changed, the driver needs to disable stream. Signed-off-by: Chiawen Huang <chiawen.huang@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 76946a7d47ca3..2a725a5fba402 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -864,7 +864,6 @@ static void disable_vbios_mode_if_required( if (stream->link->local_sink && stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { link = stream->link; - break; } if (link != NULL) { -- GitLab From 69fc1f4b976ceafe91c64e1fc4ec2a2fe8b916aa Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Mon, 11 May 2020 15:21:02 -0400 Subject: [PATCH 1438/1494] amd/drm/display: avoid dcn3 on flip opp change for slave pipes At the moment on flip opp reassignment does not work in all cases for non root pipes. This change simply makes sure we prefer pipes not used previously when splitting in dcn3. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Reviewed-by: Eric Bernstein <eric.bernstein@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 7f3354b3512db..c223f8af2084f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1899,6 +1899,41 @@ static bool dcn30_split_stream_for_mpc_or_odm( return true; } +static struct pipe_ctx *dcn30_find_split_pipe( + struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *pipe = NULL; + int i; + + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + } + + /* + * May need to fix pipes getting tossed from 1 opp to another on flip + * Add for debugging transient underflow during topology updates: + * ASSERT(pipe); + */ + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } + } + + return pipe; +} + static bool dcn30_internal_validate_bw( struct dc *dc, struct dc_state *context, @@ -2024,6 +2059,7 @@ static bool dcn30_internal_validate_bw( dcn20_release_dsc(&context->res_ctx, dc->res_pool, &pipe->stream_res.dsc); memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { struct pipe_ctx *top_pipe = pipe->top_pipe; struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; @@ -2038,6 +2074,7 @@ static bool dcn30_internal_validate_bw( pipe->stream = NULL; memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); + repopulate_pipes = true; } else ASSERT(0); /* Should never try to merge master pipe */ @@ -2058,7 +2095,7 @@ static bool dcn30_internal_validate_bw( continue; if (split[i]) { - hsplit_pipe = find_idle_secondary_pipe(&context->res_ctx, dc->res_pool, pipe); + hsplit_pipe = dcn30_find_split_pipe(dc, context); ASSERT(hsplit_pipe); if (!hsplit_pipe) goto validate_fail; @@ -2072,7 +2109,7 @@ static bool dcn30_internal_validate_bw( repopulate_pipes = true; } if (split[i] == 4) { - struct pipe_ctx *pipe_4to1 = find_idle_secondary_pipe(&context->res_ctx, dc->res_pool, pipe); + struct pipe_ctx *pipe_4to1 = dcn30_find_split_pipe(dc, context); ASSERT(pipe_4to1); if (!pipe_4to1) @@ -2083,7 +2120,7 @@ static bool dcn30_internal_validate_bw( goto validate_fail; newly_split[pipe_4to1->pipe_idx] = true; - pipe_4to1 = find_idle_secondary_pipe(&context->res_ctx, dc->res_pool, pipe); + pipe_4to1 = dcn30_find_split_pipe(dc, context); ASSERT(pipe_4to1); if (!pipe_4to1) goto validate_fail; -- GitLab From 0ac900bae2c385f169577e1bc5de711c1c648b2b Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Mon, 28 Sep 2020 10:36:41 +0800 Subject: [PATCH 1439/1494] drm/amd/display: make get_color_space_type() static This addresses the following sparse warning: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_hw_sequencer.c:180:26: warning: symbol 'get_color_space_type' was not declared. Should it be static? Reviewed-by: Harry Wentland <harry.wentland@amd.com> Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index c026b393f3c5f..2a9080400bdde 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -177,7 +177,7 @@ static bool is_ycbcr709_limited_type( ret = true; return ret; } -enum dc_color_space_type get_color_space_type(enum dc_color_space color_space) +static enum dc_color_space_type get_color_space_type(enum dc_color_space color_space) { enum dc_color_space_type type = COLOR_SPACE_RGB_TYPE; -- GitLab From faf0389f1e4004be84ede2d603d3f150d3cdfa99 Mon Sep 17 00:00:00 2001 From: Jason Yan <yanaijie@huawei.com> Date: Mon, 28 Sep 2020 10:35:43 +0800 Subject: [PATCH 1440/1494] drm/amd/display: make two symbols static This addresses the following sparse warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dce110/dce110_hw_sequencer.c:2740:6: warning: symbol 'dce110_set_cursor_position' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/dce110/dce110_hw_sequencer.c:2785:6: warning: symbol 'dce110_set_cursor_attribute' was not declared. Should it be static? Reviewed-by: Harry Wentland <harry.wentland@amd.com> Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Jason Yan <yanaijie@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index c73768ed250e8..3ac6c7b65a45a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -2737,7 +2737,7 @@ static void program_output_csc(struct dc *dc, } } -void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) +static void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) { struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; @@ -2782,7 +2782,7 @@ void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); } -void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) +static void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) { struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; -- GitLab From 3514521ccbd25ef3bd47b3c2abc28befbea8cdb1 Mon Sep 17 00:00:00 2001 From: Jean Delvare <jdelvare@suse.de> Date: Mon, 28 Sep 2020 11:10:37 +0200 Subject: [PATCH 1441/1494] drm/amdgpu: restore proper ref count in amdgpu_display_crtc_set_config A recent attempt to fix a ref count leak in amdgpu_display_crtc_set_config() turned out to be doing too much and "fixed" an intended decrease as if it were a leak. Undo that part to restore the proper balance. This is the very nature of this function to increase or decrease the power reference count depending on the situation. Consequences of this bug is that the power reference would eventually get down to 0 while the display was still in use, resulting in that display switching off unexpectedly. Signed-off-by: Jean Delvare <jdelvare@suse.de> Fixes: e008fa6fb415 ("drm/amdgpu: fix ref count leak in amdgpu_display_crtc_set_config") Cc: stable@vger.kernel.org Cc: Navid Emamdoost <navid.emamdoost@gmail.com> Cc: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index c81206e6096f4..7cc7af2a6822e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -297,7 +297,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set, take the current one */ if (active && !adev->have_disp_power_ref) { adev->have_disp_power_ref = true; - goto out; + return ret; } /* if we have no active crtcs, then drop the power ref we got before */ -- GitLab From 125b1deb604305025958939deb96ca95cdc24680 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Tue, 29 Sep 2020 12:32:29 +0800 Subject: [PATCH 1442/1494] drm/amdgpu: fix incorrect comment It should be one copy-paste typo. Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h index f29a8611d69b0..1308d976d60ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.h @@ -26,4 +26,4 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev); -#endif // __AMDGPU_PRODINFO_H__ +#endif // __AMDGPU_FRU_EEPROM_H__ -- GitLab From 72e71a82d6986b2259168575b1cea7fb78f9da32 Mon Sep 17 00:00:00 2001 From: Shashank Sharma <shashank.sharma@amd.com> Date: Wed, 29 Jul 2020 16:39:39 +0530 Subject: [PATCH 1443/1494] drm/amdgpu: add new trace event for page table update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new trace event to track the PTE update events. This specific event will provide information like: - start and end of virtual memory mapping - HW engine flags for the map - physical address for mapping This will be particularly useful for memory profiling tools (like RMV) which are monitoring the page table update events. V2: Added physical address lookup logic in trace point V3: switch to use __dynamic_array added nptes int the TPprint arguments list added page size in the arg list V4: Addressed Christian's review comments add start/end instead of seg use incr instead of page_sz to be accurate V5: Addressed Christian's review comments: add pid and vm context information in the event V6: Re-sequence the variables (put pid and ctx_id first) Cc: Christian König <christian.koenig@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Shashank Sharma <shashank.sharma@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 43 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 11 ++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 63e734a125fb6..82c2e70a6a714 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -321,6 +321,49 @@ DEFINE_EVENT(amdgpu_vm_mapping, amdgpu_vm_bo_cs, TP_ARGS(mapping) ); +TRACE_EVENT(amdgpu_vm_update_ptes, + TP_PROTO(struct amdgpu_vm_update_params *p, + uint64_t start, uint64_t end, + unsigned int nptes, uint64_t dst, + uint64_t incr, uint64_t flags, + pid_t pid, uint64_t vm_ctx), + TP_ARGS(p, start, end, nptes, dst, incr, flags, pid, vm_ctx), + TP_STRUCT__entry( + __field(u64, start) + __field(u64, end) + __field(u64, flags) + __field(unsigned int, nptes) + __field(u64, incr) + __field(pid_t, pid) + __field(u64, vm_ctx) + __dynamic_array(u64, dst, nptes) + ), + + TP_fast_assign( + unsigned int i; + + __entry->start = start; + __entry->end = end; + __entry->flags = flags; + __entry->incr = incr; + __entry->nptes = nptes; + __entry->pid = pid; + __entry->vm_ctx = vm_ctx; + for (i = 0; i < nptes; ++i) { + u64 addr = p->pages_addr ? amdgpu_vm_map_gart( + p->pages_addr, dst) : dst; + + ((u64 *)__get_dynamic_array(dst))[i] = addr; + dst += incr; + } + ), + TP_printk("pid:%u vm_ctx:0x%llx start:0x%010llx end:0x%010llx," + " flags:0x%llx, incr:%llu, dst:\n%s", __entry->pid, + __entry->vm_ctx, __entry->start, __entry->end, + __entry->flags, __entry->incr, __print_array( + __get_dynamic_array(dst), __entry->nptes, 8)) +); + TRACE_EVENT(amdgpu_vm_set_ptes, TP_PROTO(uint64_t pe, uint64_t addr, unsigned count, uint32_t incr, uint64_t flags, bool direct), diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 420931d36732f..a4efc903349e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1513,19 +1513,26 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, entry_end = min(entry_end, end); do { + struct amdgpu_vm *vm = params->vm; uint64_t upd_end = min(entry_end, frag_end); unsigned nptes = (upd_end - frag_start) >> shift; + uint64_t upd_flags = flags | AMDGPU_PTE_FRAG(frag); /* This can happen when we set higher level PDs to * silent to stop fault floods. */ nptes = max(nptes, 1u); + + trace_amdgpu_vm_update_ptes(params, frag_start, upd_end, + nptes, dst, incr, upd_flags, + vm->task_info.pid, + vm->immediate.fence_context); amdgpu_vm_update_flags(params, pt, cursor.level, pe_start, dst, nptes, incr, - flags | AMDGPU_PTE_FRAG(frag)); + upd_flags); pe_start += nptes * 8; - dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift; + dst += nptes * incr; frag_start = upd_end; if (frag_start >= frag_end) { -- GitLab From 12a6727dee5d1119fc1556b870848f511414bf5d Mon Sep 17 00:00:00 2001 From: Xiaojian Du <Xiaojian.Du@amd.com> Date: Sun, 27 Sep 2020 17:07:02 +0800 Subject: [PATCH 1444/1494] drm/amd/powerplay: add one sysfs file to support the feature to modify gfx clock on Raven/Raven2/Picasso APU. This patch is to add one sysfs file -- "pp_od_clk_voltage" for Raven/Raven2/Picasso APU, which is only used by dGPU like VEGA10. This sysfs file supports the feature to modify gfx engine clock(Mhz units), it can be used to configure the min value and the max value for gfx clock limited in the safe range. Command guide: echo "s level clock" > pp_od_clk_voltage s - adjust teh sclk level level - 0 or 1, "0" represents the min value, "1" represents the max value clock - the clock value(Mhz units), like 400, 800 or 1200, the value must be within the OD_RANGE limits. Example: $ cat pp_od_clk_voltage OD_SCLK: 0: 200Mhz 1: 1400Mhz OD_RANGE: SCLK: 200MHz 1400MHz $ echo "s 0 600" > pp_od_clk_voltage $ echo "s 1 1000" > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 600Mhz 1: 1000Mhz OD_RANGE: SCLK: 200MHz 1400MHz Signed-off-by: Xiaojian Du <Xiaojian.Du@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 12 +++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 + drivers/gpu/drm/amd/pm/inc/hwmgr.h | 5 ++ .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 16 +++- .../drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 80 +++++++++++++++++++ .../drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h | 2 +- 7 files changed, 118 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 0aec28fda0587..94132c70d7afd 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -281,6 +281,7 @@ struct amd_pm_funcs { int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit); int (*get_power_profile_mode)(void *handle, char *buf); int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state); int (*smu_i2c_bus_access)(void *handle, bool acquire); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 2d924e88a215b..529816637c731 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -827,6 +827,18 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return -EINVAL; } } else { + + if (adev->powerplay.pp_funcs->set_fine_grain_clk_vol) { + ret = amdgpu_dpm_set_fine_grain_clk_vol(adev, type, + parameter, + parameter_size); + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } + if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, parameter_size); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index dff4a5f99bb03..f6e0e7d8a0077 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -349,6 +349,10 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ (adev)->powerplay.pp_handle, parameter, size)) +#define amdgpu_dpm_set_fine_grain_clk_vol(adev, type, parameter, size) \ + ((adev)->powerplay.pp_funcs->set_fine_grain_clk_vol(\ + (adev)->powerplay.pp_handle, type, parameter, size)) + #define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ (adev)->powerplay.pp_handle, type, parameter, size)) diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h index 1b3529efc91e6..3898a95ec28b1 100644 --- a/drivers/gpu/drm/amd/pm/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h @@ -340,6 +340,9 @@ struct pp_hwmgr_func { int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); int (*powergate_mmhub)(struct pp_hwmgr *hwmgr); int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); @@ -347,6 +350,8 @@ struct pp_hwmgr_func { int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*set_hard_min_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*set_soft_max_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index a6321f2063c1d..eab9768029c11 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -911,6 +911,19 @@ static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) return ret; } +static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL) + return 0; + + return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size); +} + static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) { struct pp_hwmgr *hwmgr = handle; @@ -920,7 +933,7 @@ static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint3 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; + return 0; } return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size); @@ -1645,6 +1658,7 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .set_powergating_by_smu = pp_set_powergating_by_smu, .get_power_profile_mode = pp_get_power_profile_mode, .set_power_profile_mode = pp_set_power_profile_mode, + .set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol, .odn_edit_dpm_table = pp_odn_edit_dpm_table, .set_mp1_state = pp_dpm_set_mp1_state, .set_power_limit = pp_set_power_limit, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index e0ac54608e88e..cf60f39923038 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -242,6 +242,34 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t cloc return 0; } +static int smu10_set_hard_min_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (clock && smu10_data->gfx_actual_soft_min_freq != clock) { + smu10_data->gfx_actual_soft_min_freq = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + smu10_data->gfx_actual_soft_min_freq, + NULL); + } + return 0; +} + +static int smu10_set_soft_max_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (clock && smu10_data->gfx_max_freq_limit != (clock * 100)) { + smu10_data->gfx_max_freq_limit = clock * 100; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + clock, + NULL); + } + return 0; +} + static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); @@ -527,6 +555,9 @@ static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100; hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100; + /* enable the pp_od_clk_voltage sysfs file */ + hwmgr->od_enabled = 1; + return result; } @@ -949,6 +980,26 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, ((mclk_table->entries[i].clk / 100) == now) ? "*" : ""); break; + case OD_SCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + + size += sprintf(buf + size, "0: %10uMhz\n", + (data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : data->gfx_min_freq_limit/100); + size += sprintf(buf + size, "1: %10uMhz\n", data->gfx_max_freq_limit/100); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { + uint32_t min_freq, max_freq = 0; + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq); + + size = sprintf(buf, "%s:\n", "OD_RANGE"); + size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + min_freq, max_freq); + } + break; default: break; } @@ -1361,6 +1412,32 @@ static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mod NULL); } +static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + if (!hwmgr->od_enabled) { + pr_err("Fine grain not support\n"); + return -EINVAL; + } + + if (size != 2) { + pr_err("Input parameter number not correct\n"); + return -EINVAL; + } + + if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { + if (input[0] == 0) + smu10_set_hard_min_gfxclk_by_freq(hwmgr, input[1]); + else if (input[0] == 1) + smu10_set_soft_max_gfxclk_by_freq(hwmgr, input[1]); + else + return -EINVAL; + } + + return 0; +} + static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .backend_init = smu10_hwmgr_backend_init, .backend_fini = smu10_hwmgr_backend_fini, @@ -1401,9 +1478,12 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .powergate_sdma = smu10_powergate_sdma, .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, + .set_hard_min_gfxclk_by_freq = smu10_set_hard_min_gfxclk_by_freq, + .set_soft_max_gfxclk_by_freq = smu10_set_soft_max_gfxclk_by_freq, .get_power_profile_mode = smu10_get_power_profile_mode, .set_power_profile_mode = smu10_set_power_profile_mode, .asic_reset = smu10_asic_reset, + .set_fine_grain_clk_vol = smu10_set_fine_grain_clk_vol, }; int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h index ee0c9591620b1..6c9b5f060902b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h @@ -284,7 +284,7 @@ struct smu10_hwmgr { uint32_t dclk_soft_min; uint32_t gfx_actual_soft_min_freq; uint32_t gfx_min_freq_limit; - uint32_t gfx_max_freq_limit; + uint32_t gfx_max_freq_limit; /* in 10Khz*/ bool vcn_power_gated; bool vcn_dpg_mode; -- GitLab From 808ec542c0297ae0b945ed0e6aba6f625ea2353c Mon Sep 17 00:00:00 2001 From: Dirk Gouders <dirk@gouders.net> Date: Sun, 27 Sep 2020 11:39:45 +0200 Subject: [PATCH 1445/1494] drm/amd/display: remove duplicate call to rn_vbios_smu_get_smu_version() Commit 78fe9f63947a2b ("drm/amd/display: Remove DISPCLK Limit Floor for Certain SMU Versions") added a call to rn_vbios_smu_get_smu_version() to set clk_mgr->smu_ver. That field is initialized prior to the if-statement, already. Fixes: 78fe9f63947a2b (drm/amd/display: Remove DISPCLK Limit Floor for Certain SMU Versions) Signed-off-by: Dirk Gouders <dirk@gouders.net> Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Sung Lee <sung.lee@amd.com> Cc: Yongqiang Sun <yongqiang.sun@amd.com> Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 136ae6d70c809..2f8fee05547ac 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -784,7 +784,6 @@ void rn_clk_mgr_construct( } else { struct clk_log_info log_info = {0}; - clk_mgr->smu_ver = rn_vbios_smu_get_smu_version(clk_mgr); clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr); /* SMU Version 55.51.0 and up no longer have an issue -- GitLab From 485d531c695b0f5c87180a7724b85322d3967d39 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Mon, 28 Sep 2020 14:16:25 -0400 Subject: [PATCH 1446/1494] drm/amdgpu/swsmu/smu12: fix force clock handling for mclk The state array is in the reverse order compared to other asics (high to low rather than low to high). Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1313 Reviewed-by: Prike Liang <Prike.Liang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 55a254be5ac24..66c1026489bee 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -222,14 +222,16 @@ static int renoir_get_profiling_clk_mask(struct smu_context *smu, *sclk_mask = 0; } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { if (mclk_mask) - *mclk_mask = 0; + /* mclk levels are in reverse order */ + *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { if(sclk_mask) /* The sclk as gfxclk and has three level about max/min/current */ *sclk_mask = 3 - 1; if(mclk_mask) - *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; + /* mclk levels are in reverse order */ + *mclk_mask = 0; if(soc_mask) *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; @@ -323,7 +325,7 @@ static int renoir_get_dpm_ultimate_freq(struct smu_context *smu, case SMU_UCLK: case SMU_FCLK: case SMU_MCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); + ret = renoir_get_dpm_clk_limited(smu, clk_type, NUM_MEMCLK_DPM_LEVELS - 1, min); if (ret) goto failed; break; -- GitLab From f94582e4bc4f73c1a265fdbe9aafd6eb5d314c41 Mon Sep 17 00:00:00 2001 From: Kent Russell <kent.russell@amd.com> Date: Mon, 28 Sep 2020 14:20:05 -0400 Subject: [PATCH 1447/1494] drm/amdgpu: Use SKU instead of DID for FRU check v2 The VG20 DIDs 66a0, 66a1 and 66a4 are used for various SKUs that may or may not have the FRU EEPROM on it. Parse the VBIOS to check for server SKU variants (D131 or D134) until a more general solution can be determined. v2: Remove string-based logic, correct the VBIOS string comment Signed-off-by: Kent Russell <kent.russell@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index e811fecc540fb..8f4a8f8d81463 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -34,18 +34,31 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) { - /* TODO: Gaming SKUs don't have the FRU EEPROM. - * Use this hack to address hangs on modprobe on gaming SKUs - * until a proper solution can be implemented by only supporting - * the explicit chip IDs for VG20 Server cards - * - * TODO: Add list of supported Arcturus DIDs once confirmed + /* Only server cards have the FRU EEPROM + * TODO: See if we can figure this out dynamically instead of + * having to parse VBIOS versions. */ - if ((adev->asic_type == CHIP_VEGA20 && adev->pdev->device == 0x66a0) || - (adev->asic_type == CHIP_VEGA20 && adev->pdev->device == 0x66a1) || - (adev->asic_type == CHIP_VEGA20 && adev->pdev->device == 0x66a4)) - return true; - return false; + struct atom_context *atom_ctx = adev->mode_info.atom_context; + + /* VBIOS is of the format ###-DXXXYY-##. For SKU identification, + * we can use just the "DXXX" portion. If there were more models, we + * could convert the 3 characters to a hex integer and use a switch + * for ease/speed/readability. For now, 2 string comparisons are + * reasonable and not too expensive + */ + switch (adev->asic_type) { + case CHIP_VEGA20: + /* D161 and D163 are the VG20 server SKUs */ + if (strnstr(atom_ctx->vbios_version, "D161", + sizeof(atom_ctx->vbios_version)) || + strnstr(atom_ctx->vbios_version, "D163", + sizeof(atom_ctx->vbios_version))) + return true; + else + return false; + default: + return false; + } } static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, -- GitLab From b8810a142ad5494ecfe7ef2fa289868562918cd1 Mon Sep 17 00:00:00 2001 From: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Date: Tue, 29 Sep 2020 11:46:51 -0500 Subject: [PATCH 1448/1494] drm/amd/amdgpu: Clean up header file of symbols that are defined to be static [Why] Header file exports functions get_gpu_clock_counter(), get_cu_info() and select_se_sh() that are defined to be static Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h index fa5a3fbaf6aba..407472031daaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h @@ -26,9 +26,4 @@ extern const struct amdgpu_ip_block_version gfx_v9_0_ip_block; -void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num); - -uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev); -int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info); - #endif -- GitLab From 825c91d0908b72f9ec2a9e0c815d2c40af5ad5f4 Mon Sep 17 00:00:00 2001 From: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Date: Tue, 29 Sep 2020 12:06:15 -0500 Subject: [PATCH 1449/1494] drm/amd/amdgpu: Prepare implementation to support reporting of CU usage [Why] Allow user to know number of compute units (CU) that are in use at any given moment. [How] Read registers of SQ that give number of waves that are in flight of various queues. Use this information to determine number of CU's in use. Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 346d8288f6ab1..6959aebae6d41 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -49,6 +49,7 @@ #include "amdgpu_ras.h" #include "gfx_v9_4.h" +#include "gfx_v9_0.h" #include "asic_reg/pwr/pwr_10_0_offset.h" #include "asic_reg/pwr/pwr_10_0_sh_mask.h" @@ -788,7 +789,6 @@ static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev); static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info); static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev); -static void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring); static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring); static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, @@ -2397,7 +2397,8 @@ static void gfx_v9_0_tiling_mode_table_init(struct amdgpu_device *adev) /* TODO */ } -static void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance) +void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num, + u32 instance) { u32 data; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h index 407472031daaf..dfe8d4841f582 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.h @@ -26,4 +26,7 @@ extern const struct amdgpu_ip_block_version gfx_v9_0_ip_block; +void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num, + u32 instance); + #endif -- GitLab From 8ffff9b4499cbbda5b44cf84df576a7c5a3c2e06 Mon Sep 17 00:00:00 2001 From: Oak Zeng <Oak.Zeng@amd.com> Date: Thu, 17 Sep 2020 18:10:12 -0500 Subject: [PATCH 1450/1494] drm/amdgpu: use function pointer for gfxhub functions gfxhub functions are now called from function pointers, instead of from asic-specific functions. Signed-off-by: Oak Zeng <Oak.Zeng@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++ .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 3 +- .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 3 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h | 43 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c | 10 ++++ drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.h | 1 + drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c | 13 ++++- drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.h | 2 +- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 24 ++++++--- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h | 10 +--- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 27 +++++++--- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.h | 12 +---- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 53 ++++++++----------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 28 +++++++--- 15 files changed, 155 insertions(+), 83 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6125ba905faf8..befef3b60547e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -104,6 +104,7 @@ #include "amdgpu_mes.h" #include "amdgpu_umc.h" #include "amdgpu_mmhub.h" +#include "amdgpu_gfxhub.h" #include "amdgpu_df.h" #define MAX_GPU_INSTANCE 16 @@ -881,6 +882,9 @@ struct amdgpu_device { /* mmhub */ struct amdgpu_mmhub mmhub; + /* gfxhub */ + struct amdgpu_gfxhub gfxhub; + /* gfx */ struct amdgpu_gfx gfx; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index df0aab0fc67e6..1529815838f74 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -32,7 +32,6 @@ #include "v10_structs.h" #include "nv.h" #include "nvd.h" -#include "gfxhub_v2_0.h" enum hqd_dequeue_request_type { NO_ACTION = 0, @@ -753,7 +752,7 @@ static void set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, } /* SDMA is on gfxhub as well for Navi1* series */ - gfxhub_v2_0_setup_vm_pt_regs(adev, vmid, page_table_base); + adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); } const struct kfd2kgd_calls gfx_v10_kfd2kgd = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index 5b38f848b7729..50016bf9c4279 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -31,7 +31,6 @@ #include "v10_structs.h" #include "nv.h" #include "nvd.h" -#include "gfxhub_v2_1.h" enum hqd_dequeue_request_type { NO_ACTION = 0, @@ -657,7 +656,7 @@ static void set_vm_context_page_table_base_v10_3(struct kgd_dev *kgd, uint32_t v struct amdgpu_device *adev = get_amdgpu_device(kgd); /* SDMA is on gfxhub as well for Navi1* series */ - gfxhub_v2_1_setup_vm_pt_regs(adev, vmid, page_table_base); + adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); } #if 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index e6aede7251978..b824582463933 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -36,9 +36,6 @@ #include "v9_structs.h" #include "soc15.h" #include "soc15d.h" -#include "mmhub_v1_0.h" -#include "gfxhub_v1_0.h" - enum hqd_dequeue_request_type { NO_ACTION = 0, @@ -703,7 +700,7 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, adev->mmhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); - gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); + adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); } const struct kfd2kgd_calls gfx_v9_kfd2kgd = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h new file mode 100644 index 0000000000000..66ebc2e3b2adc --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_GFXHUB_H__ +#define __AMDGPU_GFXHUB_H__ + +struct amdgpu_gfxhub_funcs { + u64 (*get_fb_location)(struct amdgpu_device *adev); + u64 (*get_mc_fb_offset)(struct amdgpu_device *adev); + void (*setup_vm_pt_regs)(struct amdgpu_device *adev, uint32_t vmid, + uint64_t page_table_base); + int (*gart_enable)(struct amdgpu_device *adev); + + void (*gart_disable)(struct amdgpu_device *adev); + void (*set_fault_enable_default)(struct amdgpu_device *adev, bool value); + void (*init)(struct amdgpu_device *adev); + int (*get_xgmi_info)(struct amdgpu_device *adev); +}; + +struct amdgpu_gfxhub { + const struct amdgpu_gfxhub_funcs *funcs; +}; + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 40b17da6a357e..fad887a668866 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -403,3 +403,13 @@ void gfxhub_v1_0_init(struct amdgpu_device *adev) hub->eng_addr_distance = mmVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 - mmVM_INVALIDATE_ENG0_ADDR_RANGE_LO32; } + + +const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs = { + .get_mc_fb_offset = gfxhub_v1_0_get_mc_fb_offset, + .setup_vm_pt_regs = gfxhub_v1_0_setup_vm_pt_regs, + .gart_enable = gfxhub_v1_0_gart_enable, + .gart_disable = gfxhub_v1_0_gart_disable, + .set_fault_enable_default = gfxhub_v1_0_set_fault_enable_default, + .init = gfxhub_v1_0_init, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.h index 92d3a70cd9b15..0c46672bbf493 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.h @@ -33,4 +33,5 @@ u64 gfxhub_v1_0_get_mc_fb_offset(struct amdgpu_device *adev); void gfxhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base); +extern const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c index c0ab71df0d904..1e24b6d51e41e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.c @@ -21,6 +21,7 @@ * */ #include "amdgpu.h" +#include "gfxhub_v1_0.h" #include "gfxhub_v1_1.h" #include "gc/gc_9_2_1_offset.h" @@ -28,7 +29,7 @@ #include "soc15_common.h" -int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev) +static int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev) { u32 xgmi_lfb_cntl = RREG32_SOC15(GC, 0, mmMC_VM_XGMI_LFB_CNTL); u32 max_region = @@ -66,3 +67,13 @@ int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev) return 0; } + +const struct amdgpu_gfxhub_funcs gfxhub_v1_1_funcs = { + .get_mc_fb_offset = gfxhub_v1_0_get_mc_fb_offset, + .setup_vm_pt_regs = gfxhub_v1_0_setup_vm_pt_regs, + .gart_enable = gfxhub_v1_0_gart_enable, + .gart_disable = gfxhub_v1_0_gart_disable, + .set_fault_enable_default = gfxhub_v1_0_set_fault_enable_default, + .init = gfxhub_v1_0_init, + .get_xgmi_info = gfxhub_v1_1_get_xgmi_info, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.h index d753cf28a0a6e..ae5759ffbee37 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.h +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_1.h @@ -24,6 +24,6 @@ #ifndef __GFXHUB_V1_1_H__ #define __GFXHUB_V1_1_H__ -int gfxhub_v1_1_get_xgmi_info(struct amdgpu_device *adev); +extern const struct amdgpu_gfxhub_funcs gfxhub_v1_1_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index d623aeba08d5b..456360bf58faf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -102,7 +102,7 @@ gfxhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, GCVM_L2_PROTECTION_FAULT_STATUS, RW)); } -u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev) +static u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE); @@ -112,12 +112,12 @@ u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev) return base; } -u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev) +static u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev) { return (u64)RREG32_SOC15(GC, 0, mmGCMC_VM_FB_OFFSET) << 24; } -void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -342,7 +342,7 @@ static void gfxhub_v2_0_program_invalidation(struct amdgpu_device *adev) } } -int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev) +static int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev) { /* GART Enable. */ gfxhub_v2_0_init_gart_aperture_regs(adev); @@ -358,7 +358,7 @@ int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev) return 0; } -void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev) +static void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; u32 tmp; @@ -389,7 +389,7 @@ void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, +static void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -431,7 +431,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v2_0_vmhub_funcs = { .get_invalidate_req = gfxhub_v2_0_get_invalidate_req, }; -void gfxhub_v2_0_init(struct amdgpu_device *adev) +static void gfxhub_v2_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -472,3 +472,13 @@ void gfxhub_v2_0_init(struct amdgpu_device *adev) hub->vmhub_funcs = &gfxhub_v2_0_vmhub_funcs; } + +const struct amdgpu_gfxhub_funcs gfxhub_v2_0_funcs = { + .get_fb_location = gfxhub_v2_0_get_fb_location, + .get_mc_fb_offset = gfxhub_v2_0_get_mc_fb_offset, + .setup_vm_pt_regs = gfxhub_v2_0_setup_vm_pt_regs, + .gart_enable = gfxhub_v2_0_gart_enable, + .gart_disable = gfxhub_v2_0_gart_disable, + .set_fault_enable_default = gfxhub_v2_0_set_fault_enable_default, + .init = gfxhub_v2_0_init, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h index 392b8cd94fc0f..9ddc35cd53d4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.h @@ -24,14 +24,6 @@ #ifndef __GFXHUB_V2_0_H__ #define __GFXHUB_V2_0_H__ -u64 gfxhub_v2_0_get_fb_location(struct amdgpu_device *adev); -int gfxhub_v2_0_gart_enable(struct amdgpu_device *adev); -void gfxhub_v2_0_gart_disable(struct amdgpu_device *adev); -void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void gfxhub_v2_0_init(struct amdgpu_device *adev); -u64 gfxhub_v2_0_get_mc_fb_offset(struct amdgpu_device *adev); -void gfxhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); +extern const struct amdgpu_gfxhub_funcs gfxhub_v2_0_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 6dc7a040ed7f9..724bb29e9bb44 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -102,7 +102,7 @@ gfxhub_v2_1_print_l2_protection_fault_status(struct amdgpu_device *adev, GCVM_L2_PROTECTION_FAULT_STATUS, RW)); } -u64 gfxhub_v2_1_get_fb_location(struct amdgpu_device *adev) +static u64 gfxhub_v2_1_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(GC, 0, mmGCMC_VM_FB_LOCATION_BASE); @@ -112,12 +112,12 @@ u64 gfxhub_v2_1_get_fb_location(struct amdgpu_device *adev) return base; } -u64 gfxhub_v2_1_get_mc_fb_offset(struct amdgpu_device *adev) +static u64 gfxhub_v2_1_get_mc_fb_offset(struct amdgpu_device *adev) { return (u64)RREG32_SOC15(GC, 0, mmGCMC_VM_FB_OFFSET) << 24; } -void gfxhub_v2_1_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void gfxhub_v2_1_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -348,7 +348,7 @@ static void gfxhub_v2_1_program_invalidation(struct amdgpu_device *adev) } } -int gfxhub_v2_1_gart_enable(struct amdgpu_device *adev) +static int gfxhub_v2_1_gart_enable(struct amdgpu_device *adev) { if (amdgpu_sriov_vf(adev)) { /* @@ -376,7 +376,7 @@ int gfxhub_v2_1_gart_enable(struct amdgpu_device *adev) return 0; } -void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev) +static void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; u32 tmp; @@ -405,7 +405,7 @@ void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, +static void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -454,7 +454,7 @@ static const struct amdgpu_vmhub_funcs gfxhub_v2_1_vmhub_funcs = { .get_invalidate_req = gfxhub_v2_1_get_invalidate_req, }; -void gfxhub_v2_1_init(struct amdgpu_device *adev) +static void gfxhub_v2_1_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0]; @@ -496,7 +496,7 @@ void gfxhub_v2_1_init(struct amdgpu_device *adev) hub->vmhub_funcs = &gfxhub_v2_1_vmhub_funcs; } -int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev) +static int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev) { u32 xgmi_lfb_cntl = RREG32_SOC15(GC, 0, mmGCMC_VM_XGMI_LFB_CNTL); u32 max_region = @@ -531,3 +531,14 @@ int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev) return 0; } + +const struct amdgpu_gfxhub_funcs gfxhub_v2_1_funcs = { + .get_fb_location = gfxhub_v2_1_get_fb_location, + .get_mc_fb_offset = gfxhub_v2_1_get_mc_fb_offset, + .setup_vm_pt_regs = gfxhub_v2_1_setup_vm_pt_regs, + .gart_enable = gfxhub_v2_1_gart_enable, + .gart_disable = gfxhub_v2_1_gart_disable, + .set_fault_enable_default = gfxhub_v2_1_set_fault_enable_default, + .init = gfxhub_v2_1_init, + .get_xgmi_info = gfxhub_v2_1_get_xgmi_info, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.h b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.h index 3452a4e9a3dae..f75c2eccfad97 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.h +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.h @@ -24,16 +24,6 @@ #ifndef __GFXHUB_V2_1_H__ #define __GFXHUB_V2_1_H__ -u64 gfxhub_v2_1_get_fb_location(struct amdgpu_device *adev); -int gfxhub_v2_1_gart_enable(struct amdgpu_device *adev); -void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev); -void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void gfxhub_v2_1_init(struct amdgpu_device *adev); -u64 gfxhub_v2_1_get_mc_fb_offset(struct amdgpu_device *adev); -void gfxhub_v2_1_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); - -int gfxhub_v2_1_get_xgmi_info(struct amdgpu_device *adev); +extern const struct amdgpu_gfxhub_funcs gfxhub_v2_1_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 31359e519d69d..dbc8b76b9b78e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -634,11 +634,26 @@ static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev) adev->mmhub.funcs = &mmhub_v2_0_funcs; } +static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + adev->gfxhub.funcs = &gfxhub_v2_1_funcs; + break; + default: + adev->gfxhub.funcs = &gfxhub_v2_0_funcs; + break; + } +} + + static int gmc_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; gmc_v10_0_set_mmhub_funcs(adev); + gmc_v10_0_set_gfxhub_funcs(adev); gmc_v10_0_set_gmc_funcs(adev); gmc_v10_0_set_irq_funcs(adev); gmc_v10_0_set_umc_funcs(adev); @@ -676,11 +691,7 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev, { u64 base = 0; - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - base = gfxhub_v2_1_get_fb_location(adev); - else - base = gfxhub_v2_0_get_fb_location(adev); + base = adev->gfxhub.funcs->get_fb_location(adev); /* add the xgmi offset of the physical node */ base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; @@ -689,11 +700,7 @@ static void gmc_v10_0_vram_gtt_location(struct amdgpu_device *adev, amdgpu_gmc_gart_location(adev, mc); /* base offset of vram pages */ - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - adev->vm_manager.vram_base_offset = gfxhub_v2_1_get_mc_fb_offset(adev); - else - adev->vm_manager.vram_base_offset = gfxhub_v2_0_get_mc_fb_offset(adev); + adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev); /* add the xgmi offset of the physical node */ adev->vm_manager.vram_base_offset += @@ -777,11 +784,7 @@ static int gmc_v10_0_sw_init(void *handle) int r, vram_width = 0, vram_type = 0, vram_vendor = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - gfxhub_v2_1_init(adev); - else - gfxhub_v2_0_init(adev); + adev->gfxhub.funcs->init(adev); adev->mmhub.funcs->init(adev); @@ -852,7 +855,7 @@ static int gmc_v10_0_sw_init(void *handle) } if (adev->gmc.xgmi.supported) { - r = gfxhub_v2_1_get_xgmi_info(adev); + r = adev->gfxhub.funcs->get_xgmi_info(adev); if (r) return r; } @@ -944,11 +947,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - r = gfxhub_v2_1_gart_enable(adev); - else - r = gfxhub_v2_0_gart_enable(adev); + r = adev->gfxhub.funcs->gart_enable(adev); if (r) return r; @@ -969,11 +968,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ? false : true; - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - gfxhub_v2_1_set_fault_enable_default(adev, value); - else - gfxhub_v2_0_set_fault_enable_default(adev, value); + adev->gfxhub.funcs->set_fault_enable_default(adev, value); adev->mmhub.funcs->set_fault_enable_default(adev, value); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB_0, 0); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB_0, 0); @@ -1014,11 +1009,7 @@ static int gmc_v10_0_hw_init(void *handle) */ static void gmc_v10_0_gart_disable(struct amdgpu_device *adev) { - if (adev->asic_type == CHIP_SIENNA_CICHLID || - adev->asic_type == CHIP_NAVY_FLOUNDER) - gfxhub_v2_1_gart_disable(adev); - else - gfxhub_v2_0_gart_disable(adev); + adev->gfxhub.funcs->gart_disable(adev); adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index cb9e9e5afa5a1..c692facdd6b6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1164,6 +1164,19 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev) } } +static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_ARCTURUS: + case CHIP_VEGA20: + adev->gfxhub.funcs = &gfxhub_v1_1_funcs; + break; + default: + adev->gfxhub.funcs = &gfxhub_v1_0_funcs; + break; + } +} + static int gmc_v9_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1172,6 +1185,7 @@ static int gmc_v9_0_early_init(void *handle) gmc_v9_0_set_irq_funcs(adev); gmc_v9_0_set_umc_funcs(adev); gmc_v9_0_set_mmhub_funcs(adev); + gmc_v9_0_set_gfxhub_funcs(adev); adev->gmc.shared_aperture_start = 0x2000000000000000ULL; adev->gmc.shared_aperture_end = @@ -1234,7 +1248,7 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev, amdgpu_gmc_gart_location(adev, mc); amdgpu_gmc_agp_location(adev, mc); /* base offset of vram pages */ - adev->vm_manager.vram_base_offset = gfxhub_v1_0_get_mc_fb_offset(adev); + adev->vm_manager.vram_base_offset = adev->gfxhub.funcs->get_mc_fb_offset(adev); /* XXX: add the xgmi offset of the physical node? */ adev->vm_manager.vram_base_offset += @@ -1269,7 +1283,7 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev) #ifdef CONFIG_X86_64 if (adev->flags & AMD_IS_APU) { - adev->gmc.aper_base = gfxhub_v1_0_get_mc_fb_offset(adev); + adev->gmc.aper_base = adev->gfxhub.funcs->get_mc_fb_offset(adev); adev->gmc.aper_size = adev->gmc.real_vram_size; } #endif @@ -1339,7 +1353,7 @@ static int gmc_v9_0_sw_init(void *handle) int r, vram_width = 0, vram_type = 0, vram_vendor = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - gfxhub_v1_0_init(adev); + adev->gfxhub.funcs->init(adev); adev->mmhub.funcs->init(adev); @@ -1453,7 +1467,7 @@ static int gmc_v9_0_sw_init(void *handle) adev->need_swiotlb = drm_need_swiotlb(44); if (adev->gmc.xgmi.supported) { - r = gfxhub_v1_1_get_xgmi_info(adev); + r = adev->gfxhub.funcs->get_xgmi_info(adev); if (r) return r; } @@ -1569,7 +1583,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - r = gfxhub_v1_0_gart_enable(adev); + r = adev->gfxhub.funcs->gart_enable(adev); if (r) return r; @@ -1636,7 +1650,7 @@ static int gmc_v9_0_hw_init(void *handle) value = true; if (!amdgpu_sriov_vf(adev)) { - gfxhub_v1_0_set_fault_enable_default(adev, value); + adev->gfxhub.funcs->set_fault_enable_default(adev, value); adev->mmhub.funcs->set_fault_enable_default(adev, value); } for (i = 0; i < adev->num_vmhubs; ++i) @@ -1659,7 +1673,7 @@ static int gmc_v9_0_hw_init(void *handle) */ static void gmc_v9_0_gart_disable(struct amdgpu_device *adev) { - gfxhub_v1_0_gart_disable(adev); + adev->gfxhub.funcs->gart_disable(adev); adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } -- GitLab From d3768874e5fe410d80c45e57bff47e8e708c0516 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Mon, 28 Sep 2020 17:59:38 -0400 Subject: [PATCH 1451/1494] drm/amd/display: add pipe reassignment prevention code to dcn3 Add code to gracefuly handle any pipe reassignment occuring on dcn3 hardware. This should only happen when new surfaces are used for an update rather than old ones updated. Fixes: 69fc1f4b976cea ("amd/drm/display: avoid dcn3 on flip opp change for slave pipes") Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Reviewed-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index c223f8af2084f..24fb39a11e5d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1901,21 +1901,28 @@ static bool dcn30_split_stream_for_mpc_or_odm( static struct pipe_ctx *dcn30_find_split_pipe( struct dc *dc, - struct dc_state *context) + struct dc_state *context, + int old_index) { struct pipe_ctx *pipe = NULL; int i; - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL - && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { - if (context->res_ctx.pipe_ctx[i].stream == NULL) { - pipe = &context->res_ctx.pipe_ctx[i]; - pipe->pipe_idx = i; - break; + if (old_index >= 0 && context->res_ctx.pipe_ctx[old_index].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[old_index]; + pipe->pipe_idx = old_index; + } + + if (!pipe) + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (dc->current_state->res_ctx.pipe_ctx[i].top_pipe == NULL + && dc->current_state->res_ctx.pipe_ctx[i].prev_odm_pipe == NULL) { + if (context->res_ctx.pipe_ctx[i].stream == NULL) { + pipe = &context->res_ctx.pipe_ctx[i]; + pipe->pipe_idx = i; + break; + } } } - } /* * May need to fix pipes getting tossed from 1 opp to another on flip @@ -2082,8 +2089,10 @@ static bool dcn30_internal_validate_bw( for (i = 0, pipe_idx = -1; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *hsplit_pipe = NULL; bool odm; + int old_index = -1; if (!pipe->stream || newly_split[i]) continue; @@ -2095,7 +2104,20 @@ static bool dcn30_internal_validate_bw( continue; if (split[i]) { - hsplit_pipe = dcn30_find_split_pipe(dc, context); + if (odm) { + if (split[i] == 4 && old_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + } else { + if (split[i] == 4 && old_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else if (old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + } + hsplit_pipe = dcn30_find_split_pipe(dc, context, old_index); ASSERT(hsplit_pipe); if (!hsplit_pipe) goto validate_fail; @@ -2109,8 +2131,16 @@ static bool dcn30_internal_validate_bw( repopulate_pipes = true; } if (split[i] == 4) { - struct pipe_ctx *pipe_4to1 = dcn30_find_split_pipe(dc, context); + struct pipe_ctx *pipe_4to1; + if (odm && old_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe && + old_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) goto validate_fail; @@ -2120,7 +2150,14 @@ static bool dcn30_internal_validate_bw( goto validate_fail; newly_split[pipe_4to1->pipe_idx] = true; - pipe_4to1 = dcn30_find_split_pipe(dc, context); + if (odm && old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe) + old_index = old_pipe->next_odm_pipe->next_odm_pipe->next_odm_pipe->pipe_idx; + else if (!odm && old_pipe->bottom_pipe->bottom_pipe->bottom_pipe && + old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->plane_state == old_pipe->plane_state) + old_index = old_pipe->bottom_pipe->bottom_pipe->bottom_pipe->pipe_idx; + else + old_index = -1; + pipe_4to1 = dcn30_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) goto validate_fail; -- GitLab From 4a20300bc2b49c281f61f97dc398deefdd87d982 Mon Sep 17 00:00:00 2001 From: Guchun Chen <guchun.chen@amd.com> Date: Tue, 29 Sep 2020 12:41:41 +0800 Subject: [PATCH 1452/1494] drm/amdgpu: drop duplicated ecc check for vega10 (v5) The same ECC check has been executed in amdgpu_ras_init for vega10, prior to gmc_v9_0_late_init. v2: drop all atombios helper callings v3: use bit operation v4: correct inline comment, remove parity check statement v5: squash in build fix Signed-off-by: Guchun Chen <guchun.chen@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c692facdd6b6a..3ebbddb63705c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1207,21 +1207,16 @@ static int gmc_v9_0_late_init(void *handle) r = amdgpu_gmc_allocate_vm_inv_eng(adev); if (r) return r; - /* Check if ecc is available */ + + /* + * Workaround performance drop issue with VBIOS enables partial + * writes, while disables HBM ECC for vega10. + */ if (!amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_VEGA10)) { - r = amdgpu_atomfirmware_mem_ecc_supported(adev); - if (!r) { - DRM_INFO("ECC is not present.\n"); + if (!(adev->ras_features & (1 << AMDGPU_RAS_BLOCK__UMC))) { if (adev->df.funcs->enable_ecc_force_par_wr_rmw) adev->df.funcs->enable_ecc_force_par_wr_rmw(adev, false); - } else - DRM_INFO("ECC is active.\n"); - - r = amdgpu_atomfirmware_sram_ecc_supported(adev); - if (!r) - DRM_INFO("SRAM ECC is not present.\n"); - else - DRM_INFO("SRAM ECC is active.\n"); + } } if (adev->mmhub.funcs && adev->mmhub.funcs->reset_ras_error_count) -- GitLab From 39ad082459373facaa255b0791595d018597a164 Mon Sep 17 00:00:00 2001 From: Jiansong Chen <Jiansong.Chen@amd.com> Date: Wed, 30 Sep 2020 15:30:24 +0800 Subject: [PATCH 1453/1494] drm/amdgpu: disable gfxoff temporarily for navy_flounder gfxoff is temporarily disabled for navy_flounder, since at present the feature caused some tdr when performing display operations. Signed-off-by: Jiansong Chen <Jiansong.Chen@amd.com> Reviewed-by: Tao Zhou <tao.zhou1@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 17fb2efdadd3c..9792ec737029a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3610,6 +3610,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; + case CHIP_NAVY_FLOUNDER: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + break; default: break; } -- GitLab From 4caf017ee93703ba1c4504f3d73b50e6bbd4249e Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 15 Sep 2020 10:14:15 +0100 Subject: [PATCH 1454/1494] drm/i915/gem: Avoid implicit vmap for highmem on x86-32 On 32b, highmem using a finite set of indirect PTE (i.e. vmap) to provide virtual mappings of the high pages. As these are finite, map_new_virtual() must wait for some other kmap() to finish when it runs out. If we map a large number of objects, there is no method for it to tell us to release the mappings, and we deadlock. However, if we make an explicit vmap of the page, that uses a larger vmalloc arena, and also has the ability to tell us to release unwanted mappings. Most importantly, it will fail and propagate an error instead of waiting forever. Fixes: fb8621d3bee8 ("drm/i915: Avoid allocating a vmap arena for a single page") #x86-32 References: e87666b52f00 ("drm/i915/shrinker: Hook up vmap allocation failure notifier") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Cc: <stable@vger.kernel.org> # v4.7+ Link: https://patchwork.freedesktop.org/patch/msgid/20200915091417.4086-1-chris@chris-wilson.co.uk (cherry picked from commit 060bb115c2d664f04db9c7613a104dfaef3fdd98) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 26 +++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index e8a083743e092..49ce5777c5115 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -255,8 +255,30 @@ static void *i915_gem_object_map(struct drm_i915_gem_object *obj, return NULL; /* A single page can always be kmapped */ - if (n_pte == 1 && type == I915_MAP_WB) - return kmap(sg_page(sgt->sgl)); + if (n_pte == 1 && type == I915_MAP_WB) { + struct page *page = sg_page(sgt->sgl); + + /* + * On 32b, highmem using a finite set of indirect PTE (i.e. + * vmap) to provide virtual mappings of the high pages. + * As these are finite, map_new_virtual() must wait for some + * other kmap() to finish when it runs out. If we map a large + * number of objects, there is no method for it to tell us + * to release the mappings, and we deadlock. + * + * However, if we make an explicit vmap of the page, that + * uses a larger vmalloc arena, and also has the ability + * to tell us to release unwanted mappings. Most importantly, + * it will fail and propagate an error instead of waiting + * forever. + * + * So if the page is beyond the 32b boundary, make an explicit + * vmap. On 64b, this check will be optimised away as we can + * directly kmap any page on the system. + */ + if (!PageHighMem(page)) + return kmap(page); + } mem = stack; if (n_pte > ARRAY_SIZE(stack)) { -- GitLab From ba2ebf605d5f32a9be0f7b05d3174bbc501b83fe Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 15 Sep 2020 10:14:16 +0100 Subject: [PATCH 1455/1494] drm/i915/gem: Prevent using pgprot_writecombine() if PAT is not supported Let's not try and use PAT attributes for I915_MAP_WC if the CPU doesn't support PAT. Fixes: 6056e50033d9 ("drm/i915/gem: Support discontiguous lmem object maps") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Cc: <stable@vger.kernel.org> # v5.6+ Link: https://patchwork.freedesktop.org/patch/msgid/20200915091417.4086-2-chris@chris-wilson.co.uk (cherry picked from commit 121ba69ffddc60df11da56f6d5b29bdb45c8eb80) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 49ce5777c5115..d6eeefab3d018 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -254,6 +254,10 @@ static void *i915_gem_object_map(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj) && type != I915_MAP_WC) return NULL; + if (GEM_WARN_ON(type == I915_MAP_WC && + !static_cpu_has(X86_FEATURE_PAT))) + return NULL; + /* A single page can always be kmapped */ if (n_pte == 1 && type == I915_MAP_WB) { struct page *page = sg_page(sgt->sgl); -- GitLab From 922d369b2922b3bb8c72aadddbd7445e6dc1183a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Tue, 15 Sep 2020 10:14:17 +0100 Subject: [PATCH 1456/1494] drm/i915/gt: Clear the buffer pool age before use If we create a new node, it is possible for the slab allocator to return us a recently freed node. If that node was just retired, it will retain the current jiffy as its node->age. There is then a miniscule window, where as that node is retired, it will appear on the free list with an incorrect age and be eligible for reuse by one thread, and then by a second thread as the correct node->age is written. Fixes: 06b73c2d0b65 ("drm/i915/gt: Delay taking the spinlock for grabbing from the buffer pool") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200915091417.4086-3-chris@chris-wilson.co.uk (cherry picked from commit 9bb34ff25c458a2a48fb61409df42f465ede37f8) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 4b7671ac5dca4..104cb30e8c138 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -134,6 +134,7 @@ static void pool_retire(struct i915_active *ref) /* Return this object to the shrinker pool */ i915_gem_object_make_purgeable(node->obj); + GEM_BUG_ON(node->age); spin_lock_irqsave(&pool->lock, flags); list_add_rcu(&node->link, list); WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ @@ -155,6 +156,7 @@ node_create(struct intel_gt_buffer_pool *pool, size_t sz) if (!node) return ERR_PTR(-ENOMEM); + node->age = 0; node->pool = pool; i915_active_init(&node->active, pool_active, pool_retire); -- GitLab From eb2a27086a821a7993c5a3230022c85cc7ccfbda Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Fri, 11 Sep 2020 10:52:43 +0300 Subject: [PATCH 1457/1494] drm/i915: Fix an error code i915_gem_object_copy_blt() This code should use "vma[1]" instead of "vma". The "vma" variable is a valid pointer. Fixes: 6b05030496f7 ("drm/i915: Convert i915_gem_object/client_blt.c to use ww locking as well, v2.") Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200911075243.GG12635@kadam (cherry picked from commit 68ba71e3ae6dd86a23486655e33c5f8c9bd90777) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_object_blt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c index d93eb36160c90..aee7ad3cc3c68 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c @@ -364,7 +364,7 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, vma[1] = i915_vma_instance(dst, vm, NULL); if (IS_ERR(vma[1])) - return PTR_ERR(vma); + return PTR_ERR(vma[1]); i915_gem_ww_ctx_init(&ww, true); intel_engine_pm_get(ce->engine); -- GitLab From 7d5553147613b50149238ac1385c60e5c7cacb34 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Wed, 16 Sep 2020 10:00:58 +0100 Subject: [PATCH 1458/1494] drm/i915: Break up error capture compression loops with cond_resched() As the error capture will compress user buffers as directed to by the user, it can take an arbitrary amount of time and space. Break up the compression loops with a call to cond_resched(), that will allow other processes to schedule (avoiding the soft lockups) and also serve as a warning should we try to make this loop atomic in the future. Testcase: igt/gem_exec_capture/many-* Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: stable@vger.kernel.org Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200916090059.3189-2-chris@chris-wilson.co.uk (cherry picked from commit 293f43c80c0027ff9299036c24218ac705ce584e) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_gpu_error.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3e6cbb0d1150e..a635ec8d0b948 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -311,6 +311,8 @@ static int compress_page(struct i915_vma_compress *c, if (zlib_deflate(zstream, Z_NO_FLUSH) != Z_OK) return -EIO; + + cond_resched(); } while (zstream->avail_in); /* Fallback to uncompressed if we increase size? */ @@ -397,6 +399,7 @@ static int compress_page(struct i915_vma_compress *c, if (!(wc && i915_memcpy_from_wc(ptr, src, PAGE_SIZE))) memcpy(ptr, src, PAGE_SIZE); dst->pages[dst->page_count++] = ptr; + cond_resched(); return 0; } -- GitLab From 159ace7ffe690bcdc7afbd9bab81e05dac2afeac Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Date: Fri, 18 Sep 2020 13:12:08 +0200 Subject: [PATCH 1459/1494] drm/i915: Fix uninitialised variable in intel_context_create_request. In case backoff fails with an error, we return an undefined rq, assign err to rq correctly. Fixes: 8a929c9eb1c2 ("drm/i915: Use ww pinning for intel_context_create_request()") Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200918111208.1392128-1-maarten.lankhorst@linux.intel.com Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> (cherry picked from commit 4316b19dee27cc5cd34a95fdbc0a3a5237507701) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/intel_context.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index d301dda1b2617..92a3f25c40063 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -472,6 +472,7 @@ struct i915_request *intel_context_create_request(struct intel_context *ce) err = i915_gem_ww_ctx_backoff(&ww); if (!err) goto retry; + rq = ERR_PTR(err); } else { rq = ERR_PTR(err); } -- GitLab From cef8ce5528bf61a91d3116f327fc6b78310facfa Mon Sep 17 00:00:00 2001 From: Matthew Auld <matthew.auld@intel.com> Date: Mon, 21 Sep 2020 17:08:44 +0100 Subject: [PATCH 1460/1494] drm/i915: check i915_vm_alloc_pt_stash for errors If we are really unlucky and encounter an error during i915_vm_alloc_pt_stash, we end up passing an empty pt/pd stash all the way down into the low-level ppgtt alloc code, leading to explosions, since it expects at least the required number of pt/pd for the va range. [ 211.981418] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 211.981421] #PF: supervisor read access in kernel mode [ 211.981422] #PF: error_code(0x0000) - not-present page [ 211.981424] PGD 80000008439cb067 P4D 80000008439cb067 PUD 84a37f067 PMD 0 [ 211.981427] Oops: 0000 [#1] SMP PTI [ 211.981428] CPU: 1 PID: 1301 Comm: i915_selftest Tainted: G U I 5.9.0-rc5+ #3 [ 211.981430] Hardware name: /NUC6i7KYB, BIOS KYSKLi70.86A.0050.2017.0831.1924 08/31/2017 [ 211.981521] RIP: 0010:__gen8_ppgtt_alloc+0x1ed/0x3c0 [i915] [ 211.981523] Code: c1 48 c7 c7 5d 5d fe c0 65 ff 0d ee 1d 03 3f e8 d9 91 1f e2 8b 55 c4 31 c0 48 8b 75 b8 85 d2 0f 95 c0 48 8b 1c c6 48 89 45 98 <48> 8b 03 48 8b 90 58 02 00 00 48 85 d2 0f 84 07 ea 15 00 48 81 fa [ 211.981526] RSP: 0018:ffffba2cc0eb3970 EFLAGS: 00010202 [ 211.981527] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 0000000000000004 [ 211.981529] RDX: 0000000000000002 RSI: ffff9be998bdb8c0 RDI: ffff9be99c844300 [ 211.981530] RBP: ffffba2cc0eb39d8 R08: 0000000000000640 R09: ffff9be97cdfd000 [ 211.981531] R10: ffff9be97cdfd614 R11: 0000000000000000 R12: 0000000000000000 [ 211.981532] R13: ffff9be98607ba20 R14: ffff9be995a0b400 R15: ffffba2cc0eb39e8 [ 211.981534] FS: 00007f0f10b31000(0000) GS:ffff9be99fc40000(0000) knlGS:0000000000000000 [ 211.981536] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 211.981538] CR2: 0000000000000000 CR3: 000000084d74e006 CR4: 00000000003706e0 [ 211.981539] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 211.981541] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 211.981542] Call Trace: [ 211.981609] gen8_ppgtt_alloc+0x79/0x90 [i915] [ 211.981678] ppgtt_bind_vma+0x36/0x80 [i915] [ 211.981756] __vma_bind+0x39/0x40 [i915] [ 211.981818] fence_work+0x21/0x98 [i915] [ 211.981879] fence_notify+0x8d/0x128 [i915] [ 211.981939] __i915_sw_fence_complete+0x62/0x240 [i915] [ 211.982018] i915_vma_pin_ww+0x1ee/0x9c0 [i915] Fixes: cd0452aa2a0d ("drm/i915: Preallocate stashes for vma page-directories") Signed-off-by: Matthew Auld <matthew.auld@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20200921160844.73186-1-matthew.auld@intel.com (cherry picked from commit 1604cb2aa7fafd83e11f9257f765a5f5dd7c19d3) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_vma.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 495d28f6d1601..ffb5287e055a9 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -892,9 +892,11 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, /* Allocate enough page directories to used PTE */ if (vma->vm->allocate_va_range) { - i915_vm_alloc_pt_stash(vma->vm, - &work->stash, - vma->size); + err = i915_vm_alloc_pt_stash(vma->vm, + &work->stash, + vma->size); + if (err) + goto err_fence; err = i915_vm_pin_pt_stash(vma->vm, &work->stash); -- GitLab From 4fe9af8e881d946bf60790eeb37a7c4f96e28382 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Thu, 23 Jul 2020 18:21:19 +0100 Subject: [PATCH 1461/1494] drm/i915/gem: Serialise debugfs i915_gem_objects with ctx->mutex Since the debugfs may peek into the GEM contexts as the corresponding client/fd is being closed, we may try and follow a dangling pointer. However, the context closure itself is serialised with the ctx->mutex, so if we hold that mutex as we inspect the state coupled in the context, we know the pointers within the context are stable and will remain valid as we inspect their tables. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: CQ Tang <cq.tang@intel.com> Cc: Daniel Vetter <daniel.vetter@intel.com> Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200723172119.17649-3-chris@chris-wilson.co.uk (cherry picked from commit 102f5aa491f262c818e607fc4fee08a724a76c69) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_debugfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7842199621937..ea469168cd443 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -326,6 +326,7 @@ static void print_context_stats(struct seq_file *m, } i915_gem_context_unlock_engines(ctx); + mutex_lock(&ctx->mutex); if (!IS_ERR_OR_NULL(ctx->file_priv)) { struct file_stats stats = { .vm = rcu_access_pointer(ctx->vm), @@ -346,6 +347,7 @@ static void print_context_stats(struct seq_file *m, print_file_stats(m, name, stats); } + mutex_unlock(&ctx->mutex); spin_lock(&i915->gem.contexts.lock); list_safe_reset_next(ctx, cn, link); -- GitLab From 5701a66edb6b3e09a7bdba3d0d64020a70562f87 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 25 Sep 2020 11:11:06 +0100 Subject: [PATCH 1462/1494] drm/i915: Redo "Remove i915_request.lock requirement for execution callbacks" The reordering and rebasing of commit 2e4c6c1a9db5 ("drm/i915: Remove i915_request.lock requirement for execution callbacks") caused it to revert an earlier correction. Let us restore commit 99f0a640d464 ("drm/i915: Remove requirement for holding i915_request.lock for breadcrumbs") Fixes: 2e4c6c1a9db5 ("drm/i915: Remove i915_request.lock requirement for execution callbacks") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200925101107.27869-1-chris@chris-wilson.co.uk (cherry picked from commit 35faeb7de9ef83da510a048f2016061f1e31d5fc) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/i915_request.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 11e272422fb75..436ce368ddaaa 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -593,16 +593,8 @@ bool __i915_request_submit(struct i915_request *request) __notify_execute_cb_irq(request); /* We may be recursing from the signal callback of another i915 fence */ - if (!i915_request_signaled(request)) { - spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); - - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, - &request->fence.flags) && - !i915_request_enable_breadcrumb(request)) - intel_engine_signal_breadcrumbs(engine); - - spin_unlock(&request->lock); - } + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) + i915_request_enable_breadcrumb(request); return result; } -- GitLab From 3cfea8c97c93321578823c745e2ca8c8f03993ff Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Fri, 25 Sep 2020 11:11:07 +0100 Subject: [PATCH 1463/1494] drm/i915/gem: Hold request reference for canceling an active context We have to be very careful while walking the timeline->requests list under the RCU guard, as the requests (and so rq->link) use SLAB_TYPESAFE_BY_RCU and so the requests may be reallocated within an rcu grace period. As the requests are reallocated, they are removed from one list and placed on another, and if we are iterating over that request at that moment, the list iteration jumps from one list to the next and promptly gets confused. Verify we hold the request reference to ensure that the request is not added to a new list behind our backs. <4> [582.745252] general protection fault, probably for non-canonical address 0xcccccccccccccd5c: 0000 [#1] PREEMPT SMP PTI <4> [582.745297] CPU: 0 PID: 1475 Comm: gem_ctx_persist Not tainted 5.9.0-rc1-CI-CI_DRM_8908+ #1 <4> [582.745304] Hardware name: Intel Corporation NUC7CJYH/NUC7JYB, BIOS JYGLKCPX.86A.0027.2018.0125.1347 01/25/2018 <4> [582.745317] RIP: 0010:__lock_acquire+0x2c3/0x1f40 <4> [582.745323] Code: 00 65 8b 05 c7 8a ef 7e 85 c0 0f 85 b4 07 00 00 44 8b 9d c4 08 00 00 45 85 db 0f 84 0f 01 00 00 ba 05 00 00 00 e9 c8 06 00 00 <48> 81 3f c0 89 c7 82 b8 00 00 00 00 41 0f 45 c0 83 fe 01 41 89 c3 <4> [582.745334] RSP: 0018:ffffc9000461bc40 EFLAGS: 00010002 <4> [582.745340] RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000 <4> [582.745345] RDX: 0000000000000000 RSI: 0000000000000000 RDI: cccccccccccccd5c <4> [582.745350] RBP: ffff8881ec4a2880 R08: 0000000000000001 R09: 0000000000000001 <4> [582.745356] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000000 <4> [582.745361] R13: 0000000000000000 R14: 0000000000000000 R15: cccccccccccccd5c <4> [582.745367] FS: 00007fb44da78e40(0000) GS:ffff888278000000(0000) knlGS:0000000000000000 <4> [582.745373] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4> [582.745378] CR2: 00007fb44daad040 CR3: 0000000268428000 CR4: 0000000000350ef0 <4> [582.745383] Call Trace: <4> [582.745390] ? __lock_acquire+0x913/0x1f40 <4> [582.745397] lock_acquire+0xb5/0x3c0 <4> [582.745526] ? kill_engines+0x19a/0x4b0 [i915] <4> [582.745533] ? find_held_lock+0x2d/0x90 <4> [582.745541] _raw_spin_lock_irq+0x30/0x40 <4> [582.745635] ? kill_engines+0x19a/0x4b0 [i915] <4> [582.745727] kill_engines+0x19a/0x4b0 [i915] <4> [582.745820] context_close+0x195/0x410 [i915] <4> [582.745912] i915_gem_context_close+0x5b/0x160 [i915] <4> [582.745994] i915_driver_postclose+0x14/0x40 [i915] <4> [582.746003] drm_file_free.part.13+0x240/0x290 <4> [582.746009] drm_release_noglobal+0x16/0x50 <4> [582.746016] __fput+0xa5/0x250 <4> [582.746021] task_work_run+0x6e/0xb0 <4> [582.746028] exit_to_user_mode_prepare+0x178/0x180 <4> [582.746034] syscall_exit_to_user_mode+0x36/0x220 <4> [582.746040] entry_SYSCALL_64_after_hwframe+0x44/0xa9 <4> [582.746045] RIP: 0033:0x7fb44d1dc421 <4> [582.746050] Code: f7 d8 64 89 02 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 8b 05 ea cf 20 00 85 c0 75 16 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 3f f3 c3 0f 1f 44 00 00 53 89 fb 48 83 ec 10 <4> [582.746062] RSP: 002b:00007ffed2e83818 EFLAGS: 00000246 ORIG_RAX: 0000000000000003 <4> [582.746069] RAX: 0000000000000000 RBX: 0000556410bfe840 RCX: 00007fb44d1dc421 <4> [582.746075] RDX: 000000000000000a RSI: 00000000c0406469 RDI: 0000000000000008 <4> [582.746080] RBP: 0000000000000008 R08: 00007fb44d1c51cc R09: 00007fb44d1c5240 <4> [582.746086] R10: 0000000000000001 R11: 0000000000000246 R12: 00000000fffffffb <4> [582.746091] R13: 0000000000000006 R14: 0000000000000000 R15: 000000000000000a <4> [582.746099] Modules linked in: vgem mei_hdcp snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio btusb btrtl btbcm btintel x86_pkg_temp_thermal coretemp crct10dif_pclmul crc32_pclmul bluetooth ghash_clmulni_intel ecdh_generic ecc i915 r8169 realtek mei_me mei snd_hda_intel i2c_hid snd_intel_dspcfg snd_hda_codec snd_hwdep snd_hda_core snd_pcm pinctrl_geminilake pinctrl_intel prime_numbers [last unloaded: test_drm_mm] Fixes: 736e785f9b28 ("drm/i915/gem: Reduce context termination list iteration guard to RCU") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200925101107.27869-2-chris@chris-wilson.co.uk (cherry picked from commit badef44deff1fae8d21c5c1cfc4dde95fb5bf993) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 25 ++++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index cf5ecbde9e069..a548626fa8bc7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -460,8 +460,8 @@ __active_engine(struct i915_request *rq, struct intel_engine_cs **active) spin_lock(&locked->active.lock); } - if (!i915_request_completed(rq)) { - if (i915_request_is_active(rq) && rq->fence.error != -EIO) + if (i915_request_is_active(rq)) { + if (!i915_request_completed(rq)) *active = locked; ret = true; } @@ -479,13 +479,26 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) if (!ce->timeline) return NULL; + /* + * rq->link is only SLAB_TYPESAFE_BY_RCU, we need to hold a reference + * to the request to prevent it being transferred to a new timeline + * (and onto a new timeline->requests list). + */ rcu_read_lock(); - list_for_each_entry_rcu(rq, &ce->timeline->requests, link) { - if (i915_request_is_active(rq) && i915_request_completed(rq)) - continue; + list_for_each_entry_reverse(rq, &ce->timeline->requests, link) { + bool found; + + /* timeline is already completed upto this point? */ + if (!i915_request_get_rcu(rq)) + break; /* Check with the backend if the request is inflight */ - if (__active_engine(rq, &engine)) + found = true; + if (likely(rcu_access_pointer(rq->timeline) == ce->timeline)) + found = __active_engine(rq, &engine); + + i915_request_put(rq); + if (found) break; } rcu_read_unlock(); -- GitLab From 7d442ea7c504adcc9798b07cd8f6a0d235fca2da Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon, 28 Sep 2020 23:15:08 +0100 Subject: [PATCH 1464/1494] drm/i915: Cancel outstanding work after disabling heartbeats on an engine We only allow persistent requests to remain on the GPU past the closure of their containing context (and process) so long as they are continuously checked for hangs or allow other requests to preempt them, as we need to ensure forward progress of the system. If we allow persistent contexts to remain on the system after the the hangcheck mechanism is disabled, the system may grind to a halt. On disabling the mechanism, we sent a pulse along the engine to remove all executing contexts from the engine which would check for hung contexts -- but we did not prevent those contexts from being resubmitted if they survived the final hangcheck. Fixes: 9a40bddd47ca ("drm/i915/gt: Expose heartbeat interval via sysfs") Testcase: igt/gem_ctx_persistence/heartbeat-stop Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: <stable@vger.kernel.org> # v5.7+ Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Acked-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200928221510.26044-1-chris@chris-wilson.co.uk (cherry picked from commit 7a991cd3e3da9a56d5616b62d425db000a3242f2) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gt/intel_engine.h | 9 +++++++++ drivers/gpu/drm/i915/i915_request.c | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 08e2c000dcc3b..7c3a1012e7020 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -337,4 +337,13 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine) return intel_engine_has_preemption(engine); } +static inline bool +intel_engine_has_heartbeat(const struct intel_engine_cs *engine) +{ + if (!IS_ACTIVE(CONFIG_DRM_I915_HEARTBEAT_INTERVAL)) + return false; + + return READ_ONCE(engine->props.heartbeat_interval_ms); +} + #endif /* _INTEL_RINGBUFFER_H_ */ diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 436ce368ddaaa..0e813819b041b 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -542,8 +542,13 @@ bool __i915_request_submit(struct i915_request *request) if (i915_request_completed(request)) goto xfer; + if (unlikely(intel_context_is_closed(request->context) && + !intel_engine_has_heartbeat(engine))) + intel_context_set_banned(request->context); + if (unlikely(intel_context_is_banned(request->context))) i915_request_set_error_once(request, -EIO); + if (unlikely(fatal_error(request->fence.error))) __i915_request_skip(request); -- GitLab From ca65fc0d8e01dca8fc82f0ccf433725469256c71 Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon, 28 Sep 2020 23:15:09 +0100 Subject: [PATCH 1465/1494] drm/i915/gt: Always send a pulse down the engine after disabling heartbeat Currently, we check we can send a pulse prior to disabling the heartbeat to verify that we can change the heartbeat, but since we may re-evaluate execution upon changing the heartbeat interval we need another pulse afterwards to refresh execution. v2: Tvrtko asked if we could reduce the double pulse to a single, which opened up a discussion of how we should handle the pulse-error after attempting to change the property, and the desire to serialise adjustment of the property with its validating pulse, and unwind upon failure. Fixes: 9a40bddd47ca ("drm/i915/gt: Expose heartbeat interval via sysfs") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Cc: <stable@vger.kernel.org> # v5.7+ Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Acked-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200928221510.26044-2-chris@chris-wilson.co.uk (cherry picked from commit 3dd66a94de59d7792e7917eb3075342e70f06f44) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- .../gpu/drm/i915/gt/intel_engine_heartbeat.c | 106 +++++++++++------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c index 8ffdf676c0a09..5067d0524d4b5 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c @@ -177,36 +177,82 @@ void intel_engine_init_heartbeat(struct intel_engine_cs *engine) INIT_DELAYED_WORK(&engine->heartbeat.work, heartbeat); } +static int __intel_engine_pulse(struct intel_engine_cs *engine) +{ + struct i915_sched_attr attr = { .priority = I915_PRIORITY_BARRIER }; + struct intel_context *ce = engine->kernel_context; + struct i915_request *rq; + + lockdep_assert_held(&ce->timeline->mutex); + GEM_BUG_ON(!intel_engine_has_preemption(engine)); + GEM_BUG_ON(!intel_engine_pm_is_awake(engine)); + + intel_context_enter(ce); + rq = __i915_request_create(ce, GFP_NOWAIT | __GFP_NOWARN); + intel_context_exit(ce); + if (IS_ERR(rq)) + return PTR_ERR(rq); + + __set_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags); + idle_pulse(engine, rq); + + __i915_request_commit(rq); + __i915_request_queue(rq, &attr); + GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER); + + return 0; +} + +static unsigned long set_heartbeat(struct intel_engine_cs *engine, + unsigned long delay) +{ + unsigned long old; + + old = xchg(&engine->props.heartbeat_interval_ms, delay); + if (delay) + intel_engine_unpark_heartbeat(engine); + else + intel_engine_park_heartbeat(engine); + + return old; +} + int intel_engine_set_heartbeat(struct intel_engine_cs *engine, unsigned long delay) { - int err; + struct intel_context *ce = engine->kernel_context; + int err = 0; - /* Send one last pulse before to cleanup persistent hogs */ - if (!delay && IS_ACTIVE(CONFIG_DRM_I915_PREEMPT_TIMEOUT)) { - err = intel_engine_pulse(engine); - if (err) - return err; - } + if (!delay && !intel_engine_has_preempt_reset(engine)) + return -ENODEV; + + intel_engine_pm_get(engine); + + err = mutex_lock_interruptible(&ce->timeline->mutex); + if (err) + goto out_rpm; - WRITE_ONCE(engine->props.heartbeat_interval_ms, delay); + if (delay != engine->props.heartbeat_interval_ms) { + unsigned long saved = set_heartbeat(engine, delay); - if (intel_engine_pm_get_if_awake(engine)) { - if (delay) - intel_engine_unpark_heartbeat(engine); - else - intel_engine_park_heartbeat(engine); - intel_engine_pm_put(engine); + /* recheck current execution */ + if (intel_engine_has_preemption(engine)) { + err = __intel_engine_pulse(engine); + if (err) + set_heartbeat(engine, saved); + } } - return 0; + mutex_unlock(&ce->timeline->mutex); + +out_rpm: + intel_engine_pm_put(engine); + return err; } int intel_engine_pulse(struct intel_engine_cs *engine) { - struct i915_sched_attr attr = { .priority = I915_PRIORITY_BARRIER }; struct intel_context *ce = engine->kernel_context; - struct i915_request *rq; int err; if (!intel_engine_has_preemption(engine)) @@ -215,30 +261,12 @@ int intel_engine_pulse(struct intel_engine_cs *engine) if (!intel_engine_pm_get_if_awake(engine)) return 0; - if (mutex_lock_interruptible(&ce->timeline->mutex)) { - err = -EINTR; - goto out_rpm; - } - - intel_context_enter(ce); - rq = __i915_request_create(ce, GFP_NOWAIT | __GFP_NOWARN); - intel_context_exit(ce); - if (IS_ERR(rq)) { - err = PTR_ERR(rq); - goto out_unlock; + err = -EINTR; + if (!mutex_lock_interruptible(&ce->timeline->mutex)) { + err = __intel_engine_pulse(engine); + mutex_unlock(&ce->timeline->mutex); } - __set_bit(I915_FENCE_FLAG_SENTINEL, &rq->fence.flags); - idle_pulse(engine, rq); - - __i915_request_commit(rq); - __i915_request_queue(rq, &attr); - GEM_BUG_ON(rq->sched.attr.priority < I915_PRIORITY_BARRIER); - err = 0; - -out_unlock: - mutex_unlock(&ce->timeline->mutex); -out_rpm: intel_engine_pm_put(engine); return err; } -- GitLab From 651dabe27f9638f569f6a794f9d3cc1889cd315e Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon, 28 Sep 2020 23:15:10 +0100 Subject: [PATCH 1466/1494] drm/i915/gem: Always test execution status on closing the context Verify that if a context is active at the time it is closed, that it is either persistent and preemptible (with hangcheck running) or it shall be removed from execution. Fixes: 9a40bddd47ca ("drm/i915/gt: Expose heartbeat interval via sysfs") Testcase: igt/gem_ctx_persistence/heartbeat-close Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: <stable@vger.kernel.org> # v5.7+ Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Acked-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200928221510.26044-3-chris@chris-wilson.co.uk (cherry picked from commit d3bb2f9b5ee66d5e000293edd6b6575e59d11db9) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 48 +++++---------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index a548626fa8bc7..4fd38101bb565 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -390,24 +390,6 @@ __context_engines_static(const struct i915_gem_context *ctx) return rcu_dereference_protected(ctx->engines, true); } -static bool __reset_engine(struct intel_engine_cs *engine) -{ - struct intel_gt *gt = engine->gt; - bool success = false; - - if (!intel_has_reset_engine(gt)) - return false; - - if (!test_and_set_bit(I915_RESET_ENGINE + engine->id, - >->reset.flags)) { - success = intel_engine_reset(engine, NULL) == 0; - clear_and_wake_up_bit(I915_RESET_ENGINE + engine->id, - >->reset.flags); - } - - return success; -} - static void __reset_context(struct i915_gem_context *ctx, struct intel_engine_cs *engine) { @@ -431,12 +413,7 @@ static bool __cancel_engine(struct intel_engine_cs *engine) * kill the banned context, we fallback to doing a local reset * instead. */ - if (IS_ACTIVE(CONFIG_DRM_I915_PREEMPT_TIMEOUT) && - !intel_engine_pulse(engine)) - return true; - - /* If we are unable to send a pulse, try resetting this engine. */ - return __reset_engine(engine); + return intel_engine_pulse(engine) == 0; } static bool @@ -506,7 +483,7 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) return engine; } -static void kill_engines(struct i915_gem_engines *engines) +static void kill_engines(struct i915_gem_engines *engines, bool ban) { struct i915_gem_engines_iter it; struct intel_context *ce; @@ -521,7 +498,7 @@ static void kill_engines(struct i915_gem_engines *engines) for_each_gem_engine(ce, engines, it) { struct intel_engine_cs *engine; - if (intel_context_set_banned(ce)) + if (ban && intel_context_set_banned(ce)) continue; /* @@ -534,7 +511,7 @@ static void kill_engines(struct i915_gem_engines *engines) engine = active_engine(ce); /* First attempt to gracefully cancel the context */ - if (engine && !__cancel_engine(engine)) + if (engine && !__cancel_engine(engine) && ban) /* * If we are unable to send a preemptive pulse to bump * the context from the GPU, we have to resort to a full @@ -544,8 +521,10 @@ static void kill_engines(struct i915_gem_engines *engines) } } -static void kill_stale_engines(struct i915_gem_context *ctx) +static void kill_context(struct i915_gem_context *ctx) { + bool ban = (!i915_gem_context_is_persistent(ctx) || + !ctx->i915->params.enable_hangcheck); struct i915_gem_engines *pos, *next; spin_lock_irq(&ctx->stale.lock); @@ -558,7 +537,7 @@ static void kill_stale_engines(struct i915_gem_context *ctx) spin_unlock_irq(&ctx->stale.lock); - kill_engines(pos); + kill_engines(pos, ban); spin_lock_irq(&ctx->stale.lock); GEM_BUG_ON(i915_sw_fence_signaled(&pos->fence)); @@ -570,11 +549,6 @@ static void kill_stale_engines(struct i915_gem_context *ctx) spin_unlock_irq(&ctx->stale.lock); } -static void kill_context(struct i915_gem_context *ctx) -{ - kill_stale_engines(ctx); -} - static void engines_idle_release(struct i915_gem_context *ctx, struct i915_gem_engines *engines) { @@ -609,7 +583,7 @@ static void engines_idle_release(struct i915_gem_context *ctx, kill: if (list_empty(&engines->link)) /* raced, already closed */ - kill_engines(engines); + kill_engines(engines, true); i915_sw_fence_commit(&engines->fence); } @@ -667,9 +641,7 @@ static void context_close(struct i915_gem_context *ctx) * case we opt to forcibly kill off all remaining requests on * context close. */ - if (!i915_gem_context_is_persistent(ctx) || - !ctx->i915->params.enable_hangcheck) - kill_context(ctx); + kill_context(ctx); i915_gem_context_put(ctx); } -- GitLab From c60b93cd4862d108214a14e655358ea714d7a12a Mon Sep 17 00:00:00 2001 From: Chris Wilson <chris@chris-wilson.co.uk> Date: Mon, 28 Sep 2020 22:59:42 +0100 Subject: [PATCH 1467/1494] drm/i915: Avoid mixing integer types during batch copies Be consistent and use unsigned long throughout the chunk copies to avoid the inherent clumsiness of mixing integer types of different widths and signs. Failing to take acount of a wider unsigned type when using min_t can lead to treating it as a negative, only for it flip back to a large unsigned value after passing a boundary check. Fixes: ed13033f0287 ("drm/i915/cmdparser: Only cache the dst vmap") Testcase: igt/gen9_exec_parse/bb-large Reported-by: "Candelaria, Jared" <jared.candelaria@intel.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: "Candelaria, Jared" <jared.candelaria@intel.com> Cc: "Bloomfield, Jon" <jon.bloomfield@intel.com> Cc: <stable@vger.kernel.org> # v4.9+ Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200928215942.31917-1-chris@chris-wilson.co.uk (cherry picked from commit b7eeb2b4132ccf1a7d38f434cde7043913d1ed3c) Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 7 +++++-- drivers/gpu/drm/i915/i915_cmd_parser.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 5509946f1a1da..4b09bcd70cf4e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2267,8 +2267,8 @@ struct eb_parse_work { struct i915_vma *batch; struct i915_vma *shadow; struct i915_vma *trampoline; - unsigned int batch_offset; - unsigned int batch_length; + unsigned long batch_offset; + unsigned long batch_length; }; static int __eb_parse(struct dma_fence_work *work) @@ -2338,6 +2338,9 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb, struct eb_parse_work *pw; int err; + GEM_BUG_ON(overflows_type(eb->batch_start_offset, pw->batch_offset)); + GEM_BUG_ON(overflows_type(eb->batch_len, pw->batch_length)); + pw = kzalloc(sizeof(*pw), GFP_KERNEL); if (!pw) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 5ac4a999f05a6..e88970256e8ef 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1136,7 +1136,7 @@ find_reg(const struct intel_engine_cs *engine, u32 addr) /* Returns a vmap'd pointer to dst_obj, which the caller must unmap */ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, struct drm_i915_gem_object *src_obj, - u32 offset, u32 length) + unsigned long offset, unsigned long length) { bool needs_clflush; void *dst, *src; @@ -1166,8 +1166,8 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, } } if (IS_ERR(src)) { + unsigned long x, n; void *ptr; - int x, n; /* * We can avoid clflushing partial cachelines before the write @@ -1184,7 +1184,7 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, ptr = dst; x = offset_in_page(offset); for (n = offset >> PAGE_SHIFT; length; n++) { - int len = min_t(int, length, PAGE_SIZE - x); + int len = min(length, PAGE_SIZE - x); src = kmap_atomic(i915_gem_object_get_page(src_obj, n)); if (needs_clflush) @@ -1414,8 +1414,8 @@ static bool shadow_needs_clflush(struct drm_i915_gem_object *obj) */ int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct i915_vma *batch, - u32 batch_offset, - u32 batch_length, + unsigned long batch_offset, + unsigned long batch_length, struct i915_vma *shadow, bool trampoline) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 72a9449b674ed..eef9a821c49cd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1949,8 +1949,8 @@ void intel_engine_init_cmd_parser(struct intel_engine_cs *engine); void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine); int intel_engine_cmd_parser(struct intel_engine_cs *engine, struct i915_vma *batch, - u32 batch_offset, - u32 batch_length, + unsigned long batch_offset, + unsigned long batch_length, struct i915_vma *shadow, bool trampoline); #define I915_CMD_PARSER_TRAMPOLINE_SIZE 8 -- GitLab From 43a4bc828c5b156f08024fd0a966c5c2a3f09af1 Mon Sep 17 00:00:00 2001 From: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Date: Tue, 29 Sep 2020 12:14:08 -0500 Subject: [PATCH 1468/1494] drm/amd/amdgpu: Define and implement a function that collects number of waves that are in flight. [Why] Allow user to know how many compute units (CU) are in use at any given moment. [How] Read registers of SQ that give number of waves that are in flight of various queues. Use this information to determine number of CU's in use. Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Reviewed-By: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 175 ++++++++++++++++++ .../gpu/drm/amd/include/kgd_kfd_interface.h | 12 ++ 2 files changed, 187 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index b824582463933..e0d5110701bd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -36,6 +36,7 @@ #include "v9_structs.h" #include "soc15.h" #include "soc15d.h" +#include "gfx_v9_0.h" enum hqd_dequeue_request_type { NO_ACTION = 0, @@ -703,6 +704,179 @@ void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, adev->gfxhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); } +static void lock_spi_csq_mutexes(struct amdgpu_device *adev) +{ + mutex_lock(&adev->srbm_mutex); + mutex_lock(&adev->grbm_idx_mutex); + +} + +static void unlock_spi_csq_mutexes(struct amdgpu_device *adev) +{ + mutex_unlock(&adev->grbm_idx_mutex); + mutex_unlock(&adev->srbm_mutex); +} + +/** + * @get_wave_count: Read device registers to get number of waves in flight for + * a particular queue. The method also returns the VMID associated with the + * queue. + * + * @adev: Handle of device whose registers are to be read + * @queue_idx: Index of queue in the queue-map bit-field + * @wave_cnt: Output parameter updated with number of waves in flight + * @vmid: Output parameter updated with VMID of queue whose wave count + * is being collected + */ +static void get_wave_count(struct amdgpu_device *adev, int queue_idx, + int *wave_cnt, int *vmid) +{ + int pipe_idx; + int queue_slot; + unsigned int reg_val; + + /* + * Program GRBM with appropriate MEID, PIPEID, QUEUEID and VMID + * parameters to read out waves in flight. Get VMID if there are + * non-zero waves in flight. + */ + *vmid = 0xFF; + *wave_cnt = 0; + pipe_idx = queue_idx / adev->gfx.mec.num_queue_per_pipe; + queue_slot = queue_idx % adev->gfx.mec.num_queue_per_pipe; + soc15_grbm_select(adev, 1, pipe_idx, queue_slot, 0); + reg_val = RREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_CSQ_WF_ACTIVE_COUNT_0) + + queue_slot); + *wave_cnt = reg_val & SPI_CSQ_WF_ACTIVE_COUNT_0__COUNT_MASK; + if (*wave_cnt != 0) + *vmid = (RREG32_SOC15(GC, 0, mmCP_HQD_VMID) & + CP_HQD_VMID__VMID_MASK) >> CP_HQD_VMID__VMID__SHIFT; +} + +/** + * @kgd_gfx_v9_get_cu_occupancy: Reads relevant registers associated with each + * shader engine and aggregates the number of waves that are in flight for the + * process whose pasid is provided as a parameter. The process could have ZERO + * or more queues running and submitting waves to compute units. + * + * @kgd: Handle of device from which to get number of waves in flight + * @pasid: Identifies the process for which this query call is invoked + * @wave_cnt: Output parameter updated with number of waves in flight that + * belong to process with given pasid + * @max_waves_per_cu: Output parameter updated with maximum number of waves + * possible per Compute Unit + * + * @note: It's possible that the device has too many queues (oversubscription) + * in which case a VMID could be remapped to a different PASID. This could lead + * to an iaccurate wave count. Following is a high-level sequence: + * Time T1: vmid = getVmid(); vmid is associated with Pasid P1 + * Time T2: passId = getPasId(vmid); vmid is associated with Pasid P2 + * In the sequence above wave count obtained from time T1 will be incorrectly + * lost or added to total wave count. + * + * The registers that provide the waves in flight are: + * + * SPI_CSQ_WF_ACTIVE_STATUS - bit-map of queues per pipe. The bit is ON if a + * queue is slotted, OFF if there is no queue. A process could have ZERO or + * more queues slotted and submitting waves to be run on compute units. Even + * when there is a queue it is possible there could be zero wave fronts, this + * can happen when queue is waiting on top-of-pipe events - e.g. waitRegMem + * command + * + * For each bit that is ON from above: + * + * Read (SPI_CSQ_WF_ACTIVE_COUNT_0 + queue_idx) register. It provides the + * number of waves that are in flight for the queue at specified index. The + * index ranges from 0 to 7. + * + * If non-zero waves are in flight, read CP_HQD_VMID register to obtain VMID + * of the wave(s). + * + * Determine if VMID from above step maps to pasid provided as parameter. If + * it matches agrregate the wave count. That the VMID will not match pasid is + * a normal condition i.e. a device is expected to support multiple queues + * from multiple proceses. + * + * Reading registers referenced above involves programming GRBM appropriately + */ +static void kgd_gfx_v9_get_cu_occupancy(struct kgd_dev *kgd, int pasid, + int *pasid_wave_cnt, int *max_waves_per_cu) +{ + int qidx; + int vmid; + int se_idx; + int sh_idx; + int se_cnt; + int sh_cnt; + int wave_cnt; + int queue_map; + int pasid_tmp; + int max_queue_cnt; + int vmid_wave_cnt = 0; + struct amdgpu_device *adev; + DECLARE_BITMAP(cp_queue_bitmap, KGD_MAX_QUEUES); + + adev = get_amdgpu_device(kgd); + lock_spi_csq_mutexes(adev); + soc15_grbm_select(adev, 1, 0, 0, 0); + + /* + * Iterate through the shader engines and arrays of the device + * to get number of waves in flight + */ + bitmap_complement(cp_queue_bitmap, adev->gfx.mec.queue_bitmap, + KGD_MAX_QUEUES); + max_queue_cnt = adev->gfx.mec.num_pipe_per_mec * + adev->gfx.mec.num_queue_per_pipe; + sh_cnt = adev->gfx.config.max_sh_per_se; + se_cnt = adev->gfx.config.max_shader_engines; + for (se_idx = 0; se_idx < se_cnt; se_idx++) { + for (sh_idx = 0; sh_idx < sh_cnt; sh_idx++) { + + gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff); + queue_map = RREG32(SOC15_REG_OFFSET(GC, 0, + mmSPI_CSQ_WF_ACTIVE_STATUS)); + + /* + * Assumption: queue map encodes following schema: four + * pipes per each micro-engine, with each pipe mapping + * eight queues. This schema is true for GFX9 devices + * and must be verified for newer device families + */ + for (qidx = 0; qidx < max_queue_cnt; qidx++) { + + /* Skip qeueus that are not associated with + * compute functions + */ + if (!test_bit(qidx, cp_queue_bitmap)) + continue; + + if (!(queue_map & (1 << qidx))) + continue; + + /* Get number of waves in flight and aggregate them */ + get_wave_count(adev, qidx, &wave_cnt, &vmid); + if (wave_cnt != 0) { + pasid_tmp = + RREG32(SOC15_REG_OFFSET(OSSSYS, 0, + mmIH_VMID_0_LUT) + vmid); + if (pasid_tmp == pasid) + vmid_wave_cnt += wave_cnt; + } + } + } + } + + gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + soc15_grbm_select(adev, 0, 0, 0, 0); + unlock_spi_csq_mutexes(adev); + + /* Update the output parameters and return */ + *pasid_wave_cnt = vmid_wave_cnt; + *max_waves_per_cu = adev->gfx.cu_info.simd_per_cu * + adev->gfx.cu_info.max_waves_per_simd; +} + const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, @@ -723,4 +897,5 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, + .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy, }; diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index fc592f60e6a04..e37b4b9f626df 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -212,6 +212,15 @@ struct tile_config { * IH ring entry. This function allows the KFD ISR to get the VMID * from the fault status register as early as possible. * + * @get_cu_occupancy: Function pointer that returns to caller the number + * of wave fronts that are in flight for all of the queues of a process + * as identified by its pasid. It is important to note that the value + * returned by this function is a snapshot of current moment and cannot + * guarantee any minimum for the number of waves in-flight. This function + * is defined for devices that belong to GFX9 and later GFX families. Care + * must be taken in calling this function as it is not defined for devices + * that belong to GFX8 and below GFX families. + * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -286,6 +295,9 @@ struct kfd2kgd_calls { void (*set_vm_context_page_table_base)(struct kgd_dev *kgd, uint32_t vmid, uint64_t page_table_base); uint32_t (*read_vmid_from_vmfault_reg)(struct kgd_dev *kgd); + + void (*get_cu_occupancy)(struct kgd_dev *kgd, int pasid, int *wave_cnt, + int *max_waves_per_cu); }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ -- GitLab From f2fa07b39fafb2a5f49c71a504862c5efa57d03e Mon Sep 17 00:00:00 2001 From: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Date: Tue, 29 Sep 2020 12:15:13 -0500 Subject: [PATCH 1469/1494] drm/amd/amdkfd: Surface files in Sysfs to allow users to get number of compute units that are in use. [Why] Allow user to know how many compute units (CU) are in use at any given moment. [How] Surface files in Sysfs that allow user to determine the number of compute units that are in use for a given process. One Sysfs file is used per device. Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com> Reviewed-By: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 25 +++++++++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 71 +++++++++++++++++++++++- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 56f92cfff591a..b7be5c5751b7f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -705,6 +705,31 @@ struct kfd_process_device { struct kobject *kobj_stats; unsigned int doorbell_index; + + /* + * @cu_occupancy: Reports occupancy of Compute Units (CU) of a process + * that is associated with device encoded by "this" struct instance. The + * value reflects CU usage by all of the waves launched by this process + * on this device. A very important property of occupancy parameter is + * that its value is a snapshot of current use. + * + * Following is to be noted regarding how this parameter is reported: + * + * The number of waves that a CU can launch is limited by couple of + * parameters. These are encoded by struct amdgpu_cu_info instance + * that is part of every device definition. For GFX9 devices this + * translates to 40 waves (simd_per_cu * max_waves_per_simd) when waves + * do not use scratch memory and 32 waves (max_scratch_slots_per_cu) + * when they do use scratch memory. This could change for future + * devices and therefore this example should be considered as a guide. + * + * All CU's of a device are available for the process. This may not be true + * under certain conditions - e.g. CU masking. + * + * Finally number of CU's that are occupied by a process is affected by both + * number of CU's a device has along with number of other competing processes + */ + struct attribute attr_cu_occupancy; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 17d909c86f508..2807e1c4d59bf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -249,6 +249,52 @@ static void kfd_sdma_activity_worker(struct work_struct *work) } } +/** + * @kfd_get_cu_occupancy() - Collect number of waves in-flight on this device + * by current process. Translates acquired wave count into number of compute units + * that are occupied. + * + * @atr: Handle of attribute that allows reporting of wave count. The attribute + * handle encapsulates GPU device it is associated with, thereby allowing collection + * of waves in flight, etc + * + * @buffer: Handle of user provided buffer updated with wave count + * + * Return: Number of bytes written to user buffer or an error value + */ +static int kfd_get_cu_occupancy(struct attribute *attr, char *buffer) +{ + int cu_cnt; + int wave_cnt; + int max_waves_per_cu; + struct kfd_dev *dev = NULL; + struct kfd_process *proc = NULL; + struct kfd_process_device *pdd = NULL; + + pdd = container_of(attr, struct kfd_process_device, attr_cu_occupancy); + dev = pdd->dev; + if (dev->kfd2kgd->get_cu_occupancy == NULL) + return -EINVAL; + + cu_cnt = 0; + proc = pdd->process; + if (pdd->qpd.queue_count == 0) { + pr_debug("Gpu-Id: %d has no active queues for process %d\n", + dev->id, proc->pasid); + return snprintf(buffer, PAGE_SIZE, "%d\n", cu_cnt); + } + + /* Collect wave count from device if it supports */ + wave_cnt = 0; + max_waves_per_cu = 0; + dev->kfd2kgd->get_cu_occupancy(dev->kgd, proc->pasid, &wave_cnt, + &max_waves_per_cu); + + /* Translate wave count to number of compute units */ + cu_cnt = (wave_cnt + (max_waves_per_cu - 1)) / max_waves_per_cu; + return snprintf(buffer, PAGE_SIZE, "%d\n", cu_cnt); +} + static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, char *buffer) { @@ -344,6 +390,7 @@ static ssize_t kfd_procfs_queue_show(struct kobject *kobj, return 0; } + static ssize_t kfd_procfs_stats_show(struct kobject *kobj, struct attribute *attr, char *buffer) { @@ -359,8 +406,13 @@ static ssize_t kfd_procfs_stats_show(struct kobject *kobj, PAGE_SIZE, "%llu\n", jiffies64_to_msecs(evict_jiffies)); - } else + + /* Sysfs handle that gets CU occupancy is per device */ + } else if (strcmp(attr->name, "cu_occupancy") == 0) { + return kfd_get_cu_occupancy(attr, buffer); + } else { pr_err("Invalid attribute"); + } return 0; } @@ -466,6 +518,7 @@ static int kfd_procfs_add_sysfs_stats(struct kfd_process *p) * Create sysfs files for each GPU: * - proc/<pid>/stats_<gpuid>/ * - proc/<pid>/stats_<gpuid>/evicted_ms + * - proc/<pid>/stats_<gpuid>/cu_occupancy */ list_for_each_entry(pdd, &p->per_device_data, per_device_list) { struct kobject *kobj_stats; @@ -496,6 +549,19 @@ static int kfd_procfs_add_sysfs_stats(struct kfd_process *p) if (ret) pr_warn("Creating eviction stats for gpuid %d failed", (int)pdd->dev->id); + + /* Add sysfs file to report compute unit occupancy */ + if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) { + pdd->attr_cu_occupancy.name = "cu_occupancy"; + pdd->attr_cu_occupancy.mode = KFD_SYSFS_FILE_MODE; + sysfs_attr_init(&pdd->attr_cu_occupancy); + ret = sysfs_create_file(kobj_stats, + &pdd->attr_cu_occupancy); + if (ret) + pr_warn("Creating %s failed for gpuid: %d", + pdd->attr_cu_occupancy.name, + (int)pdd->dev->id); + } } err: return ret; @@ -537,7 +603,6 @@ static int kfd_procfs_add_sysfs_files(struct kfd_process *p) return ret; } - void kfd_procfs_del_queue(struct queue *q) { if (!q) @@ -909,6 +974,8 @@ static void kfd_process_wq_release(struct work_struct *work) sysfs_remove_file(p->kobj, &pdd->attr_vram); sysfs_remove_file(p->kobj, &pdd->attr_sdma); sysfs_remove_file(p->kobj, &pdd->attr_evict); + if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) + sysfs_remove_file(p->kobj, &pdd->attr_cu_occupancy); kobject_del(pdd->kobj_stats); kobject_put(pdd->kobj_stats); pdd->kobj_stats = NULL; -- GitLab From 2101bfca57d8102292b85a62331239295bfa772e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen <tomi.valkeinen@ti.com> Date: Tue, 29 Sep 2020 12:19:18 +0300 Subject: [PATCH 1470/1494] drm: bridge: cdns-mhdp8546: fix compile warning On x64 we get: drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c:751:10: warning: conversion from 'long unsigned int' to 'unsigned int' changes value from '18446744073709551613' to '4294967293' [-Woverflow] The registers are 32 bit, so fix by casting to u32. Fixes: fb43aa0acdfd ("drm: bridge: Add support for Cadence MHDP8546 DPI/DP bridge") Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reviewed-by: Swapnil Jakhade <sjakhade@cadence.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20200929091918.24813-1-tomi.valkeinen@ti.com --- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index 621ebdbff8a3a..d0c65610ebb5c 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -748,7 +748,7 @@ static int cdns_mhdp_fw_activate(const struct firmware *fw, * bridge should already be detached. */ if (mhdp->bridge_attached) - writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK); spin_unlock(&mhdp->start_lock); @@ -1689,7 +1689,7 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge, /* Enable SW event interrupts */ if (hw_ready) - writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK); return 0; @@ -2122,7 +2122,7 @@ static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge) /* Enable SW event interrupts */ if (mhdp->bridge_attached) - writel(~CDNS_APB_INT_MASK_SW_EVENT_INT, + writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK); } -- GitLab From 1bba36834c3bc317d8a30dd5d0cc3e59d64dbfb3 Mon Sep 17 00:00:00 2001 From: Hawking Zhang <Hawking.Zhang@amd.com> Date: Thu, 17 Sep 2020 19:32:34 +0800 Subject: [PATCH 1471/1494] drm/amdgpu: add helper function for indirect reg access (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helper function in order to remove RREG32/WREG32 in current pcie_rreg/wreg function for soc15 and onwards adapters. PCIE_INDEX/DATA pairs are used to access regsiters outside of mmio bar in the helper functions. The new helper functions help remove the recursion of amdgpu_mm_rreg/wreg from pcie_rreg/wreg and provide the oppotunity to centralize direct and indirect access in a single function. v2: Fixed typo and refine the comments v3: Remove unnecessary volatile local variable Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 13 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 129 +++++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index befef3b60547e..bc921c83aad78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1032,6 +1032,19 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset); u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg); void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v); +u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr); +u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr); +void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr, u32 reg_data); +void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr, u64 reg_data); + bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type); bool amdgpu_device_has_dc_support(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 76581c59f196c..83aeacaf94d53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -592,6 +592,135 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v) } } +/** + * amdgpu_device_indirect_rreg - read an indirect register + * + * @adev: amdgpu_device pointer + * @pcie_index: mmio register offset + * @pcie_data: mmio register offset + * + * Returns the value of indirect register @reg_addr + */ +u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr) +{ + unsigned long flags; + u32 r; + void __iomem *pcie_index_offset; + void __iomem *pcie_data_offset; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; + + writel(reg_addr, pcie_index_offset); + readl(pcie_index_offset); + r = readl(pcie_data_offset); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + + return r; +} + +/** + * amdgpu_device_indirect_rreg64 - read a 64bits indirect register + * + * @adev: amdgpu_device pointer + * @pcie_index: mmio register offset + * @pcie_data: mmio register offset + * + * Returns the value of indirect register @reg_addr + */ +u64 amdgpu_device_indirect_rreg64(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr) +{ + unsigned long flags; + u64 r; + void __iomem *pcie_index_offset; + void __iomem *pcie_data_offset; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; + + /* read low 32 bits */ + writel(reg_addr, pcie_index_offset); + readl(pcie_index_offset); + r = readl(pcie_data_offset); + /* read high 32 bits */ + writel(reg_addr + 4, pcie_index_offset); + readl(pcie_index_offset); + r |= ((u64)readl(pcie_data_offset) << 32); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + + return r; +} + +/** + * amdgpu_device_indirect_wreg - write an indirect register address + * + * @adev: amdgpu_device pointer + * @pcie_index: mmio register offset + * @pcie_data: mmio register offset + * @reg_addr: indirect register offset + * @reg_data: indirect register data + * + */ +void amdgpu_device_indirect_wreg(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr, u32 reg_data) +{ + unsigned long flags; + void __iomem *pcie_index_offset; + void __iomem *pcie_data_offset; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; + + writel(reg_addr, pcie_index_offset); + readl(pcie_index_offset); + writel(reg_data, pcie_data_offset); + readl(pcie_data_offset); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + +/** + * amdgpu_device_indirect_wreg64 - write a 64bits indirect register address + * + * @adev: amdgpu_device pointer + * @pcie_index: mmio register offset + * @pcie_data: mmio register offset + * @reg_addr: indirect register offset + * @reg_data: indirect register data + * + */ +void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev, + u32 pcie_index, u32 pcie_data, + u32 reg_addr, u64 reg_data) +{ + unsigned long flags; + void __iomem *pcie_index_offset; + void __iomem *pcie_data_offset; + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4; + pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4; + + /* write low 32 bits */ + writel(reg_addr, pcie_index_offset); + readl(pcie_index_offset); + writel((u32)(reg_data & 0xffffffffULL), pcie_data_offset); + readl(pcie_data_offset); + /* write high 32 bits */ + writel(reg_addr + 4, pcie_index_offset); + readl(pcie_index_offset); + writel((u32)(reg_data >> 32), pcie_data_offset); + readl(pcie_data_offset); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} + /** * amdgpu_invalid_rreg - dummy reg read function * -- GitLab From 705a2b5ba0635c2fa3e5b6a830a6b4fe178de699 Mon Sep 17 00:00:00 2001 From: Hawking Zhang <Hawking.Zhang@amd.com> Date: Tue, 15 Sep 2020 17:57:30 +0800 Subject: [PATCH 1472/1494] drm/amdgpu: switch to indirect reg access helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch WREG32/RREG32_PCIE to use indirect reg access helper for soc15 and onwards Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/nv.c | 51 +++++------------------------- drivers/gpu/drm/amd/amdgpu/soc15.c | 51 +++++------------------------- 2 files changed, 16 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index bc894cfba60c2..1ce741a0c6a74 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -69,75 +69,40 @@ static const struct amd_ip_funcs nv_common_ip_funcs; */ static u32 nv_pcie_rreg(struct amdgpu_device *adev, u32 reg) { - unsigned long flags, address, data; - u32 r; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg); - (void)RREG32(address); - r = RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; + return amdgpu_device_indirect_rreg(adev, address, data, reg); } static void nv_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { - unsigned long flags, address, data; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg); - (void)RREG32(address); - WREG32(data, v); - (void)RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + amdgpu_device_indirect_wreg(adev, address, data, reg, v); } static u64 nv_pcie_rreg64(struct amdgpu_device *adev, u32 reg) { - unsigned long flags, address, data; - u64 r; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - /* read low 32 bit */ - WREG32(address, reg); - (void)RREG32(address); - r = RREG32(data); - - /* read high 32 bit*/ - WREG32(address, reg + 4); - (void)RREG32(address); - r |= ((u64)RREG32(data) << 32); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; + return amdgpu_device_indirect_rreg64(adev, address, data, reg); } static void nv_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) { - unsigned long flags, address, data; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - /* write low 32 bit */ - WREG32(address, reg); - (void)RREG32(address); - WREG32(data, (u32)(v & 0xffffffffULL)); - (void)RREG32(data); - - /* write high 32 bit */ - WREG32(address, reg + 4); - (void)RREG32(address); - WREG32(data, (u32)(v >> 32)); - (void)RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + amdgpu_device_indirect_wreg64(adev, address, data, reg, v); } static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index ddd55e3176c47..0de9df8cc8dd8 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -101,75 +101,40 @@ */ static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg) { - unsigned long flags, address, data; - u32 r; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg); - (void)RREG32(address); - r = RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; + return amdgpu_device_indirect_rreg(adev, address, data, reg); } static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { - unsigned long flags, address, data; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg); - (void)RREG32(address); - WREG32(data, v); - (void)RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + amdgpu_device_indirect_wreg(adev, address, data, reg, v); } static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg) { - unsigned long flags, address, data; - u64 r; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - /* read low 32 bit */ - WREG32(address, reg); - (void)RREG32(address); - r = RREG32(data); - - /* read high 32 bit*/ - WREG32(address, reg + 4); - (void)RREG32(address); - r |= ((u64)RREG32(data) << 32); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; + return amdgpu_device_indirect_rreg64(adev, address, data, reg); } static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) { - unsigned long flags, address, data; + unsigned long address, data; address = adev->nbio.funcs->get_pcie_index_offset(adev); data = adev->nbio.funcs->get_pcie_data_offset(adev); - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - /* write low 32 bit */ - WREG32(address, reg); - (void)RREG32(address); - WREG32(data, (u32)(v & 0xffffffffULL)); - (void)RREG32(data); - - /* write high 32 bit */ - WREG32(address, reg + 4); - (void)RREG32(address); - WREG32(data, (u32)(v >> 32)); - (void)RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + amdgpu_device_indirect_wreg64(adev, address, data, reg, v); } static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) -- GitLab From f7ee1874b06cfda6295ef236116ef189fdb9bd06 Mon Sep 17 00:00:00 2001 From: Hawking Zhang <Hawking.Zhang@amd.com> Date: Fri, 18 Sep 2020 20:32:25 +0800 Subject: [PATCH 1473/1494] drm/amdgpu: support indirect access reg outside of mmio bar (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit support both direct and indirect accessor in unified helper functions. v2: Retire indirect mmio access via mm_index/data Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Kevin Wang <kevin1.wang@amd.com> Reviewed-by: Guchun Chen <guchun.chen@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 23 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 95 +++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 4 +- 4 files changed, 53 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index bc921c83aad78..87f095dc385c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1020,12 +1020,13 @@ int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev); void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, uint32_t *buf, size_t size, bool write); -uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, +uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, + uint32_t reg, uint32_t acc_flags); +void amdgpu_device_wreg(struct amdgpu_device *adev, + uint32_t reg, uint32_t v, uint32_t acc_flags); -void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, - uint32_t acc_flags); -void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t v, - uint32_t acc_flags); +void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, + uint32_t reg, uint32_t v); void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value); uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset); @@ -1055,8 +1056,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev); */ #define AMDGPU_REGS_NO_KIQ (1<<1) -#define RREG32_NO_KIQ(reg) amdgpu_mm_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ) -#define WREG32_NO_KIQ(reg, v) amdgpu_mm_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ) +#define RREG32_NO_KIQ(reg) amdgpu_device_rreg(adev, (reg), AMDGPU_REGS_NO_KIQ) +#define WREG32_NO_KIQ(reg, v) amdgpu_device_wreg(adev, (reg), (v), AMDGPU_REGS_NO_KIQ) #define RREG32_KIQ(reg) amdgpu_kiq_rreg(adev, (reg)) #define WREG32_KIQ(reg, v) amdgpu_kiq_wreg(adev, (reg), (v)) @@ -1064,9 +1065,9 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define RREG8(reg) amdgpu_mm_rreg8(adev, (reg)) #define WREG8(reg, v) amdgpu_mm_wreg8(adev, (reg), (v)) -#define RREG32(reg) amdgpu_mm_rreg(adev, (reg), 0) -#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_mm_rreg(adev, (reg), 0)) -#define WREG32(reg, v) amdgpu_mm_wreg(adev, (reg), (v), 0) +#define RREG32(reg) amdgpu_device_rreg(adev, (reg), 0) +#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", amdgpu_device_rreg(adev, (reg), 0)) +#define WREG32(reg, v) amdgpu_device_wreg(adev, (reg), (v), 0) #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) #define RREG32_PCIE(reg) adev->pcie_rreg(adev, (reg)) @@ -1112,7 +1113,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); WREG32_SMC(_Reg, tmp); \ } while (0) -#define DREG32_SYS(sqf, adev, reg) seq_printf((sqf), #reg " : 0x%08X\n", amdgpu_mm_rreg((adev), (reg), false)) +#define DREG32_SYS(sqf, adev, reg) seq_printf((sqf), #reg " : 0x%08X\n", amdgpu_device_rreg((adev), (reg), false)) #define RREG32_IO(reg) amdgpu_io_rreg(adev, (reg)) #define WREG32_IO(reg, v) amdgpu_io_wreg(adev, (reg), (v)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index abe0c2729e1cf..2d125b8b15ee1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -267,7 +267,7 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, } else { r = get_user(value, (uint32_t *)buf); if (!r) - amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0); + amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value); } if (r) { result = r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 83aeacaf94d53..d0a42c2b6809f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -301,10 +301,10 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, } /* - * MMIO register access helper functions. + * register access helper functions. */ /** - * amdgpu_mm_rreg - read a memory mapped IO register + * amdgpu_device_rreg - read a memory mapped IO or indirect register * * @adev: amdgpu_device pointer * @reg: dword aligned register offset @@ -312,33 +312,29 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos, * * Returns the 32 bit value from the offset specified. */ -uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, - uint32_t acc_flags) +uint32_t amdgpu_device_rreg(struct amdgpu_device *adev, + uint32_t reg, uint32_t acc_flags) { uint32_t ret; if (adev->in_pci_err_recovery) return 0; - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && - down_read_trylock(&adev->reset_sem)) { - ret = amdgpu_kiq_rreg(adev, reg); - up_read(&adev->reset_sem); - return ret; + if ((reg * 4) < adev->rmmio_size) { + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && + amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + ret = amdgpu_kiq_rreg(adev, reg); + up_read(&adev->reset_sem); + } else { + ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); + } + } else { + ret = adev->pcie_rreg(adev, reg * 4); } - if ((reg * 4) < adev->rmmio_size) - ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); - else { - unsigned long flags; - - spin_lock_irqsave(&adev->mmio_idx_lock, flags); - writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4)); - ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); - spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); - } + trace_amdgpu_device_rreg(adev->pdev->device, reg, ret); - trace_amdgpu_mm_rreg(adev->pdev->device, reg, ret); return ret; } @@ -392,29 +388,8 @@ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) BUG(); } -static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, - uint32_t reg, uint32_t v, - uint32_t acc_flags) -{ - if (adev->in_pci_err_recovery) - return; - - trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); - - if ((reg * 4) < adev->rmmio_size) - writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); - else { - unsigned long flags; - - spin_lock_irqsave(&adev->mmio_idx_lock, flags); - writel((reg * 4), ((void __iomem *)adev->rmmio) + (mmMM_INDEX * 4)); - writel(v, ((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); - spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); - } -} - /** - * amdgpu_mm_wreg - write to a memory mapped IO register + * amdgpu_device_wreg - write to a memory mapped IO or indirect register * * @adev: amdgpu_device pointer * @reg: dword aligned register offset @@ -423,20 +398,27 @@ static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, * * Writes the value specified to the offset specified. */ -void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, - uint32_t acc_flags) +void amdgpu_device_wreg(struct amdgpu_device *adev, + uint32_t reg, uint32_t v, + uint32_t acc_flags) { if (adev->in_pci_err_recovery) return; - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && - down_read_trylock(&adev->reset_sem)) { - amdgpu_kiq_wreg(adev, reg, v); - up_read(&adev->reset_sem); - return; + if ((reg * 4) < adev->rmmio_size) { + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && + amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + amdgpu_kiq_wreg(adev, reg, v); + up_read(&adev->reset_sem); + } else { + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); + } + } else { + adev->pcie_wreg(adev, reg * 4, v); } - amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags); + trace_amdgpu_device_wreg(adev->pdev->device, reg, v); } /* @@ -444,21 +426,20 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, * * this function is invoked only the debugfs register access * */ -void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t v, - uint32_t acc_flags) +void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, + uint32_t reg, uint32_t v) { if (adev->in_pci_err_recovery) return; if (amdgpu_sriov_fullaccess(adev) && - adev->gfx.rlc.funcs && - adev->gfx.rlc.funcs->is_rlcg_access_range) { - + adev->gfx.rlc.funcs && + adev->gfx.rlc.funcs->is_rlcg_access_range) { if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v); + } else { + writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); } - - amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 82c2e70a6a714..ee9480d14cbc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -35,7 +35,7 @@ #define AMDGPU_JOB_GET_TIMELINE_NAME(job) \ job->base.s_fence->finished.ops->get_timeline_name(&job->base.s_fence->finished) -TRACE_EVENT(amdgpu_mm_rreg, +TRACE_EVENT(amdgpu_device_rreg, TP_PROTO(unsigned did, uint32_t reg, uint32_t value), TP_ARGS(did, reg, value), TP_STRUCT__entry( @@ -54,7 +54,7 @@ TRACE_EVENT(amdgpu_mm_rreg, (unsigned long)__entry->value) ); -TRACE_EVENT(amdgpu_mm_wreg, +TRACE_EVENT(amdgpu_device_wreg, TP_PROTO(unsigned did, uint32_t reg, uint32_t value), TP_ARGS(did, reg, value), TP_STRUCT__entry( -- GitLab From 346dbbb8f7a0f94eb4264d1e0a253be2edca6eb8 Mon Sep 17 00:00:00 2001 From: Hawking Zhang <Hawking.Zhang@amd.com> Date: Wed, 30 Sep 2020 23:09:57 +0800 Subject: [PATCH 1474/1494] drm/amdgpu: enable GDDR6 save-restore support for navy_flounder add mp0 11_0_11 for navy_flounder to the mem training supported list, otherwise the modeprobe would fail on navy_flounder with latest vbios. Signed-off-by: Hawking Zhang <Hawking.Zhang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 17c010d0431fb..b4df6460e45a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -543,6 +543,7 @@ int amdgpu_mem_train_support(struct amdgpu_device *adev) case HW_REV(11, 0, 0): case HW_REV(11, 0, 5): case HW_REV(11, 0, 7): + case HW_REV(11, 0, 11): ret = 1; break; default: -- GitLab From 1a8a763b218cef8cf881fc0d1d739283db24c167 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 1 Oct 2020 09:03:37 -0400 Subject: [PATCH 1475/1494] drm/amdgpu/swsmu: add interrupt work function So we can schedule work from interrupts. This might include long tasks or things that could sleep. Fixes: e1188aacad1730 ("drm/amdgpu/smu11: add support for SMU AC/DC interrupts") Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 2 ++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 85c5e8627e3be..44fd0cd069de6 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -453,6 +453,7 @@ struct smu_context struct work_struct throttling_logging_work; atomic64_t throttle_int_counter; + struct work_struct interrupt_work; unsigned fan_max_rpm; unsigned manual_fan_speed_rpm; @@ -601,6 +602,7 @@ struct pptable_funcs { int (*deep_sleep_control)(struct smu_context *smu, bool enablement); int (*get_fan_parameters)(struct smu_context *smu); int (*post_init)(struct smu_context *smu); + void (*interrupt_work)(struct smu_context *smu); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3010cb31324ab..d20a657ee081d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -780,6 +780,19 @@ static void smu_throttling_logging_work_fn(struct work_struct *work) smu_log_thermal_throttling(smu); } +static void smu_interrupt_work_fn(struct work_struct *work) +{ + struct smu_context *smu = container_of(work, struct smu_context, + interrupt_work); + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs && smu->ppt_funcs->interrupt_work) + smu->ppt_funcs->interrupt_work(smu); + + mutex_unlock(&smu->mutex); +} + static int smu_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -802,6 +815,7 @@ static int smu_sw_init(void *handle) mutex_init(&smu->message_lock); INIT_WORK(&smu->throttling_logging_work, smu_throttling_logging_work_fn); + INIT_WORK(&smu->interrupt_work, smu_interrupt_work_fn); atomic64_set(&smu->throttle_int_counter, 0); smu->watermarks_bitmap = 0; smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; @@ -1197,6 +1211,7 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) int ret = 0; cancel_work_sync(&smu->throttling_logging_work); + cancel_work_sync(&smu->interrupt_work); ret = smu_disable_thermal_alert(smu); if (ret) { -- GitLab From 234676d6dbbcd8b2a495e76efdc69e24c0aa300f Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Thu, 1 Oct 2020 10:43:28 -0400 Subject: [PATCH 1476/1494] drm/amdgpu/swsmu: add interrupt work handler for smu11 parts We need to schedule the smu AC/DC interrupt ack to avoid potentially sleeping if the smu message mutex is contended. Fixes: e1188aacad1730 ("drm/amdgpu/smu11: add support for SMU AC/DC interrupts") Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 + .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 10 ++++++++-- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 03198d214bbaa..2d1c3babaa3a0 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -280,5 +280,7 @@ int smu_v11_0_gfx_ulv_control(struct smu_context *smu, int smu_v11_0_deep_sleep_control(struct smu_context *smu, bool enablement); +void smu_v11_0_interrupt_work(struct smu_context *smu); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index d298fa65274df..fc376281e629a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2388,6 +2388,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, .get_fan_parameters = arcturus_get_fan_parameters, + .interrupt_work = smu_v11_0_interrupt_work, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index be44cb941e732..3f1377f284937 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2755,6 +2755,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .deep_sleep_control = smu_v11_0_deep_sleep_control, .get_fan_parameters = navi10_get_fan_parameters, .post_init = navi10_post_smu_init, + .interrupt_work = smu_v11_0_interrupt_work, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index a2cb831ce8aae..3c8732f34b1fc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2784,6 +2784,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, .get_fan_parameters = sienna_cichlid_get_fan_parameters, + .interrupt_work = smu_v11_0_interrupt_work, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index d8ca6d968813d..2380759ddf480 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -955,6 +955,12 @@ static int smu_v11_0_process_pending_interrupt(struct smu_context *smu) return ret; } +void smu_v11_0_interrupt_work(struct smu_context *smu) +{ + if (smu_v11_0_ack_ac_dc_interrupt(smu)) + dev_err(smu->adev->dev, "Ack AC/DC interrupt Failed!\n"); +} + int smu_v11_0_enable_thermal_alert(struct smu_context *smu) { int ret = 0; @@ -1320,11 +1326,11 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, switch (ctxid) { case 0x3: dev_dbg(adev->dev, "Switched to AC mode!\n"); - smu_v11_0_ack_ac_dc_interrupt(&adev->smu); + schedule_work(&smu->interrupt_work); break; case 0x4: dev_dbg(adev->dev, "Switched to DC mode!\n"); - smu_v11_0_ack_ac_dc_interrupt(&adev->smu); + schedule_work(&smu->interrupt_work); break; case 0x7: /* -- GitLab From edb899841c4e4c52cd78257029929bd9c6ab011d Mon Sep 17 00:00:00 2001 From: Dave Airlie <airlied@redhat.com> Date: Thu, 1 Oct 2020 14:20:12 +1000 Subject: [PATCH 1477/1494] drm/vmwgfx: fix regression in thp code due to ttm init refactor. When I refactored this code with the new init paths, I failed to set the funcs back up properly, this caused a failure to bringup gdm properly. Fixes: 252f8d7b9174 ("drm/vmwgfx/ttm: convert vram mm init to new code paths") Signed-off-by: Dave Airlie <airlied@redhat.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201001042012.13114-1-airlied@gmail.com --- drivers/gpu/drm/vmwgfx/vmwgfx_thp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c index 63fe7da4cbf40..c158e672b7623 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_thp.c @@ -26,6 +26,8 @@ static struct vmw_thp_manager *to_thp_manager(struct ttm_resource_manager *man) return container_of(man, struct vmw_thp_manager, manager); } +static const struct ttm_resource_manager_func vmw_thp_func; + static int vmw_thp_insert_aligned(struct drm_mm *mm, struct drm_mm_node *node, unsigned long align_pages, const struct ttm_place *place, @@ -132,6 +134,7 @@ int vmw_thp_init(struct vmw_private *dev_priv) ttm_resource_manager_init(&rman->manager, dev_priv->vram_size >> PAGE_SHIFT); + rman->manager.func = &vmw_thp_func; drm_mm_init(&rman->mm, 0, rman->manager.size); spin_lock_init(&rman->lock); @@ -171,7 +174,7 @@ static void vmw_thp_debug(struct ttm_resource_manager *man, spin_unlock(&rman->lock); } -const struct ttm_resource_manager_func vmw_thp_func = { +static const struct ttm_resource_manager_func vmw_thp_func = { .alloc = vmw_thp_get_node, .free = vmw_thp_put_node, .debug = vmw_thp_debug -- GitLab From 2ae78708047026397713a0e4af011bdd5d392e14 Mon Sep 17 00:00:00 2001 From: Dirk Gouders <dirk@gouders.net> Date: Thu, 1 Oct 2020 21:55:25 +0200 Subject: [PATCH 1478/1494] drm/amdgpu: fix NULL pointer dereference for Renoir Commit c1cf79ca5ced46 ("drm/amdgpu: use IP discovery table for renoir") introduced a NULL pointer dereference when booting with amdgpu.discovery=0, because it removed the call of vega10_reg_base_init() for that case. Fix this by calling that funcion if amdgpu_discovery == 0 in addition to the case that amdgpu_discovery_reg_base_init() failed. Fixes: c1cf79ca5ced46 ("drm/amdgpu: use IP discovery table for renoir") Signed-off-by: Dirk Gouders <dirk@gouders.net> Cc: Hawking Zhang <Hawking.Zhang@amd.com> Cc: Evan Quan <evan.quan@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/soc15.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 0de9df8cc8dd8..afcccc6c0fc61 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -662,12 +662,12 @@ static void soc15_reg_base_init(struct amdgpu_device *adev) * it doesn't support SRIOV. */ if (amdgpu_discovery) { r = amdgpu_discovery_reg_base_init(adev); - if (r) { - DRM_WARN("failed to init reg base from ip discovery table, " - "fallback to legacy init method\n"); - vega10_reg_base_init(adev); - } + if (r == 0) + break; + DRM_WARN("failed to init reg base from ip discovery table, " + "fallback to legacy init method\n"); } + vega10_reg_base_init(adev); break; case CHIP_VEGA20: vega20_reg_base_init(adev); -- GitLab From 79b1eca0e4acab4c3c71e9563cbbd7ab79e9c70b Mon Sep 17 00:00:00 2001 From: Alex Sierra <alex.sierra@amd.com> Date: Sat, 3 Oct 2020 13:31:21 -0500 Subject: [PATCH 1479/1494] drm/amdgpu: align frag_end to covered address space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit align frag_end to the next pd when there are no page table entries on the current pde. This fixes invalidation of larger address space areas where some page tables are allocated and other aren't. Signed-off-by: Alex Sierra <alex.sierra@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index a4efc903349e9..2b65e83c808b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1502,6 +1502,8 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, pt = cursor.entry->base.bo; shift = parent_shift; + frag_end = max(frag_end, ALIGN(frag_start + 1, + 1ULL << shift)); } /* Looks good so far, calculate parameters for the update */ -- GitLab From 2f8be0e516803cc3fd87c1671247896571a5a8fb Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Date: Wed, 30 Sep 2020 13:57:54 -0400 Subject: [PATCH 1480/1494] drm/amd/display: Avoid set zero in the requested clk [Why] Sometimes CRTCs can be disabled due to display unplugging or temporarily transition in the userspace; in these circumstances, DCE tries to set the minimum clock threshold. When we have this situation, the function bw_calcs is invoked with number_of_displays set to zero, making DCE set dispclk_khz and sclk_khz to zero. For these reasons, we have seen some ATOM bios errors that look like: [drm:atom_op_jump [amdgpu]] *ERROR* atombios stuck in loop for more than 5secs aborting [drm:amdgpu_atom_execute_table_locked [amdgpu]] *ERROR* atombios stuck executing EA8A (len 761, WS 0, PS 0) @ 0xEABA [How] This error happens due to an attempt to optimize the bandwidth using the sclk, and the dispclk clock set to zero. Technically we handle this in the function dce112_set_clock, but we are not considering the case that this value is set to zero. This commit fixes this issue by ensuring that we never set a minimum value below the minimum clock threshold. Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c index d031bd3d30724..807dca8f7d7aa 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce112/dce112_clk_mgr.c @@ -79,8 +79,7 @@ int dce112_set_clock(struct clk_mgr *clk_mgr_base, int requested_clk_khz) memset(&dce_clk_params, 0, sizeof(dce_clk_params)); /* Make sure requested clock isn't lower than minimum threshold*/ - if (requested_clk_khz > 0) - requested_clk_khz = max(requested_clk_khz, + requested_clk_khz = max(requested_clk_khz, clk_mgr_dce->base.dentist_vco_freq_khz / 62); dce_clk_params.target_clock_frequency = requested_clk_khz; -- GitLab From dc3de51642add38e9dbdc6eb9f8286b3eee42fe0 Mon Sep 17 00:00:00 2001 From: Chris Park <Chris.Park@amd.com> Date: Tue, 22 Sep 2020 18:31:38 -0400 Subject: [PATCH 1481/1494] drm/amd/display: Change to correct unit on audio rate [Why] Formula uses kHz in their formula while our driver operates with Hz. [How] Divide audio rate by 1000 on the initial variable that is entered into formula. Signed-off-by: Chris Park <Chris.Park@amd.com> Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Acked-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index bf37a229a3424..d50a9c3706372 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -150,7 +150,6 @@ struct _vcs_dpi_ip_params_st dcn2_0_ip = { .dispclk_delay_subtotal = 87, // .dcfclk_cstate_latency = 10, // SRExitTime .max_inter_dcn_tile_repeaters = 8, - .xfc_supported = true, .xfc_fill_bw_overhead_percent = 10.0, .xfc_fill_constant_bytes = 0, @@ -2203,9 +2202,9 @@ int dcn20_populate_dml_pipes_from_context( /* todo: default max for now, until there is logic reflecting this in dc*/ pipes[pipe_cnt].dout.output_bpc = 12; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) - /*fill up the audio sample rate*/ + /*fill up the audio sample rate (unit in kHz)*/ get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check); - pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate; + pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000; #endif /* * For graphic plane, cursor number is 1, nv12 is 0 -- GitLab From 95d620adb48f7728e67d82f56f756e8d451cf8d2 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo <Jerry.Zuo@amd.com> Date: Mon, 21 Sep 2020 17:52:43 -0400 Subject: [PATCH 1482/1494] drm/amd/display: HDMI remote sink need mode validation for Linux [Why] Currently mode validation is bypassed if remote sink exists. That leads to mode set issue when a BW bottle neck exists in the link path, e.g., a DP-to-HDMI converter that only supports HDMI 1.4. Any invalid mode passed to Linux user space will cause the modeset failure due to limitation of Linux user space implementation. [How] Mode validation is skipped only if in edid override. For real remote sink, clock limit check should be done for HDMI remote sink. Have HDMI related remote sink going through mode validation to elimiate modes which pixel clock exceeds BW limitation. Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Reviewed-by: Hersen Wu <hersenxs.wu@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f13396254b5d2..fec87a2e210cf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2441,7 +2441,7 @@ enum dc_status dc_link_validate_mode_timing( /* A hack to avoid failing any modes for EDID override feature on * topology change such as lower quality cable for DP or different dongle */ - if (link->remote_sinks[0]) + if (link->remote_sinks[0] && link->remote_sinks[0]->sink_signal == SIGNAL_TYPE_VIRTUAL) return DC_OK; /* Passive Dongle */ -- GitLab From a3fb64c00d44a3ce869c0ca8210f95f99497aa9e Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Sun, 4 Oct 2020 16:17:58 +0200 Subject: [PATCH 1483/1494] Revert "gpu/drm: ingenic: Add option to mmap GEM buffers cached" This reverts commit 37054fc81443 ("gpu/drm: ingenic: Add option to mmap GEM buffers cached") At the very moment this commit was created, the DMA API it relied on was modified in the DMA tree, which caused the driver to break in linux-next. Revert it for now, and it will be resubmitted later to work with the new DMA API. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20201004141758.1013317-1-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 116 ++-------------------- drivers/gpu/drm/ingenic/ingenic-drm.h | 4 - drivers/gpu/drm/ingenic/ingenic-ipu.c | 12 +-- 3 files changed, 13 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 937d080f5d06a..1be1235bd546d 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -9,8 +9,6 @@ #include <linux/component.h> #include <linux/clk.h> #include <linux/dma-mapping.h> -#include <linux/dma-noncoherent.h> -#include <linux/io.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -21,7 +19,6 @@ #include <drm/drm_bridge.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h> @@ -79,11 +76,6 @@ static const u32 ingenic_drm_primary_formats[] = { DRM_FORMAT_XRGB8888, }; -static bool ingenic_drm_cached_gem_buf; -module_param_named(cached_gem_buffers, ingenic_drm_cached_gem_buf, bool, 0400); -MODULE_PARM_DESC(cached_gem_buffers, - "Enable fully cached GEM buffers [default=false]"); - static bool ingenic_drm_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -346,8 +338,6 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane, plane->state->fb->format->format != state->fb->format->format)) crtc_state->mode_changed = true; - drm_atomic_helper_check_plane_damage(state->state, state); - return 0; } @@ -450,35 +440,17 @@ void ingenic_drm_plane_config(struct device *dev, } } -void ingenic_drm_sync_data(struct device *dev, - struct drm_plane_state *old_state, - struct drm_plane_state *state) +static void ingenic_drm_update_palette(struct ingenic_drm *priv, + const struct drm_color_lut *lut) { - const struct drm_format_info *finfo = state->fb->format; - struct ingenic_drm *priv = dev_get_drvdata(dev); - struct drm_atomic_helper_damage_iter iter; - unsigned int offset, i; - struct drm_rect clip; - dma_addr_t paddr; - void *addr; - - if (!ingenic_drm_cached_gem_buf) - return; - - drm_atomic_helper_damage_iter_init(&iter, old_state, state); + unsigned int i; - drm_atomic_for_each_plane_damage(&iter, &clip) { - for (i = 0; i < finfo->num_planes; i++) { - paddr = drm_fb_cma_get_gem_addr(state->fb, state, i); - addr = phys_to_virt(paddr); + for (i = 0; i < ARRAY_SIZE(priv->dma_hwdescs->palette); i++) { + u16 color = drm_color_lut_extract(lut[i].red, 5) << 11 + | drm_color_lut_extract(lut[i].green, 6) << 5 + | drm_color_lut_extract(lut[i].blue, 5); - /* Ignore x1/x2 values, invalidate complete lines */ - offset = clip.y1 * state->fb->pitches[i]; - - dma_cache_sync(priv->dev, addr + offset, - (clip.y2 - clip.y1) * state->fb->pitches[i], - DMA_TO_DEVICE); - } + priv->dma_hwdescs->palette[i] = color; } } @@ -492,7 +464,7 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, dma_addr_t addr; if (state && state->fb) { - ingenic_drm_sync_data(priv->dev, oldstate, state); + crtc_state = state->crtc->state; addr = drm_fb_cma_get_gem_addr(state->fb, state, 0); width = state->src_w >> 16; @@ -649,69 +621,7 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0); } -static struct drm_framebuffer * -ingenic_drm_gem_fb_create(struct drm_device *dev, struct drm_file *file, - const struct drm_mode_fb_cmd2 *mode_cmd) -{ - if (ingenic_drm_cached_gem_buf) - return drm_gem_fb_create_with_dirty(dev, file, mode_cmd); - - return drm_gem_fb_create(dev, file, mode_cmd); -} - -static int ingenic_drm_gem_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) -{ - struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj); - struct device *dev = cma_obj->base.dev->dev; - unsigned long attrs; - int ret; - - if (ingenic_drm_cached_gem_buf) - attrs = DMA_ATTR_NON_CONSISTENT; - else - attrs = DMA_ATTR_WRITE_COMBINE; - - /* - * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the - * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map - * the whole buffer. - */ - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_pgoff = 0; - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - - ret = dma_mmap_attrs(dev, vma, cma_obj->vaddr, cma_obj->paddr, - vma->vm_end - vma->vm_start, attrs); - if (ret) - drm_gem_vm_close(vma); - - return ret; -} - -static int ingenic_drm_gem_cma_mmap(struct file *filp, - struct vm_area_struct *vma) -{ - int ret; - - ret = drm_gem_mmap(filp, vma); - if (ret) - return ret; - - return ingenic_drm_gem_mmap(vma->vm_private_data, vma); -} - -static const struct file_operations ingenic_drm_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .compat_ioctl = drm_compat_ioctl, - .poll = drm_poll, - .read = drm_read, - .llseek = noop_llseek, - .mmap = ingenic_drm_gem_cma_mmap, -}; +DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); static struct drm_driver ingenic_drm_driver_data = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, @@ -775,7 +685,7 @@ static const struct drm_encoder_helper_funcs ingenic_drm_encoder_helper_funcs = }; static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = { - .fb_create = ingenic_drm_gem_fb_create, + .fb_create = drm_gem_fb_create, .output_poll_changed = drm_fb_helper_output_poll_changed, .atomic_check = drm_atomic_helper_check, .atomic_commit = drm_atomic_helper_commit, @@ -902,8 +812,6 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } - drm_plane_enable_fb_damage_clips(&priv->f1); - drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1, @@ -929,8 +837,6 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } - drm_plane_enable_fb_damage_clips(&priv->f0); - if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) { ret = component_bind_all(dev, drm); if (ret) { diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.h b/drivers/gpu/drm/ingenic/ingenic-drm.h index df99f0f75d393..43f7d959cff7e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm.h +++ b/drivers/gpu/drm/ingenic/ingenic-drm.h @@ -168,10 +168,6 @@ void ingenic_drm_plane_config(struct device *dev, struct drm_plane *plane, u32 fourcc); void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane); -void ingenic_drm_sync_data(struct device *dev, - struct drm_plane_state *old_state, - struct drm_plane_state *state); - extern struct platform_driver *ingenic_ipu_driver_ptr; #endif /* DRIVERS_GPU_DRM_INGENIC_INGENIC_DRM_H */ diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index 38c83e8cc6a54..fc8c6e970ee31 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -20,7 +20,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> @@ -317,8 +316,6 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane, JZ_IPU_CTRL_CHIP_EN | JZ_IPU_CTRL_LCDC_SEL); } - ingenic_drm_sync_data(ipu->master, oldstate, state); - /* New addresses will be committed in vblank handler... */ ipu->addr_y = drm_fb_cma_get_gem_addr(state->fb, state, 0); if (finfo->num_planes > 1) @@ -537,7 +534,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, if (!state->crtc || !crtc_state->mode.hdisplay || !crtc_state->mode.vdisplay) - goto out_check_damage; + return 0; /* Plane must be fully visible */ if (state->crtc_x < 0 || state->crtc_y < 0 || @@ -554,7 +551,7 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, return -EINVAL; if (!osd_changed(state, plane->state)) - goto out_check_damage; + return 0; crtc_state->mode_changed = true; @@ -581,9 +578,6 @@ static int ingenic_ipu_plane_atomic_check(struct drm_plane *plane, ipu->denom_w = denom_w; ipu->denom_h = denom_h; -out_check_damage: - drm_atomic_helper_check_plane_damage(state->state, state); - return 0; } @@ -765,8 +759,6 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d) return err; } - drm_plane_enable_fb_damage_clips(plane); - /* * Sharpness settings range is [0,32] * 0 : nearest-neighbor -- GitLab From 6561e0aa4627da90f59076fec5e3a1b72a8aa63f Mon Sep 17 00:00:00 2001 From: Ondrej Jirman <megous@megous.com> Date: Wed, 1 Jul 2020 20:46:40 +0200 Subject: [PATCH 1484/1494] MAINTAINERS: Update entry for st7703 driver after the rename The driver was renamed, change the path in the MAINTAINERS file. Signed-off-by: Ondrej Jirman <megous@megous.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://lore.kernel.org/lkml/20200701184640.1674969-1-megous@megous.com/#t --- MAINTAINERS | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 10992f6541bd1..99db89d21ddd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5594,12 +5594,13 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.yaml F: drivers/gpu/drm/panel/panel-raydium-rm67191.c -DRM DRIVER FOR ROCKTECH JH057N00900 PANELS +DRM DRIVER FOR SITRONIX ST7703 PANELS M: Guido Günther <agx@sigxcpu.org> R: Purism Kernel Team <kernel@puri.sm> +R: Ondrej Jirman <megous@megous.com> S: Maintained -F: Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.txt -F: drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c +F: Documentation/devicetree/bindings/display/panel/rocktech,jh057n00900.yaml +F: drivers/gpu/drm/panel/panel-sitronix-st7703.c DRM DRIVER FOR SAVAGE VIDEO CARDS S: Orphan / Obsolete -- GitLab From c2df75ad2a9f205820e4bc0db936d3d9af3da1ae Mon Sep 17 00:00:00 2001 From: Christian Hewitt <christianshewitt@gmail.com> Date: Thu, 8 Oct 2020 14:17:38 +0000 Subject: [PATCH 1485/1494] drm/panfrost: increase readl_relaxed_poll_timeout values Amlogic SoC devices report the following errors frequently causing excessive dmesg log spam and early log rotataion, although the errors appear to be harmless as everything works fine: [ 7.202702] panfrost ffe40000.gpu: error powering up gpu L2 [ 7.203760] panfrost ffe40000.gpu: error powering up gpu shader ARM staff have advised increasing the timeout values to eliminate the errors in most normal scenarios, and testing with several different G31/G52 devices shows 20000 to be a reliable value. Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver") Suggested-by: Steven Price <steven.price@arm.com> Signed-off-by: Christian Hewitt <christianshewitt@gmail.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201008141738.13560-1-christianshewitt@gmail.com --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index e1b2a3376624a..2aae636f1cf5c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -325,13 +325,13 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) /* Just turn on everything for now */ gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present); ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO, - val, val == pfdev->features.l2_present, 100, 1000); + val, val == pfdev->features.l2_present, 100, 20000); if (ret) dev_err(pfdev->dev, "error powering up gpu L2"); gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present); ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO, - val, val == pfdev->features.shader_present, 100, 1000); + val, val == pfdev->features.shader_present, 100, 20000); if (ret) dev_err(pfdev->dev, "error powering up gpu shader"); -- GitLab From 508300a57141a120430e790b487d2dba287e23f8 Mon Sep 17 00:00:00 2001 From: Alvin Lee <alvin.lee2@amd.com> Date: Mon, 21 Sep 2020 16:23:25 -0400 Subject: [PATCH 1486/1494] drm/amd/display: Don't allow pstate if no support in blank [Why] We will hang if we report switch in VACTIVE but not in VBLANK and DPG_EN = 1 [How] Block switch in ACTIVE if not supported in BLANK Signed-off-by: Alvin Lee <alvin.lee2@amd.com> Reviewed-by: Jun Lei <Jun.Lei@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 50b7d011705d1..9e0ae18e71fac 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -5558,7 +5558,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( } } - if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) { *DRAMClockChangeSupport = dm_dram_clock_change_vactive; } else if (((mode_lib->vba.SynchronizedVBlank == true || mode_lib->vba.TotalNumberOfActiveOTG == 1 || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0)) { *DRAMClockChangeSupport = dm_dram_clock_change_vblank; -- GitLab From dd7a595af15de437c38f9bddb6637afef93659c6 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Date: Wed, 16 Sep 2020 16:49:08 -0400 Subject: [PATCH 1487/1494] drm/amd/display: Fix OPTC_DATA_FORMAT programming This should be programmed with timing rather than with odm. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Eryk Brol <eryk.brol@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 11 +++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 8 -------- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 8 -------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 2972392f9788a..800be2693faca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -288,6 +288,17 @@ void optc1_program_timing( if (optc1_is_two_pixels_per_containter(&patched_crtc_timing) || optc1->opp_count == 2) h_div = H_TIMING_DIV_BY2; + if (REG(OPTC_DATA_FORMAT_CONTROL)) { + uint32_t data_fmt = 0; + + if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + data_fmt = 1; + else if (patched_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) + data_fmt = 2; + + REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); + } + #if defined(CONFIG_DRM_AMD_DC_DCN3_0) if (optc1->tg_mask->OTG_H_TIMING_DIV_MODE != 0) { if (optc1->opp_count == 4) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index 8c16967fe0180..d8b18c515d067 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -239,7 +239,6 @@ void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) / opp_cnt; uint32_t memory_mask; - uint32_t data_fmt = 0; ASSERT(opp_cnt == 2); @@ -262,13 +261,6 @@ void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c REG_SET(OPTC_MEMORY_CONFIG, 0, OPTC_MEM_SEL, memory_mask); - if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) - data_fmt = 1; - else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - data_fmt = 2; - - REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); - REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, OPTC_NUM_OF_INPUT_SEGMENT, 1, OPTC_SEG0_SRC_SEL, opp_id[0], diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index 6d13431ff6937..b1f228fc119a3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -209,7 +209,6 @@ static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, in int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) / opp_cnt; uint32_t memory_mask = 0; - uint32_t data_fmt = 0; /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1); @@ -240,13 +239,6 @@ static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, in REG_SET(OPTC_MEMORY_CONFIG, 0, OPTC_MEM_SEL, memory_mask); - if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) - data_fmt = 1; - else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - data_fmt = 2; - - REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); - if (opp_cnt == 2) { REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, OPTC_NUM_OF_INPUT_SEGMENT, 1, -- GitLab From 305a81bfbd89a45711cdc1c16a602b3b7c4f017f Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 6 Oct 2020 09:20:47 -0400 Subject: [PATCH 1488/1494] drm/amdgpu/swsmu: fix ARC build errors We want to use the dev_* functions here rather than the pr_* variants. Switch to using dev_warn() which mirrors what we do on other asics. Fixes the following build errors on ARC: ../drivers/gpu/drm/amd/amdgpu/../powerplay/navi10_ppt.c: In function 'navi10_fill_i2c_req': ../arch/arc/include/asm/bug.h:24:2: error: implicit declaration of function 'pr_warn'; did you mean 'drm_warn'? [-Werror=implicit-function-declaration] ../drivers/gpu/drm/amd/amdgpu/../powerplay/sienna_cichlid_ppt.c: In function 'sienna_cichlid_fill_i2c_req': ../arch/arc/include/asm/bug.h:24:2: error: implicit declaration of function 'pr_warn'; did you mean 'drm_warn'? [-Werror=implicit-function-declaration] Reported-by: kernel test robot <lkp@intel.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Evan Quan <evan.quan@amd.com> Cc: Vineet Gupta <vgupta@synopsys.com> Cc: linux-snps-arc@lists.infradead.org Acked-by: Randy Dunlap <rdunlap@infradead.org> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 14 ++++++++++++-- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 3f1377f284937..8d8081c6bd385 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2336,8 +2336,6 @@ static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, { int i; - BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); - req->I2CcontrollerPort = 0; req->I2CSpeed = 2; req->SlaveAddress = address; @@ -2375,6 +2373,12 @@ static int navi10_i2c_read_data(struct i2c_adapter *control, struct smu_table_context *smu_table = &adev->smu.smu_table; struct smu_table *table = &smu_table->driver_table; + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + memset(&req, 0, sizeof(req)); navi10_fill_i2c_req(&req, false, address, numbytes, data); @@ -2411,6 +2415,12 @@ static int navi10_i2c_write_data(struct i2c_adapter *control, SwI2cRequest_t req; struct amdgpu_device *adev = to_amdgpu_device(control); + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + memset(&req, 0, sizeof(req)); navi10_fill_i2c_req(&req, true, address, numbytes, data); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 3c8732f34b1fc..c27806fd07e09 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2422,8 +2422,6 @@ static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t *req, bool write, { int i; - BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); - req->I2CcontrollerPort = 0; req->I2CSpeed = 2; req->SlaveAddress = address; @@ -2461,6 +2459,12 @@ static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control, struct smu_table_context *smu_table = &adev->smu.smu_table; struct smu_table *table = &smu_table->driver_table; + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + memset(&req, 0, sizeof(req)); sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data); @@ -2497,6 +2501,12 @@ static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control, SwI2cRequest_t req; struct amdgpu_device *adev = to_amdgpu_device(control); + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + memset(&req, 0, sizeof(req)); sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data); -- GitLab From 9142c4131a701bbb7de6262eccca1a48ace835c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher <alexander.deucher@amd.com> Date: Tue, 6 Oct 2020 09:10:24 -0400 Subject: [PATCH 1489/1494] drm/amdgpu: prevent spurious warning The default auto setting for kcq should not generate a warning. Fixes: a300de40f66b ("drm/amdgpu: introduce a new parameter to configure how many KCQ we want(v5)") Reviewed-by: Kent Russell <kent.russell@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d0a42c2b6809f..e8b41756c9f9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1370,7 +1370,9 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) amdgpu_gmc_tmz_set(adev); - if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { + if (amdgpu_num_kcq == -1) { + amdgpu_num_kcq = 8; + } else if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { amdgpu_num_kcq = 8; dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n"); } -- GitLab From 3cb9d2416ccdea14c5f1b05b5fdb15d5ebfa386b Mon Sep 17 00:00:00 2001 From: Evan Quan <evan.quan@amd.com> Date: Wed, 30 Sep 2020 11:54:01 +0800 Subject: [PATCH 1490/1494] drm/amd/pm: setup APU dpm clock table in SMU HW initialization As the dpm clock table is needed during DC HW initialization. And that (DC HW initialization) comes before smu_late_init() where current APU dpm clock table setup is performed. So, NULL pointer dereference will be triggered. By moving APU dpm clock table setup to smu_hw_init(), this can be avoided. Fixes: 02cf91c113ea ("drm/amd/powerplay: postpone operations not required for hw setup to late_init") Signed-off-by: Evan Quan <evan.quan@amd.com> Reported-by: Dirk Gouders <dirk@gouders.net> Acked-by: Nirmoy Das <nirmoy.das@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index d20a657ee081d..e41fd6ea64518 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -481,17 +481,6 @@ static int smu_late_init(void *handle) return ret; } - /* - * Set initialized values (get from vbios) to dpm tables context such as - * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each - * type of clks. - */ - ret = smu_set_default_dpm_table(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup default dpm clock tables!\n"); - return ret; - } - ret = smu_populate_umd_state_clk(smu); if (ret) { dev_err(adev->dev, "Failed to populate UMD state clocks!\n"); @@ -1030,6 +1019,17 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } + /* + * Set initialized values (get from vbios) to dpm tables context such as + * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each + * type of clks. + */ + ret = smu_set_default_dpm_table(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup default dpm clock tables!\n"); + return ret; + } + ret = smu_notify_display_change(smu); if (ret) return ret; -- GitLab From 0224b2758fb0d8a09c1a034afa6f03f27a8c7cc7 Mon Sep 17 00:00:00 2001 From: kernel test robot <lkp@intel.com> Date: Wed, 23 Sep 2020 10:28:28 +0800 Subject: [PATCH 1491/1494] drm/amdgpu: kfd_initialized can be static Fixes: c7651b73586600 ("drm/amdgpu: Fix handling of KFD initialization failures") Signed-off-by: kernel test robot <lkp@intel.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 3c0e43f548fbd..0544460653b95 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -36,7 +36,7 @@ */ uint64_t amdgpu_amdkfd_total_mem_size; -bool kfd_initialized; +static bool kfd_initialized; int amdgpu_amdkfd_init(void) { -- GitLab From b0047e53c4a5f92b9c59c5532490bbe5023d0404 Mon Sep 17 00:00:00 2001 From: "Emily.Deng" <Emily.Deng@amd.com> Date: Thu, 8 Oct 2020 08:53:59 +0800 Subject: [PATCH 1492/1494] drm/amdgpu: Remove warning for virtual_display Remove the virtual_display warning in drm_crtc_vblank_off when dev->num_crtcs is null. Reviewed-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com> Signed-off-by: Emily.Deng <Emily.Deng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 469c05fd43d54..b4d4b76538d2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -174,8 +174,10 @@ static void dce_virtual_crtc_commit(struct drm_crtc *crtc) static void dce_virtual_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); + struct drm_device *dev = crtc->dev; - drm_crtc_vblank_off(crtc); + if (dev->num_crtcs) + drm_crtc_vblank_off(crtc); amdgpu_crtc->enabled = false; amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; -- GitLab From 9c27bc97aff8bbe62b5b29ebf528291dd85d9c86 Mon Sep 17 00:00:00 2001 From: Ye Bin <yebin10@huawei.com> Date: Fri, 9 Oct 2020 15:42:18 +0800 Subject: [PATCH 1493/1494] drm/amdgpu: Fix invalid number of character '{' in amdgpu_acpi_init Fix follow warning: Checking drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c... [drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:770]: (error) Invalid number of character '{' when these macros are defined: ''. Checking drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c: CONFIG_ACPI... [drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:770]: (error) Invalid number of character '{' when these macros are defined: 'CONFIG_ACPI'. ...... Checking drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c: CONFIG_X86... [drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:770]: (error) Invalid number of character '{' when these macros are defined: 'CONFIG_X86'. Checking drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c: _X86_... [drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:770]: (error) Invalid number of character '{' when these macros are defined: '_X86_'. Checking drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c: __linux__... [drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c:770]: (error) Invalid number of character '{' when these macros are defined: '__linux__'. Fixes: 97d798b276e9 ("drm/amdgpu: simplify ATIF backlight handling") Reported-by: Hulk Robot <hulkci@huawei.com> Signed-off-by: Ye Bin <yebin10@huawei.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 4a93b880c6bfb..165b02e267b0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -806,8 +806,8 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) } adev->atif = atif; - if (atif->notifications.brightness_change) { #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + if (atif->notifications.brightness_change) { if (amdgpu_device_has_dc_support(adev)) { #if defined(CONFIG_DRM_AMD_DC) struct amdgpu_display_manager *dm = &adev->dm; -- GitLab From d3c8f2784d3266d27956659c78835ee1d1925ad2 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@crapouillou.net> Date: Mon, 12 Oct 2020 12:25:09 +0200 Subject: [PATCH 1494/1494] drm/ingenic: Fix bad revert Fix a badly reverted commit. The revert commit was cherry-picked from drm-misc-next to drm-misc-next-fixes, and in the process some unrelated code was added. Fixes: a3fb64c00d44 ("Revert "gpu/drm: ingenic: Add option to mmap GEM buffers cached"") Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20201012102509.10690-1-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index 1be1235bd546d..a3d1617d7c67e 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -440,20 +440,6 @@ void ingenic_drm_plane_config(struct device *dev, } } -static void ingenic_drm_update_palette(struct ingenic_drm *priv, - const struct drm_color_lut *lut) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(priv->dma_hwdescs->palette); i++) { - u16 color = drm_color_lut_extract(lut[i].red, 5) << 11 - | drm_color_lut_extract(lut[i].green, 6) << 5 - | drm_color_lut_extract(lut[i].blue, 5); - - priv->dma_hwdescs->palette[i] = color; - } -} - static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *oldstate) { @@ -464,8 +450,6 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, dma_addr_t addr; if (state && state->fb) { - crtc_state = state->crtc->state; - addr = drm_fb_cma_get_gem_addr(state->fb, state, 0); width = state->src_w >> 16; height = state->src_h >> 16; -- GitLab