From 8401e2edf77097bb6ac6ddac4aa7fb1aecd8e01a Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 16 Jul 2020 10:11:13 +0200 Subject: 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 Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/378239/ --- drivers/gpu/drm/radeon/radeon_ttm.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 54af06df865b..b474781a0920 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 @@ memcpy: 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 */ -- cgit v1.2.3 From 902d77f3568a9f35493e1ebcfe25ba32cd3489e0 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 16 Jul 2020 10:28:04 +0200 Subject: 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 Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/378243/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 44fa8bc49d18..0dd5e802091d 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 @@ memcpy: */ 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 */ -- cgit v1.2.3 From 4922f1bcad1a001dc6379cfe5196f3862c6107c6 Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 22 Jul 2020 09:40:11 +0800 Subject: drm/amdgpu: expand sienna chichlid reg access support Added dedicated 64bit reg read/write support Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index ea69ae76773e..74d02d270d34 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; -- cgit v1.2.3 From b16284259f2dd11e331be73829cdc9877b5f7280 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 20 Jul 2020 11:11:13 +0800 Subject: 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 Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e10f02ed3f65..bcce4c0be462 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; } -- cgit v1.2.3 From 799a2fbbbfc1caa6832c4b74294e6e86fb1ebb4e Mon Sep 17 00:00:00 2001 From: Changfeng Date: Tue, 21 Jul 2020 10:38:19 +0800 Subject: 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 Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 838a369c9ec3..f778b00e49eb 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 98face8c5fd6..f9e63f18b157 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, -- cgit v1.2.3 From 5befb6fc3b77b7c689c22ceb190e9d9087b3a961 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Jul 2020 14:24:43 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- 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(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index acdb61cfa24c..e11c21a639fd 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 394e6f56948a..993185fb7135 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 fa0bca3e1f73..07cae64d55f1 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 757fa8e83f5b..48134b9673f0 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, -- cgit v1.2.3 From f2c1b5c145c8ffe71b314d94f35383ac0d94edd0 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Jul 2020 14:57:02 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 34cbd6f6a56b..21d2c8543f85 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 e11c21a639fd..1785a0e378df 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 ec90c62078d9..e6c8526f0093 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; -- cgit v1.2.3 From 2577db91e82e9b2e68acb9f467ae29ce3aa89d52 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Jul 2020 17:39:26 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 1785a0e378df..bbecd879744a 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 993185fb7135..607a76a1ebb7 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 07cae64d55f1..777384e6fa10 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 e6c8526f0093..8f35e1315177 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 48134b9673f0..8f911efec607 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, -- cgit v1.2.3 From caa9f483ca76693159499bd45e2e635c7e47bf46 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Jul 2020 18:04:46 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index bbecd879744a..9d58c56f6cfc 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 607a76a1ebb7..76acd7f7723e 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 777384e6fa10..1f6112b7fa49 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 8f35e1315177..a1798ec25d2b 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 8f911efec607..d83912901f73 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) -- cgit v1.2.3 From db92fbc3d7f0128a2fab8a34f80c388509721eb1 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Jul 2020 18:08:24 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index a1798ec25d2b..19051ce122b1 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" -- cgit v1.2.3 From 06b668c1dc1f5ef02e3065ef9201b4710cc03d0e Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 22 Jul 2020 07:36:36 -0400 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 1ab261836983..0aa1ac1accd6 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) { -- cgit v1.2.3 From 8fe384ff2d9610f4bf4aa2a9cecb5a209a1e85a2 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Wed, 22 Jul 2020 21:27:35 +0800 Subject: 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 Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f778b00e49eb..6b03f750e63b 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; } -- cgit v1.2.3 From 2afda735c5504e1258a0ec259aceec2078d3da67 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 22 Jul 2020 14:38:13 +0200 Subject: 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 Reviewed-by: Nicholas Kazlauskas Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') 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 45886649cc53..03a60c749834 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 @@ skip_modeset: * 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: -- cgit v1.2.3 From 4031ead37239ec397fb9441555ae2d60e46dc333 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 20 Jul 2020 15:03:27 +0200 Subject: 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 Acked-by: Daniel Vetter Cc: Russell King 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(-) (limited to 'drivers/gpu/drm') diff --git a/Documentation/gpu/pl111.rst b/Documentation/gpu/pl111.rst index 9b03736d33dd..6d9a1b59a545 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 96e58fda75d8..46b0d1c4a16c 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. * -- cgit v1.2.3 From ebee9621bbc1e9f07e105121bf2d4d5debd435fd Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Tue, 21 Jul 2020 14:01:53 +0800 Subject: 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 Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 6b03f750e63b..727cb9fd4aee 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"); -- cgit v1.2.3 From 7a3ecc82f1b9e14e8e864772f03ce040835735ba Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Tue, 21 Jul 2020 13:13:39 +0800 Subject: drm/amd/powerplay: add msg map for mode1 reset Mapping Mode1Reset message for sienna_cichlid. Signed-off-by: Likun Gao Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 59da3ca2a4ca..f44fd33aeb93 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] = { -- cgit v1.2.3 From 91190db1a72dada38f1ae375c63a6b02c8d3d465 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Tue, 21 Jul 2020 16:39:45 +0800 Subject: 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 Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f44fd33aeb93..dcc5d25a7894 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] = { -- cgit v1.2.3 From 8f3b800a31f8ac6fe243649c41bcfa15c987ce20 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Thu, 23 Jul 2020 15:26:27 +0800 Subject: drm/amdgpu: update golden setting for sienna_cichlid Update golden setting for sienna_cichlid. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 61e89247faf3..8344c3b0b9b5 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), -- cgit v1.2.3 From c5a4ef3e20da16829bf417fb2093824c1bc0f82f Mon Sep 17 00:00:00 2001 From: John Clements Date: Thu, 23 Jul 2020 17:38:20 +0800 Subject: drm/amdgpu: move umc specific macros to header certain umc macros are common across umc versions Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index a615a1eb750b..183814493658 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 418cf097c918..5288617ca552 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}, -- cgit v1.2.3 From cc0e7ff8ffe01653a078824594e32be114414035 Mon Sep 17 00:00:00 2001 From: Li Heng Date: Thu, 23 Jul 2020 11:27:43 +0800 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm') 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 d94fdc52be37..d8af56a58196 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, -- cgit v1.2.3 From ccda42a4629aa6ea48b5343a131ba420d0fa5c8f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 16 Jul 2020 22:20:04 -0400 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 5f20cadee343..0a05db9b7132 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: -- cgit v1.2.3 From 23278bf54afe180967069bdc8c0f1c7a365fc63e Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 23 Jul 2020 22:04:42 +0530 Subject: 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 Signed-off-by: Bjorn Andersson Co-developed-by: Srinivas Kandagatla Signed-off-by: Srinivas Kandagatla Tested-by: John Stultz Signed-off-by: Vinod Koul Signed-off-by: Sam Ravnborg # 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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 43271c21d3fc..c7f0dacfb57a 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 d63d4b7e4347..7d7c123a95e4 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 000000000000..1009fc4ed4ed --- /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 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#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"); -- cgit v1.2.3 From 2a5c2ff5848efc77a115c53d59655aa6016237e8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 13 Apr 2020 20:30:05 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: Thierry Reding Cc: Sam Ravnborg 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(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 88493538a147..54323515ca2c 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[] = { -- cgit v1.2.3 From ddb8e853dc8507ecf9c7b4630857771da1f89752 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:10 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: Thierry Reding Cc: Sam Ravnborg 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 54323515ca2c..2c972cc8d197 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, -- cgit v1.2.3 From 9f069c6fbc72669311723262766047f577dba496 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:11 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: Thierry Reding Cc: Sam Ravnborg 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 2c972cc8d197..5cba33394083 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) -- cgit v1.2.3 From 385ca38da29c214e03f526d28346176e1b500db8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:12 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index 5ac1430fab04..a277739fab58 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 = { -- cgit v1.2.3 From 1644127f83bc72fcf2564dfbcab5802b587d964e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:13 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: kbuild test robot Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index a277739fab58..d89394bc5aa4 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); -- cgit v1.2.3 From 5b851515eff335a3b09de46a0080a64d66085875 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:17 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index d789ea2a7fb9..614b19f0f1b7 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); -- cgit v1.2.3 From 43c601a6e85e9a1c2a013006345ccf12af578c10 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:18 +0200 Subject: drm/bridge: megachips: add helper to create connector Factor out connector creation to a small helper function. Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Cc: Peter Senna Tschudin Cc: Martin Donnelly Cc: Martyn Welch Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-10-sam@ravnborg.org --- .../drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 47 +++++++++++++--------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'drivers/gpu/drm') 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 6200f12a37e6..258e0525cdcc 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; -- cgit v1.2.3 From 77860a7c892eca5a3a4b0d5e0e7065f1cd45c655 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:19 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Peter Senna Tschudin Cc: Martin Donnelly Cc: Martyn Welch Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') 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 258e0525cdcc..cf1dfbc88acf 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; } -- cgit v1.2.3 From a3d495ce5c0b25739b6e450d0810567819a96735 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:20 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Peter Senna Tschudin Cc: Martin Donnelly Cc: Martyn Welch Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-12-sam@ravnborg.org --- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') 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 cf1dfbc88acf..450dca33ea48 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); -- cgit v1.2.3 From 489ce80fa4942ba855b937eee7f621d52ccdff3f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:21 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Peter Senna Tschudin Cc: Martin Donnelly Cc: Martyn Welch Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-13-sam@ravnborg.org --- .../drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 31 ++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm') 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 450dca33ea48..f7b55dc374ac 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 @@ err: 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); -- cgit v1.2.3 From a8ef18d7dd4817cc35ab03358b3fe2aafad22d9f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 26 Jul 2020 22:33:22 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Peter Senna Tschudin Cc: Martin Donnelly Cc: Martyn Welch Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20200726203324.3722593-14-sam@ravnborg.org --- drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm') 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 f7b55dc374ac..61a24f265c7a 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); -- cgit v1.2.3 From 136d73a8c88d113b46d29c51710fe9e689e1b93e Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 27 Jul 2020 19:03:16 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index c2777b226c75..bde89e213882 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); -- cgit v1.2.3 From 731f4badcb3b47e2b0a1f4971a047fcaa552b406 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 27 Jul 2020 19:03:17 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index bde89e213882..b26c669f3e91 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); -- cgit v1.2.3 From de5e6c027ae67dd1dfcd3022593651c24b3f794a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 27 Jul 2020 19:03:18 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index b26c669f3e91..34a3e4e9f717 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)) -- cgit v1.2.3 From 4151c14cdda689fd64299736f2779668a9fb3a7d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 27 Jul 2020 19:03:19 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 438e566ce0a4..2805c8938f98 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); -- cgit v1.2.3 From 8f22c21dce5b6a8a50049275f77c771c598e5598 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 27 Jul 2020 19:03:20 +0200 Subject: 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 Reviewed-by: Laurent Pinchart Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 2805c8938f98..e941c1132598 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); -- cgit v1.2.3 From de7fe7e87a926743b05b895575d58e853f3bb515 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Thu, 4 Jun 2020 12:02:06 -0400 Subject: 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 Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index 7a51c615d22d..845306f63cdb 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); -- cgit v1.2.3 From 8214617aafa31c7d30721e3f9128737a1259a52a Mon Sep 17 00:00:00 2001 From: James Zhu Date: Wed, 3 Jun 2020 09:29:27 -0400 Subject: 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 Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index e99bef6e2354..2719ef9de3bd 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; } -- cgit v1.2.3 From 26cfd12b5e24993ac943ac37044128fe33b3ed94 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 23 Jul 2020 08:51:55 -0400 Subject: drm/amd/amdgpu: Add RLC_CGTT_MGCG_OVERRIDE to gfx 10.3 headers Signed-off-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/include/asic_reg/gc/gc_10_3_0_offset.h | 2 ++ .../amd/include/asic_reg/gc/gc_10_3_0_sh_mask.h | 25 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'drivers/gpu/drm') 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 05d1b0a5f6d2..cbaad7d83194 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 aac57f714cf1..c2d035ef3e94 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 -- cgit v1.2.3 From 0a5baee415000a3e18730ac98e19d046c3cebbe6 Mon Sep 17 00:00:00 2001 From: Laurent Morichetti Date: Mon, 6 Jul 2020 16:13:40 -0700 Subject: 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 Reviewed-by: Jay Cornwall Acked-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 930 +++++++++++---------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 2 + 2 files changed, 468 insertions(+), 464 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 577d901fdb63..7290a30f26ca 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 5b220f2a7501..4569db452160 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) -- cgit v1.2.3 From 156589f74d07fbf4083b05712a3d71f834fdf2af Mon Sep 17 00:00:00 2001 From: James Zhu Date: Thu, 23 Jul 2020 11:07:52 -0400 Subject: 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 Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index 42f1a516005e..c41e5590a701 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); -- cgit v1.2.3 From 309182389e367a806744c94a8bca75d472434015 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Thu, 23 Jul 2020 11:42:33 -0400 Subject: 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 Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 910a4a32ff78..4edd5c426e24 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; } -- cgit v1.2.3 From 6c3e0504339d0819ee0d296e857fd100d9170dfa Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 23 Jul 2020 15:36:37 +0100 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') 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 5d83e8174005..0853bc9917c7 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); -- cgit v1.2.3 From c5079f35c0ec315c944398e687821c1ceb6c6d4f Mon Sep 17 00:00:00 2001 From: Boyuan Zhang Date: Thu, 23 Jul 2020 22:34:22 -0400 Subject: drm/amdgpu: update dec ring test for VCN 3.0 Signed-off-by: Boyuan Zhang Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 4edd5c426e24..101fc4948110 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, -- cgit v1.2.3 From df9c8d1aa278c435c30a69b8f2418b4a52fcb929 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Wed, 8 Jul 2020 15:07:13 +0800 Subject: 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 Suggested-by: Andrey Grodzovsky Suggested-by: Christian König Suggested-by: Felix Kuehling Suggested-by: Lijo Lazar Suggested-by: Luben Tukov Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 40 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 2 +- drivers/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 +- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 16 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 4 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 2 +- 39 files changed, 463 insertions(+), 183 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 327a0daf4a1d..58e39429395f 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 1b865fed74ca..a0ea663ecdbc 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 @@ allocate_mem_pin_bo_failed: 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 bf927f432506..b0dcc800251e 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 744366c7ee85..275f20399373 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 feab4cc6e836..4997189d8b36 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 c7fd0c47b254..73728181b88f 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 e5a5ba869eb4..a21cf84b882c 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 @@ err: 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 a512ccbc4dea..a3b150304dae 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 8842c55d4490..d85d13f7a043 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 193ffdb957b6..3a4b31b1c4f2 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 @@ failure: /* 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 aa5b54e5a1d7..62ecac97fbd2 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 @@ end: 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 @@ skip_sched_resume: 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 7f9e50247413..73cc68ab53d0 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 78d37f92c7be..8eff0173360d 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 @@ failed_undo: 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 937029ad5271..75d37dfb51aa 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 a8c47aecd342..b9c1fce6da79 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 0a05db9b7132..2f7b0550ff16 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 8034111acd9a..a053b7af0680 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 bcce4c0be462..5680f7eafcb1 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 5f2f3faad792..605d266754f6 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 183743c5fb7b..039245c98ff8 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 1203c20491e6..5cae39d35c04 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -93,7 +93,7 @@ failed_undo: 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 f826945989c7..b2046c3a404d 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 e3a3755cb999..4e017f379eb6 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 6999eab16a72..61720cd4a1ee 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 4cfc786699c7..8341bd965202 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 8344c3b0b9b5..db9f1e89a0f8 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 33f1c4a46ebe..8d7208959c95 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 cb9d60a4e05e..e4e751f87092 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 19051ce122b1..1a78073c2f05 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 e18296dc1386..0f8e8aff9114 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 a9e722b8a458..abe64010f0d5 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 6e4f3ff4810f..c5f94bab4a01 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 5fd67e1cc2a0..fe31cbeccfe9 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 ce2bf1fb79ed..6f55172e8337 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 e0e60b0d0669..7ad1537820b5 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 40695d52e9a8..ee2258404c8f 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 03a60c749834..cf79857ece53 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 727cb9fd4aee..0eeccf3341a3 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 3b8839641770..bacbe2fa1f9a 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)); -- cgit v1.2.3 From 2c2b0d880f1b4c01f30e14242977b82fa527342d Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Thu, 23 Jul 2020 23:09:57 -0400 Subject: 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 Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- 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 + drivers/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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index a0ea663ecdbc..92790db5edc0 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 ffe149aafc39..a10507ecb750 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 4bfedaab183f..d5e790f046b4 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 7b348bf9df21..86c2c3e97944 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 #include #include +#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 a9cb218fef96..15537b2cccb5 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 0eeccf3341a3..7d9c40ad5780 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 3b9182c8c53f..f13979687b9e 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 28312d6dc187..b57b10406390 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 fd82402065e6..a9453ec01619 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 f738c3b53f4e..df6c7a43aadc 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 */ -- cgit v1.2.3 From 059ea10abdddfbfb3ec4c29c120344846745223b Mon Sep 17 00:00:00 2001 From: Changfeng Date: Fri, 24 Jul 2020 13:15:10 +0800 Subject: 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 Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 7d9c40ad5780..3b427fa099fe 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 f9e63f18b157..98face8c5fd6 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, -- cgit v1.2.3 From ea368183ae900e376b66d3f23da22acde48e385a Mon Sep 17 00:00:00 2001 From: Jay Cornwall Date: Fri, 24 Jul 2020 16:58:48 -0700 Subject: 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 Tested-by: Laurent Morichetti Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h | 178 +++++++++++---------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 7 +- 2 files changed, 95 insertions(+), 90 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 7290a30f26ca..a5cf735daf48 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 4569db452160..0f8e06a2ea8d 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: -- cgit v1.2.3 From 1df67a4ecedd34046a867afa6b29c12baf03cd25 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Sat, 25 Jul 2020 09:30:35 -0400 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 101fc4948110..63e5547cfb16 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; } -- cgit v1.2.3 From 81b41ff5d287bc2346ee7ffb544ace3557f05642 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 14 Jul 2020 14:25:39 +0800 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 2f7b0550ff16..581b2d6bea3b 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); -- cgit v1.2.3 From 6b36fa6143f6caa16bfe92c639b3dad4694b58b0 Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 27 Jul 2020 10:41:44 +0800 Subject: drm/amdgpu: add umc v8_7_0 IP headers the change introduces IP headers for unified memory controller (umc) Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- .../amd/include/asic_reg/umc/umc_8_7_0_offset.h | 33 +++++++++ .../amd/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 (limited to 'drivers/gpu/drm') 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 000000000000..3685766c4d56 --- /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 000000000000..4c5097fa0c09 --- /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 -- cgit v1.2.3 From d817f3753e6d31469358d2ae7664b616360d057f Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Fri, 24 Jul 2020 17:24:08 +0800 Subject: 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 Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- .../powerplay/inc/smu11_driver_if_sienna_cichlid.h | 21 +++++++++++++++------ drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 11 ++++++++--- 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') 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 b2232e24d82f..aa2708fccb6d 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 429f5aa8924a..9504f9954fd3 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 dcc5d25a7894..f64a1be94cb8 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; -- cgit v1.2.3 From 48ef409c25a632caeb19093b8513a17028372097 Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 27 Jul 2020 11:36:18 +0800 Subject: drm/amdgpu: add support for umc 8.7 ras functions added support for umc 8.7 error reporting and query Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- 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 (limited to 'drivers/gpu/drm') 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 000000000000..5665c77a9d58 --- /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 000000000000..d4d0468e3df5 --- /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 -- cgit v1.2.3 From 0eb52d81565588797d031d50f09fe871112f1138 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 27 Jul 2020 09:08:22 +0800 Subject: 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 Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 3b427fa099fe..55463e7a11e2 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; -- cgit v1.2.3 From a00d8fd405ed7c071b2e3fa12a2e03d0a0d2d6fa Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 6 Jul 2020 10:54:37 -0400 Subject: 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 Reviewed-by: Eric Bernstein Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 49 +++------------------- .../gpu/drm/amd/display/dc/dml/display_mode_vba.c | 14 +------ .../gpu/drm/amd/display/dc/dml/display_mode_vba.h | 7 +--- 3 files changed, 7 insertions(+), 63 deletions(-) (limited to 'drivers/gpu/drm') 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 968a89bbcf24..2a5e7175926a 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 7916a7ea9336..b0064087b9bb 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 756d8eb1221c..21e5111ea7a0 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, -- cgit v1.2.3 From 91b2e45be439e098f4f2e17be1c87570e5a42928 Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Tue, 16 Jun 2020 16:24:11 -0400 Subject: 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 Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- 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(-) (limited to 'drivers/gpu/drm') 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 998f729976bf..1c177c2ad1dc 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 da0897fe3b54..a643927e272b 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 ba50214d6c32..79b640e202eb 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 5915994f9eb8..f520e13aee4c 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; -- cgit v1.2.3 From f92e25e56137cb410c89dd5d69aed47849b3236c Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Tue, 16 Jun 2020 16:29:19 -0400 Subject: 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 Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm') 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 1c177c2ad1dc..e5a6d9115949 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}, -- cgit v1.2.3 From be6ccdf861de048833b2000d80db800ab4f8d81b Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Tue, 14 Jul 2020 15:06:40 -0400 Subject: 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 Reviewed-by: Jun Lei Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') 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 d8af56a58196..b0e9b0509568 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); } } -- cgit v1.2.3 From b246f90a09706ecf755c40006fc8b4c07cdfc314 Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Wed, 15 Jul 2020 11:21:43 +0800 Subject: 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 Reviewed-by: Aric Cyr Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 50 ++++++++++++++++++++++ .../drm/amd/display/include/link_service_types.h | 2 + 2 files changed, 52 insertions(+) (limited to 'drivers/gpu/drm') 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 5cb7b834e459..1a3dbed3becb 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 4869d4562e4d..550f46e9b95f 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 { -- cgit v1.2.3 From 94bc373b7f1669b0fa227051f6080a6988d9d4ea Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 21 Jul 2020 13:59:52 -0400 Subject: 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 Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') 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 cf79857ece53..3100c59d1707 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: -- cgit v1.2.3 From 1ee1290363b57361ebf6addbfbbb57dabc4c7a36 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 24 Jul 2020 16:36:07 -0400 Subject: drm/amd/display: Use proper abm/backlight functions for DCN3 Use DCN21 functions instead of DCE110 Signed-off-by: Bhawanpreet Lakha Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') 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 1b354c219d0a..9afee7160490 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 = { -- cgit v1.2.3 From f5cd85555bf2ced9725a1eb5cd68f2c2096e283a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 27 Jul 2020 12:34:36 +0200 Subject: 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 Signed-off-by: Christophe JAILLET Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index f178ba321715..d099fffbc5be 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; } -- cgit v1.2.3 From 4c0d0bcb224f968510aff5eddef2b294e5aa4b8b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 27 Jul 2020 12:34:21 +0200 Subject: 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 Signed-off-by: Christophe JAILLET Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index d099fffbc5be..3808a753127b 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; } -- cgit v1.2.3 From 9b66d6600e6a060333712c54af90631eb6276d93 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Jul 2020 16:39:40 +0300 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index be4b678d0e60..5c23c44c33bd 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; -- cgit v1.2.3 From 6863660d72e4fde650658acc10e4558ec1a277fb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 22 Jun 2020 17:06:14 -0400 Subject: 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 --- .../gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h | 76 +++++++++++++++ .../drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h | 104 +++++++++++++++++++++ 2 files changed, 180 insertions(+) (limited to 'drivers/gpu/drm') 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 ae798f768853..9de01ae574c0 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 abe05bc80752..41c4a46ce357 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 -- cgit v1.2.3 From f233c09842bc91a8f7f5dfadc6de77f52273befc Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sat, 11 Jul 2020 21:28:48 +0200 Subject: 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 Signed-off-by: Alex Deucher Signed-off-by: Mauro Rossi --- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 40 +++++++++++++++++++++++ drivers/gpu/drm/amd/display/include/dal_types.h | 3 ++ 2 files changed, 43 insertions(+) (limited to 'drivers/gpu/drm') 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 abeb58d544b1..b267987aed06 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 b67c9fa6b9cd..8aaa3af69202 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, -- cgit v1.2.3 From 7c15fd86aaec3e602e140c242369df2baddc865e Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sat, 11 Jul 2020 21:43:25 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/Makefile | 4 + drivers/gpu/drm/amd/display/dc/dce60/Makefile | 34 + .../drm/amd/display/dc/dce60/dce60_hw_sequencer.c | 54 + .../drm/amd/display/dc/dce60/dce60_hw_sequencer.h | 37 + .../gpu/drm/amd/display/dc/dce60/dce60_resource.c | 1532 ++++++++++++++++++++ .../gpu/drm/amd/display/dc/dce60/dce60_resource.h | 47 + .../amd/display/dc/dce60/dce60_timing_generator.c | 247 ++++ .../amd/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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index e0f4f1be1618..047b1e2dd8f1 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 000000000000..7036c3bd0f87 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/Makefile @@ -0,0 +1,34 @@ +# +# Copyright 2020 Mauro Rossi +# +# 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 000000000000..e30e3510ec4a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..f3b2d8b60d5b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..18d535c2cc28 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c @@ -0,0 +1,1532 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 + +#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 000000000000..5d653a76b0b0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.h @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..eb9705e9d40a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.c @@ -0,0 +1,247 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..81d831233cc5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_timing_generator.h @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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__ */ -- cgit v1.2.3 From 683b59504d4ecec3251a23fdac7e8775385a18c5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sun, 26 May 2019 17:31:42 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/gpu/drm') 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 7b5f90ebb133..ca26714c800e 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); -- cgit v1.2.3 From c4a54f70a6afd1a91072ef06cb083221ff189cca Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 5 Oct 2018 22:53:25 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/Makefile | 9 + .../drm/amd/display/dc/bios/command_table_helper.c | 8 + .../drm/amd/display/dc/bios/command_table_helper.h | 3 + .../amd/display/dc/bios/command_table_helper2.c | 8 + .../amd/display/dc/bios/command_table_helper2.h | 3 + .../dc/bios/dce60/command_table_helper_dce60.c | 354 +++++++++++++++++++++ .../dc/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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/dc/bios/Makefile b/drivers/gpu/drm/amd/display/dc/bios/Makefile index 239e86bbec5a..ed6b5e9763f6 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 253bbb1eea60..48b4ef03fc8f 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 4c3789df253d..dfd30aaf4032 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 21ff6b686f5f..74c498b6774d 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 785fcb20a1b9..66e0a3e73768 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 000000000000..710221b4f5c5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.c @@ -0,0 +1,354 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..f733be553d5a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/bios/dce60/command_table_helper_dce60.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 -- cgit v1.2.3 From b168930d68a95d7696773007b426a0f60a9c3fd7 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sun, 29 Sep 2019 18:41:38 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 12 + .../amd/display/dc/gpio/dce60/hw_factory_dce60.c | 175 +++++++++ .../amd/display/dc/gpio/dce60/hw_factory_dce60.h | 32 ++ .../amd/display/dc/gpio/dce60/hw_translate_dce60.c | 411 +++++++++++++++++++++ .../amd/display/dc/gpio/dce60/hw_translate_dce60.h | 32 ++ drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 10 + drivers/gpu/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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index 0f2f4508e564..74c0943ed644 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 000000000000..cc69acd8ada7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.c @@ -0,0 +1,175 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..1fd54ff8979c --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_factory_dce60.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..255df31ec577 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.c @@ -0,0 +1,411 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..1e811f35cec7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/gpio/dce60/hw_translate_dce60.h @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 e5cfe28bc7bf..6fc8a6e9dc15 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 efea7cb0f17c..3a93c945e57d 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: -- cgit v1.2.3 From 61bf32937bdd05fdf74292460d56936d63beaba5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sat, 8 Feb 2020 10:41:01 +0100 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/irq/Makefile | 11 + .../amd/display/dc/irq/dce60/irq_service_dce60.c | 395 +++++++++++++++++++++ .../amd/display/dc/irq/dce60/irq_service_dce60.h | 40 +++ drivers/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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 3352b79fb1cb..405c25322607 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 000000000000..524481885fd0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.c @@ -0,0 +1,395 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 + +#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 000000000000..294db29e8115 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dce60/irq_service_dce60.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 33053b9fe6bd..6bf27bde8724 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" -- cgit v1.2.3 From 55e56389bdecc4f08524a6ae81940b13f986e125 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sun, 26 May 2019 17:33:45 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 114 ++++++++++++++++++++++ 1 file changed, 114 insertions(+) (limited to 'drivers/gpu/drm') 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 3100c59d1707..149da893b714 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; -- cgit v1.2.3 From 3ecb3b794e2c1793443b72a968cb09d829c01a10 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sat, 11 Jul 2020 22:59:07 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 11 ++ drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 6 + .../amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c | 174 +++++++++++++++++++++ .../amd/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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 6874276bb2a1..52b1ce775a1e 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 6a345d43028c..efb909ef7a0f 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 000000000000..c11c6b3a787d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -0,0 +1,174 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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 000000000000..eca3e5168089 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h @@ -0,0 +1,36 @@ +/* + * Copyright 2020 Mauro Rossi + * + * 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_ */ -- cgit v1.2.3 From f17f90f4fe43a4ff157a15d5be1986b2bdfe2aed Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 19 Jun 2020 00:12:05 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm') 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 18d535c2cc28..534db1c4eaa6 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; /************************************************* -- cgit v1.2.3 From 2a39b1f16b526528132685e308fe83a64bafb263 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:00:51 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_audio.c | 131 +++++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_audio.h | 23 +++++ 2 files changed, 154 insertions(+) (limited to 'drivers/gpu/drm') 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 408046579712..2a2a0fdb9253 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 1392fab0860b..5622d5e32d81 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); -- cgit v1.2.3 From eab5a79984b1736a5b2b5b0713e8e179df7f8442 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:05:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/gpu/drm') 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 5e044c2d3d6d..93e7f34d4775 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), \ -- cgit v1.2.3 From ff0649f846395690aadc3c43c2c85995e32e8322 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:10:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- 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(+) (limited to 'drivers/gpu/drm') 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 e1c5839a80dc..4202fadb2c0e 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 66b88d6ba398..70bbc1311327 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); -- cgit v1.2.3 From 89571d7c31011abd5673ef22f0da72ecaef7b7a5 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:15:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- 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(+) (limited to 'drivers/gpu/drm') 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 ce30dbf579d4..80569a2734eb 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 ca04e97d44c3..0028d4bdd81b 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_ */ -- cgit v1.2.3 From c1a64ebd4d13da1ddc4ec7ddc14a0c86a281a7f8 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:20:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 369 +++++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 38 +++ 2 files changed, 407 insertions(+) (limited to 'drivers/gpu/drm') 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 8d8c84c81b34..b409f6b2bfd8 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 384389f0e2c3..40ea2220330c 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, -- cgit v1.2.3 From b91f056fb5e192411635ce9e9e81f9f741ea1f5f Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:25:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c | 176 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h | 103 ++++++++++++ 2 files changed, 278 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm') 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 51481e922eb9..79a6f261a0da 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 d15b0d7f47fc..23db5c72f07e 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, -- cgit v1.2.3 From d85a1e536ab8cbc9f96f7a0554703887d603c401 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:30:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- 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(+) (limited to 'drivers/gpu/drm') 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 51081d9ae3fb..e459ae65aaf7 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 , 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 2ab0147cbd9d..4d484ef60f35 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); -- cgit v1.2.3 From b70aaf5586f214d610ac21606128c0c992db5d9c Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:35:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 268 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 150 ++++++++++++ 2 files changed, 418 insertions(+) (limited to 'drivers/gpu/drm') 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 ab63d0d0304c..3303d01c1aae 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 948281d8b6af..95b28dadc8c5 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, -- cgit v1.2.3 From 102b2f587ac814afd9ef396dd6fccb99d7f4d649 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Thu, 16 Jul 2020 00:54:08 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_transform.c | 72 ++++++++++++++++++++-- drivers/gpu/drm/amd/display/dc/dce/dce_transform.h | 28 +++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm') 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 3303d01c1aae..2a32b66959ba 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 95b28dadc8c5..cbce194ec7b8 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 */ -- cgit v1.2.3 From 167d74fd7dfc18158c116c84565dda24b40473c6 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:40:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dce60/dce60_hw_sequencer.c | 381 ++++++++++++++++++++- 1 file changed, 379 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') 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 e30e3510ec4a..9d8797ac0c98 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; } -- cgit v1.2.3 From 1bd26c7db150a98ebc13e417341bc4dcf67c0b0d Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sun, 12 Jul 2020 22:54:13 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm') 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 9d8797ac0c98..920c7ae29d53 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; -- cgit v1.2.3 From 9caf2a1f4e8aeff31124c807a529375451a56899 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 10 Jul 2020 20:45:01 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- .../amd/display/dc/dce60/dce60_timing_generator.c | 55 +++++++++++++++------- .../drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 11 +++++ 2 files changed, 48 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm') 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 eb9705e9d40a..fc1af0ff0ca4 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 4e6e18bbef5d..ca9eedb643f2 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) -- cgit v1.2.3 From 75b4766bad05c4db6e9e568af95712321f57d02e Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Tue, 7 Jul 2020 17:24:56 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dce60/dce60_resource.c | 89 ++++++++++------------ 1 file changed, 42 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm') 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 534db1c4eaa6..5a5a9cb77acb 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 -#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; } -- cgit v1.2.3 From f784112f0126a8d9cd4d92878dc76796b5eba11e Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Thu, 16 Jul 2020 20:54:28 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') 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 149da893b714..5109ee032b72 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); -- cgit v1.2.3 From 7427a7a0b3b8f66ea45472a9a37b79689ed8c3b3 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Fri, 3 Jul 2020 16:29:39 +0200 Subject: 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 Reviewed-by: Christian König Signed-off-by: Christian König Link: https://patchwork.freedesktop.org/patch/374724/ --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 126e74758a34..5c4263335cba 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) -- cgit v1.2.3 From d59bc6324208e427d141826d26408b193d522244 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 23 Jul 2020 10:58:12 +0200 Subject: 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 Reviewed-by: Felix Kuehling Tested-by: Alex Sierra Link: https://patchwork.freedesktop.org/patch/379039/ --- drivers/gpu/drm/ttm/ttm_bo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 0768a054a916..469aa93ea317 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; -- cgit v1.2.3 From 64200c468fb0a3ab88033f6b90ea4a576ae6a1e0 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Fri, 5 Oct 2018 00:00:17 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/si.c | 10 ++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 62ecac97fbd2..638c2cc426c1 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 1b449291f068..5a112c7a35ca 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); -- cgit v1.2.3 From 5963cdde1acf6b81c62bf6d3bdae723139bf8138 Mon Sep 17 00:00:00 2001 From: Mauro Rossi Date: Sun, 14 Oct 2018 20:51:29 +0200 Subject: 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 Signed-off-by: Mauro Rossi Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 34ae4f3a32f4..77569097a480 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 -- cgit v1.2.3 From 6cd3c6798aac0d1a53d1426e1cfa0432cce51486 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jul 2020 10:35:07 -0400 Subject: 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 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 92 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 5a112c7a35ca..e330884edd19 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) -- cgit v1.2.3 From fcf863ec07688a5242b75b032bad3f0e3581d68d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:33 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 508764fccd27..79cd2511a86b 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From c42001e357f7de11e882f54461be27757a7fe51a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:34 +0300 Subject: 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 Reviewed-by: Emil Velikov Reviewed-by: Stefan Agner Signed-off-by: Stefan Agner 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 (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 0dca8f27169e..e43b326e9147 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 ff6e358088fa..811584e54ad1 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 79cd2511a86b..689f50b1ef68 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -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 0b65b5194a9c..0e3e5a63bbf9 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 9eca1605d11d..000000000000 --- 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 - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} -- cgit v1.2.3 From 8c6619ff22113666b112cace7e4e8d872e09dff3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:35 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 932d7ea08fd5..713d8f830135 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 -- cgit v1.2.3 From 92000371c8294136accc2997cba89dff8c0bc9f5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:36 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 713d8f830135..78e6cb754712 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__ */ -- cgit v1.2.3 From 8a460068494a536e3d544dc4778d3c9d4081c504 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:37 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index b69ace8bf526..8b6339316929 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 78e6cb754712..8ebb52bb1b46 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__ */ -- cgit v1.2.3 From f14fec8481ce64e9c544770d8977e8c8efab4a11 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:38 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 8b6339316929..be60c4021e2f 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; -- cgit v1.2.3 From 7865cd5aae2267b8b1efd1019279b9a6e1a11941 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:39 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index be60c4021e2f..722bd9b4f5f9 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) -- cgit v1.2.3 From eb28c5cee2a8c44f80b0a35b8bc8ba2924fcb87d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:40 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 722bd9b4f5f9..aef72adabf41 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) -- cgit v1.2.3 From f16a008921aa13b7012b9f8cf48c44130e6e8a35 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 27 Jul 2020 05:06:41 +0300 Subject: 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 Reviewed-by: Stefan Agner Reviewed-by: Emil Velikov Signed-off-by: Stefan Agner 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(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index aef72adabf41..c4f1575b4210 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -10,19 +10,13 @@ #include #include -#include -#include +#include -#include